diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e45ce91 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +docs/javascripts/* linguist-vendored +eslint.config.mjs linguist-generated +package-lock.json linguist-generated +package.json linguist-generated diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..42008f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug Report +about: Report an issue or bug in the documentation +title: "[BUG] " +labels: bug +assignees: "" +--- + +## Bug Report + +**Document Title:** + +**Current URL/Location:** + +**Description of Issue:** (What is the issue? Typo, broken link, +incorrect information, etc.) + +**Expected Behavior:** (What should the correct information be?) + +--- + +### Additional Information + +Include any other relevant information, screenshots, +or logs that might help in resolving the issue. + +--- + +### Checklist + +- [ ] I have searched the existing issues for related topics. +- [ ] I have provided all necessary information to reproduce the issue. diff --git a/.github/ISSUE_TEMPLATE/epic.md b/.github/ISSUE_TEMPLATE/epic.md new file mode 100644 index 0000000..22ff732 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/epic.md @@ -0,0 +1,46 @@ +--- +name: Epic +about: A parent issue that tracks multiple sub-issues +title: "[EPIC] " +labels: epic +assignees: "" +--- + +## Epic Overview + +**Description:** +Provide a clear and concise description of the overall goal of this epic. +Include any relevant background information. + +--- + +### Sub-Issues + +List the sub-issues that are part of this epic. +These should be created as separate issues and linked here. + +- [ ] #SubIssue1 +- [ ] #SubIssue2 +- [ ] #SubIssue3 + +--- + +### Success Criteria + +Describe what success looks like for this epic. +Include any measurable outcomes or key results. + +--- + +### Additional Information + +Include any other relevant information, screenshots, +or notes that might help in tracking and completing this epic. + +--- + +### Checklist + +- [ ] All sub-issues are created and linked +- [ ] Description and success criteria are clear +- [ ] Epic is assigned to the appropriate milestone diff --git a/.github/ISSUE_TEMPLATE/new_document.md b/.github/ISSUE_TEMPLATE/new_document.md new file mode 100644 index 0000000..7a2f699 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_document.md @@ -0,0 +1,35 @@ +--- +name: New Document +about: Suggest a new document to be added to the documentation +title: "[NEW DOC] " +labels: documentation +assignees: "" +--- + +## New Document Request + +**Title:** + +**Purpose:** (Why is this document needed? What problem does it solve?) + +**Target Audience:** (Who is the intended reader? Beginners, +advanced users, developers, etc.) + +**Key Sections:** (List out the main sections or headings that should be included) + +**References:** (Any external resources, links, +or documents that should be referenced or included) + +--- + +### Additional Information + +Include any other relevant information, screenshots, +or notes that might help in creating this new document. + +--- + +### Checklist + +- [ ] I have searched the existing issues for related topics. +- [ ] I have outlined the main sections and purpose. diff --git a/.github/ISSUE_TEMPLATE/question_clarification.md b/.github/ISSUE_TEMPLATE/question_clarification.md new file mode 100644 index 0000000..b2b33c8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question_clarification.md @@ -0,0 +1,29 @@ +--- +name: Question/Clarification +about: Ask a question or request a clarification about the documentation +title: "[QUESTION] " +labels: question +assignees: "" +--- + +## Question/Clarification + +**Document Title:** + +**Current URL/Location:** + +**Specific Question:** (What is your question or what needs to be clarified?) + +--- + +### Additional Information + +Include any other relevant information that might help in addressing your +question or clarification. + +--- + +### Checklist + +- [ ] I have searched the existing issues for related topics. +- [ ] I have provided all necessary information to understand the request. diff --git a/.github/ISSUE_TEMPLATE/update_document.md b/.github/ISSUE_TEMPLATE/update_document.md new file mode 100644 index 0000000..b8efcf0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/update_document.md @@ -0,0 +1,32 @@ +--- +name: Update Document +about: Suggest an update to an existing document +title: "[UPDATE DOC] " +labels: documentation +assignees: "" +--- + +## Update Document Request + +**Document Title:** + +**Current URL/Location:** + +**Changes Required:** (Describe what needs to be added, updated, or removed) + +**Reason for Update:** (Why is this update needed? Is it outdated, incorrect, +or missing information?) + +--- + +### Additional Information + +Include any other relevant information, screenshots, +or notes that might help in updating this document. + +--- + +### Checklist + +- [ ] I have searched the existing issues for related topics. +- [ ] The changes reflect the current state of the project. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..869b1b6 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,61 @@ +# Documentation Pull Request Template + +## Description + +Provide a brief description of the changes in this pull request. +Explain the purpose and scope of the document, the problem it solves, +or the improvement it provides. + +--- + +## Type of Change + +- [ ] New Document +- [ ] Update to Existing Document +- [ ] Bug Fix +- [ ] Question/clarification +- [ ] Other (please describe): + +--- + +## Related Issues + +Link any related issues or pull requests here. +Use the format `Fixes #issue-number` to automatically close the related issue +when this pull request is merged. + +--- + +## Checklist + +- [ ] I have reviewed the existing documentation to avoid duplication. +- [ ] The new or updated document includes clear and concise information. +- [ ] All relevant sections (e.g., introduction, usage examples, references) + are included. +- [ ] The document follows the project's style guide and formatting rules. +- [ ] I have included any necessary references or external resources. +- [ ] Spellcheck and grammar check have been performed. +- [ ] (For updates) I have verified that the changes reflect the current state + of the project. + +--- + +## Additional Information + +Include any other relevant information, screenshots, +or notes that might help in reviewing this pull request. + +--- + +## Reviewer Checklist + +- [ ] The purpose and scope of the document are clear. +- [ ] The document is easy to understand and follow. +- [ ] There are no typos or grammatical errors. +- [ ] All necessary sections are included and well-structured. +- [ ] The document is consistent with the project's style guide. +- [ ] Any referenced links or resources are valid and appropriate. + +--- + +**Thank you for contributing to our documentation!** diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8ac6b8c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..3956d21 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,46 @@ +name: Lint + +on: [pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + version: "9" + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Check formatting + run: pnpm format:check + + - name: Run ESLint + run: pnpm lint:check + + - name: Run Spellcheck + run: pnpm spell:check diff --git a/.github/workflows/mkdocs.yml b/.github/workflows/mkdocs.yml new file mode 100644 index 0000000..b6e823a --- /dev/null +++ b/.github/workflows/mkdocs.yml @@ -0,0 +1,61 @@ +name: mkdocs + +on: + push: + branches: + - master + - main + pull_request: + +permissions: + contents: write + +jobs: + build: + name: Build documentation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Install dependencies + run: pip install mkdocs-material + + - name: Build documentation + run: mkdocs build --strict + + - name: Upload site as artifact + if: ${{ github.event_name == 'pull_request' }} + uses: actions/upload-artifact@v4 + with: + name: mkdocs-site-preview + path: site # Upload the `site` directory generated by MkDocs + + deploy: + name: Deploy GitHub Pages + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Install dependencies + run: pip install mkdocs-material + + - name: Deploy GitHub Pages + run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4cfb3f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# mkdocs-material build +site/ +.cache +__pycache__ + +# IDE files +.vscode/ +.idea/ + +# JavaScript build artifacts +node_modules/ +.pnpm-store/ + +# macOS files +.DS_Store diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..eeeb7be --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +pnpm-lock.yaml \ No newline at end of file diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..10d1f2c --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,10 @@ +# number of characters per line +printWidth: 80 +# convert tabs to spaces +useTabs: false +# number of spaces per tab +tabWidth: 2 +# do not wrap prose in markdown based on `printWidth` +proseWrap: preserve +# use double quotes +singleQuote: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d72c7f7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "yzhang.markdown-all-in-one", + "streetsidesoftware.code-spell-checker", + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4a8e89e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,20 @@ +{ + "eslint.codeActionsOnSave.mode": "problems", + "eslint.format.enable": false, + "eslint.run": "onSave", + "eslint.probe": ["html", "json", "markdown"], + "prettier.configPath": ".prettierrc.yaml", + "prettier.requireConfig": true, + "prettier.prettierPath": "./node_modules/prettier", + "yaml.schemas": { + "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" + }, + "yaml.customTags": [ + "!ENV scalar", + "!ENV sequence", + "!relative scalar", + "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", + "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", + "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..51d0ad4 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# Strata - Public Docs + +This repository contains all private devnet documentation related to [Strata](https://stratabtc.org). + +## Getting Started + +1. Clone this repository: + + ```bash + git clone https://github.com/alpenlabs/docs.git + ``` + +2. Install required dependencies. + + ```bash + wget -qO- https://get.pnpm.io/install.sh | sh - # install pnpm + pnpm install + ``` + +3. Install `mkdocs-material`: + + ```bash + pip install mkdocs-material + ``` + +> [!NOTE] +> Alternatively you can use the `mkdocs-material` Docker image: +> +> ```bash +> docker pull squidfunk/mkdocs-material +> ``` + +## Making Changes + +You can add your changes by editing/creating the markdown files in the +appropriate location in the repository. Make sure that you adhere to our +[style guide](./style-guide.md). + +To preview your changes, run the following command: + +```bash +mkdocs serve +``` + +> [!NOTE] +> If you are using the Docker image, you can run the following command: +> +> ```bash +> docker run --rm -u "$(id -u):$(id -g)" -v "$PWD":/docs -p 8000:8000 squidfunk/mkdocs-material +> ``` + +Your preview should be available at . + +## Contributing + +Before you push any changes or create a PR, please run the following: + +```bash +# check that everything is formatted correctly +pnpm format:check + +# check that there are no spelling errors +pnpm spell:check + +# check that all documents follow the markdownlint rules +pnpm lint:check +``` + +Errors in any of the above commands will cause the CI to fail. +Formatting and lint issues can be fixed with the following: + +```bash +pnpm format:fix + +pnpm lint:fix +``` + +It is best to let your editor help you with these things so that you are not +caught by surprise when the CI checks run. This repo includes settings for +`vscode` that will help you get feedback from your editor as early as possible. diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..dbcda78 --- /dev/null +++ b/cspell.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", + "version": "0.2", + "dictionaryDefinitions": [ + { + "name": "project-words", + "path": "./project-words.txt", + "addWords": true + } + ], + "dictionaries": ["project-words"], + "ignorePaths": [ + "node_modules", + "/project-words.txt", + "*.json", + "pnpm-lock.yaml" + ] +} diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png new file mode 100644 index 0000000..f29686d Binary files /dev/null and b/docs/assets/favicon.png differ diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000..b893ee4 Binary files /dev/null and b/docs/assets/logo.png differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..638c547 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,70 @@ +# Introduction to Strata + +!!! note + + Strata's devnet will be launching soon. + To build on devnet, + please apply using the devnet form on our [website](https://stratabtc.org/). + +Strata gives developers the freedom to program nearly +any locking conditions for BTC imaginable, +limited only by the Strata block size and gas limits. +This enables developers to create new kinds of applications for BTC +with features such as: + +- **New signature types**, "provide a valid `P-256` signature to authorize a transfer" + +- **Vaults**, "transfers must wait `N` days after being initiated to be effectuated, + and can be cancelled in the mean time" + +- **Transfer limits**, "only `X%` or less of the current balance + can be immediately with a single signature, + larger amounts can only be transferred with multiple signatures" + +- **Strong privacy**, "transaction details are end-to-end encrypted + and verified using a zero-knowledge proof" + +- **Economically secured zero-confirmation payments**, + "if a double-spend from this sender is reported, + the reporter gets to claim the sender's full wallet balance" + +- **Financial transactions**, + "if enough BTC is locked as collateral to maintain up + to `X%` loan-to-value ratio, + then up to N of this other asset can be borrowed" + +... and many more possibilities. + +Technically speaking, +**Strata is a work-in-progress EVM-compatible validity rollup on bitcoin**. +Let's break down what this means: + +- **EVM-compatible**: The Strata block producer runs a client that is based on + [Reth](https://github.com/paradigmxyz/reth), + an Ethereum execution client. + So far, no changes have been made that affect compatibility with the EVM spec. + If you can deploy a smart contract to Ethereum, + you can deploy it to Strata with no changes. + +- **Validity rollup**: Every Strata state transition is proven to + be valid using cryptographic validity proofs, + which clients can use for fast, low-cost verification. + +- **On bitcoin**: Strata uses bitcoin for consensus and data availability. + When a Strata block gets confirmed on bitcoin, + the only way to reorganize this block is to reorganize + the bitcoin block that the Strata block was confirmed in. + +You can find detailed technical information in the +[How Strata works](technical/specs.md) +section of this documentation. + +!!! note + + During the devnet phase, + Strata will be running on a private bitcoin signet, + and will use signet blocks to store state commitments + rather than the complete Strata state data, + making Strata function more like a commit chain than a rollup. + Support for full onchain data availability + and for running Strata on bitcoin mainnet are planned for future releases. diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js new file mode 100644 index 0000000..fe408ae --- /dev/null +++ b/docs/javascripts/mathjax.js @@ -0,0 +1,20 @@ +window.MathJax = { + tex: { + tags: "ams", // adds label capability + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true, + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex", + }, +}; + +document$.subscribe(() => { + MathJax.startup.output.clearCache(); + MathJax.typesetClear(); + MathJax.texReset(); + MathJax.typesetPromise(); +}); diff --git a/docs/security.txt b/docs/security.txt new file mode 100644 index 0000000..fe7b243 --- /dev/null +++ b/docs/security.txt @@ -0,0 +1,3 @@ +Contact: https://github.com/alpenlabs/strata/issues +Expires: 2026-01-01T04:59:00.000Z +Preferred-Languages: en diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 0000000..bf1c94b --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,16 @@ +:root { + --md-accent-fg-color: #bc512f; + --md-accent-fg-color--light: #bc512f; + --md-accent-fg-color--dark: #bc512f; + --md-accent-bg-color: #bc512f; + --md-accent-bg-color--light: #bc512f; + --md-accent-bg-color--dark: #bc512f; +} + +.red { + color: red; +} + +.green { + color: green; +} diff --git a/docs/technical/architecture.md b/docs/technical/architecture.md new file mode 100644 index 0000000..1c2b0bf --- /dev/null +++ b/docs/technical/architecture.md @@ -0,0 +1,6 @@ +# System Architecture + +- System architecture diagram, showing the major components (each labelled with + a number) and how they interact +- Based on the component labels on the diagram, write a numbered list of + components and an explanation about what each one does diff --git a/docs/technical/bitcoin-bridge.md b/docs/technical/bitcoin-bridge.md new file mode 100644 index 0000000..1724fdc --- /dev/null +++ b/docs/technical/bitcoin-bridge.md @@ -0,0 +1,147 @@ +# Bitcoin Bridge + +The Bitcoin bridge is a two-way peg program between Bitcoin and Alpen Labs' rollup. +It is a federated bridge, where a group of operators +sign transactions to move funds into the rollup, +whereas the user can withdraw funds from the rollup with the guarantee +that at least one operator is honest. + +!!! info + + The current bridge design assumes an N-of-N cooperation amongst + the bridge operators. + Future designs will enhance the security model of the bridge operation. + +The deposit flow is composed of a Deposit Request Transaction (DRT) +which is fulfilled by the bridge federation with a Deposit Transaction (DT). +The user should provide an Execution Layer (EL) address to receive the funds +in the rollup. + +The withdrawal request is assigned to an operator that fulfills it +with the Bridge's funds with a Withdrawal Transaction (WT), +and then collects the signatures from the bridge federation. + +!!! note + + Deposits and withdrawals are allowed in a denomination of $D$ BTC where + $D = 10 \ \text{BTC}$ is a value predefined by the bridge federation. + +!!! info + + All the multisigs in the deposit and withdraw follows + the [MuSig2](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki) + protocol, where signatures are aggregated into a single signature + that validates all $n$ participants' partial signatures. + +## Deposit + +The deposit process is initiated by the user, +who sends 10[^fees] BTC to a P2TR address, where: + +[^fees]: The user must pay the Bitcoin network fees for both the Deposit Request and Deposit Transactions. + +1. The key path spend is unspendable, following + [BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs) + with a "NUMS"[^nums] point added to the random scalar + $r = \text{0x82758434e13488368e0781c4a94019d3d6722f854d26c15d2d157acd1f464723}$. + +[^nums]: + "Nothing Up My Sleeve" (NUMS) point, + i.e., a point with unknown discrete logarithm, chosen as $H = lift_x(G)$ + where $G$ is the secp256k1 generator point, + as per [BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs). + An unspendable pubkey is a point on the curve whose discrete log + is not known with respect to the generator point $G$. + This can be verified by revealing the random scalar $r$ + used to generate the pubkey by shifting the NUMS point. + +1. The script path spend has two paths: + 1. "deposit path", an $n$-of-$n$ multisig path, + where $n$ is the number of operators in the bridge. + 1. "take back" path, + which allows the user to take back their funds if the bridge fails to + move funds from the Deposit Request Transaction (DRT) + into the bridge address within a two-week period, + i.e. it is time-locked and the user provides a signature to spend it. + +This transaction has some metadata attached to it, in the form of an `OP_RETURN` +output, that can be up to 80-bytes long (according to Bitcoin consensus rules); +and is composed of the following data: + +1. Magic bytes in the form `OP_PUSHBYTES_11 `. + These take $1 + 11 = 12$ bytes and are used to identify the bridge. +1. "Take back" TapLeaf hash as `OP_PUSHBYTES_32 `. + These take $1 + 32 = 33$ bytes and are used to validate the + Deposit Request Transaction (DRT), + while also necessary for the control block required + to spend the P2TR output via the $n$-of-$n$ Tapscript. +1. Execution layer (EL) Address as `OP_PUSHBYTES_20 `. + The Execution Layer (EL) address is the address in the rollup where + the user wants to receive the funds (sBTC) in the rollup. + It is a 20-byte Ethereum Virtual Machine (EVM) address. + This is $1 + 20 = 21$ bytes long. + +The bridge monitors the blockchain for incoming transactions, +which can be detected by the `OP_RETURN` output. +Once the bridge detects the Deposit Request Transaction (DRT), +it verifies the "take back" TapLeaf hash, the multisig pubkey path, +and the full Taproot commitment. + +If the Deposit Request Transaction (DRT) is valid, +the bridge operators fulfill the deposit with a Deposit Transaction (DT) +that transfers the BTC to the bridge address's UTXO set +and also mints the same amount of sBTC in the rollup to +the Execution Layer (EL) address provided by the user. + +Below in the figure is the deposit flow: + +```mermaid +sequenceDiagram + participant User + participant Bitcoin + participant Bridge + + User->>Bitcoin: DRT + Bitcoin->>Bitcoin: DRT + Bitcoin->>Bridge: DRT + Bridge->>Bridge: DRT + Bridge->>Bitcoin: DRT-DT + Bitcoin->>Bitcoin: DT + Bridge->>Bridge: Mint +``` + +## Withdrawal + +All withdrawals take place through the bridge's UTXO set. + +The user requests a withdrawal in the rollup and an operator is assigned to +fulfill the request in the Bitcoin network: + +1. The user requests a withdrawal from the rollup making sure to burn the + same amount of `sBTC`. +1. The assigned operator creates and signs a Withdrawal Transaction + (WT) where they spend 10 BTC from the Bridge Address' UTXO set, + while subtracting the operator's fee and the transaction fee; + and requests the other $N−1$ operators to sign + the Withdrawal Transaction. +1. Once all the signatures have been aggregated, the transaction is submitted to + the Bitcoin network. +1. Once the transaction is confirmed, + the withdrawal request is fulfilled. + +The withdrawal flow is shown below: + +```mermaid +sequenceDiagram + participant User + participant Operator + participant Bridge + participant Bitcoin + + User->>User: Burn + User->>Bridge: Withdrawal + Bridge->>Operator: Duty + Operator->>Bitcoin: WT + Operator->>Operator: WT + Bitcoin->>Bitcoin: WT +``` diff --git a/docs/technical/comparing-ethereum.md b/docs/technical/comparing-ethereum.md new file mode 100644 index 0000000..bb36eb4 --- /dev/null +++ b/docs/technical/comparing-ethereum.md @@ -0,0 +1,32 @@ +# Comparing Strata and Ethereum + +## EVM compatibility + +Strata is an EVM-compatible blockchain. +The execution client used by the Strata block producer is based on reth +and is fully compatible with the EVM spec. +During the devnet phase, Strata can be considered a Type 1 zkEVM. + +!!! note + + In a future release, + Strata developers plan to introduce changes + that will result in a Type 2.5 zkEVM rating. + Watch the Strata [issues repo](https://github.com/alpenlabs/strata/issues) + to stay up to date with proposed consensus changes. + +## Blockchain functionality + +Comparing differences in how Strata and Ethereum functionally operate: + + + +| | Strata | Ethereum | +| ---------------- | ------------------------------------------------------------------------------------------------------ | -------------- | +| Consensus: | Proof of Work | Proof of Stake | +| Gas asset: | BTC | ETH | +| Block gas limit: | 8,000,000 | 30,000,000 | +| Block time: | ~5s | ~12s | +| Finality: | Probabilistic, blocks are confirmed in
batches on a private bitcoin signet
about once per hour | ~15m | + + diff --git a/docs/technical/node-types.md b/docs/technical/node-types.md new file mode 100644 index 0000000..7ce4c38 --- /dev/null +++ b/docs/technical/node-types.md @@ -0,0 +1,91 @@ +# Node Types + +Strata consists of different types of nodes, +each serving specific roles within the network. + +- **Full node**: responsible for maintaining a local copy of + and validating the entire Strata state +- **Sequencer node**: full node that has the additional responsibility + of ordering transactions and producing new Strata blocks. +- **Bridge node**: full node that has the additional responsibility + of facilitating the transfer of assets between bitcoin and Strata. + +## Node comparison table + + + +| Network | Feature | Full node | Sequencer node | Bridge node | +| :--------------------- | :------------------------------------------------- | -------------------------- | -------------------------- | -------------------------- | +| **Strata** | **storage** of blocks and state | :material-check:{ .green } | :material-close:{ .red } | :material-close:{ .red } | +| **Strata** | **validation** of incoming blocks and transactions | :material-check:{ .green } | :material-close:{ .red } | :material-close:{ .red } | +| **Strata** | **RPC**-endpoint | :material-check:{ .green } | :material-close:{ .red } | :material-close:{ .red } | +| **Strata** | **relay** of transactions and blocks | :material-check:{ .green } | :material-check:{ .green } | :material-close:{ .red } | +| **Strata** | **sequence** of incoming transactions | :material-close:{ .red } | :material-check:{ .green } | :material-close:{ .red } | +| **Strata** | **construction** of new blocks | :material-close:{ .red } | :material-check:{ .green } | :material-close:{ .red } | +| **Strata** | **broadcast** of new blocks | :material-close:{ .red } | :material-check:{ .green } | :material-close:{ .red } | +| **Strata** | **execution** of incoming transactions | :material-check:{ .green } | :material-check:{ .green } | :material-close:{ .red } | +| **Bitcoin** | **writing** of batch data | :material-close:{ .red } | :material-check:{ .green } | :material-close:{ .red } | +| **Bitcoin** | **monitoring** of deposit transactions | :material-close:{ .red } | :material-close:{ .red } | :material-check:{ .green } | +| **Bitcoin** | **processing** of withdrawal requests | :material-close:{ .red } | :material-close:{ .red } | :material-check:{ .green } | +| **Bitcoin**/**Strata** | **Ensuring** secure BTC transfers | :material-close:{ .red } | :material-close:{ .red } | :material-check:{ .green } | + + + +## Full node + +A Strata full node is responsible for maintaining +and validating the entire state of the Strata chain. + +**Key features**: + +- Stores the complete history of Strata blocks and state. +- Validates incoming Strata blocks and transactions. +- Serves RPC requests for chain data. +- Participates in the network by relaying transactions and blocks. + +## Sequencer node + +A sequencer node is a specialized full node that has +the additional responsibility of ordering transactions +and producing new Strata blocks. + +**Key features**: + +- All features of a _full node_. +- Receives and orders incoming transactions. +- Executes transactions to produce new Strata blocks. +- Interacts with the bitcoin node write batch metadata to bitcoin. +- Serves Strata blocks to other full nodes via RPC. + +## Bridge node + +A bridge node facilitates the transfer of assets between +bitcoin and Strata. + +**Key features**: + +- Monitors bitcoin for deposit transactions. +- Processes Strata withdrawal requests. +- Interacts with both bitcoin and Strata to ensure secure BTC transfers. + +## Key differences between node types + + + +1. **Block production**: + - _Only_ sequencer nodes produce and relay new Strata blocks. + - Full nodes and bridge nodes validate blocks + but do _not_ produce or relay them. +2. **Network interactions**: + - Sequencer nodes have the most complex network interactions, + dealing with both Strata transaction intake and bitcoin checkpoints. + - Bridge nodes interact extensively with both bitcoin + and Strata for BTC transfers. + - Full nodes primarily interact within the Strata network. +3. **Resource requirements**: + - Sequencer nodes typically require the most resources + due to their block production responsibilities. + - Full nodes require significant storage for the entire state history. + - Bridge nodes require reliable connections to both bitcoin and Strata. + + diff --git a/docs/technical/specs.md b/docs/technical/specs.md new file mode 100644 index 0000000..e78725a --- /dev/null +++ b/docs/technical/specs.md @@ -0,0 +1,24 @@ +# Specifications + +Some introductory text here about the specifications. + +## Parameters + +Another introductory text here about parameters. + +### Block Time + +Something about block time. + +### Gas Limit + +Something about gas limit. + +## Precompiles + +All precompiles supported, including rollup-specific precompiles. + +## Addresses + +Any "system" addresses related to rollup operations or that would otherwise be +helpful for users to know about diff --git a/docs/technical/transaction-lifecycle.md b/docs/technical/transaction-lifecycle.md new file mode 100644 index 0000000..877cf49 --- /dev/null +++ b/docs/technical/transaction-lifecycle.md @@ -0,0 +1,131 @@ +# Transaction lifecycle + +This document describes the journey of Strata transactions +from initiation to finalization. + +## Transaction initiation and propagation + +For devnet, Strata supports both Externally Owned Account (EOA) transactions +and account abstraction transactions (referred to as UserOperations) +as defined in ERC-4337. +EOA transactions can be initiated by users through any EVM-compatible wallet +that is connected to a Strata full node. +For account abstraction, we provide a bundler that accepts UserOperations +and relays them to a full node we have deployed. +On devnet, each full node is directly connected to a full node run by Alpen Labs, +which in turn is connected to the sequencer (also run by Alpen Labs). +This setup helps reduce propagation time, +given the relatively small number of full nodes expected. +Ultimately, all user transactions reach the sequencer through +this full node. + +## Block building + +The sequencer orders the EVM transactions received based on +the default algorithm used by Reth, +which is to prioritize the transactions with higher effective gas price, +respecting the account nonce ordering (ascending). +A block is constructed every 5 seconds, and it includes: + +- A header with metadata (timestamp, block number, etc.) +- An L1 segment (information from the bitcoin chain) +- An execution segment (includes the actual EVM transactions and related info) + +The block is executed against the current Strata chain state, +during which the pending withdrawals and deposits are processed +and the chain state is updated. +The chain state primarily includes: + +- EVM state +- Strata’s view of the bitcoin state + (eg. current "safe" bitcoin block, blocks that may reorg, etc.) +- List of current bridge operators +- Pending deposit and withdrawal info +- Auxiliary info about the Strata chain e.g. latest Strata block, + current slot and checkpoint period, etc. More about checkpointing below. + +After the block is executed and verified, the block is added to the blockchain +and is relayed to the prover and full nodes, who are all polling for new blocks. + +## Batch building + +A batch represents a collection of blocks associated with a single checkpoint, +which includes a proof of state transition and state commitments, +written to bitcoin in a bitcoin transaction. +The process of building a new batch checkpoint begins when the checkpoint for +the previous batch is detected on bitcoin. +The first block of the new batch follows immediately after +the final block of the previous batch - this applies to both the Strata +and bitcoin batches. +The final block in the Strata batch is chosen to be +the latest block in the Strata chain, +while the final block in the bitcoin batch is the most recent "safe" block on +the bitcoin chain as seen by the sequencer. +A safe block is one that has been sufficiently buried in the bitcoin chain +to be resistant to reorganization. + +Once the sequencer decides on the ranges for the new batch checkpoint, +the prover begins constructing +an aggregated proof of state transition for that batch. +Once the proof is ready, it is prepared to be written to bitcoin, +along with the checkpoint information. + +## Proving + +The prover starts proving the state transition for a Strata block as soon as +it is constructed by the sequencer, +retrieving all the inputs necessary for proof generation from the sequencer. +Since block construction by the sequencer is faster than +the proof generation for a block, +proof generation of multiple blocks happen in parallel. +When it is time to construct a proof for a new batch, +the prover retrieves previous proof information, +the new batch checkpoint information, and the relevant bitcoin chain, +and the prover starts two parallel processes: + +1. constructing a recursive proof in proper order from + the individual state transition proofs of + each Strata block generated for this batch, and +2. constructing a proof by reading the bitcoin chain for the given range, + verifying its validity, + and verifying that all relevant transactions in the bitcoin chain, + such as deposits and the previous batch proof, are included in the Strata chain. + Both of these proofs are then recursively combined to create the batch proof. + +The batch proof proves the following: + +- The input bitcoin chain is valid and corresponds to the range of this batch. +- Every transaction in the bitcoin chain was scanned and all + the relevant transactions + (such as the previous checkpoint transaction and deposit transactions) + are properly extracted. +- The previous batch proof in the extracted checkpoint is valid. +- All deposits initiated on bitcoin are included in the Strata batch. +- The current batch starts immediately after the last block of the previous batch. +- Execution of the Strata blocks in this batch produces a valid state transition. + +The batch proof is recursive, +so by verifying the latest batch proof a client can verify that +the Strata state transitions from genesis to the latest block included included +in the batch are valid. +This batch proof is passed to the sequencer for writing to bitcoin. + +## Batch checkpoint + +Once the batch proof is ready, +the proof is included in the checkpoint which is signed by the sequencer, +compressed, and serialized into bytes. +The sequencer then creates bitcoin transactions with +an [envelope](https://docs.ordinals.com/inscriptions.html) that contains +the signed checkpoint data along with Strata chain information such as +the blockchain name and version. + +The transactions are then broadcast to the bitcoin network +and eventually confirmed in a bitcoin block. + +### Batch finalization + +Once the bitcoin block containing the batch checkpoint +is sufficiently buried in the blockchain, +full nodes consider the Strata batch committed to in the checkpoint, +and all transactions in that batch, to be finalized. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..9a252a4 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,47 @@ +import markdownlint from "eslint-plugin-markdownlint"; +import eslintConfigPrettier from "eslint-config-prettier"; +import parser from "eslint-plugin-markdownlint/parser.js"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + { + plugins: { + markdownlint, + eslintConfigPrettier, + }, + }, + ...compat.extends("plugin:markdownlint/recommended").map((config) => ({ + ...config, + files: ["**/*.md"], + })), + { + files: ["**/*.md"], + + languageOptions: { + parser, + }, + + rules: { + "markdownlint/md033": "off", // inline HTML + "markdownlint/md046": "off", // code block style + "markdownlint/md024": [ + "error", + { + // duplicate headings + siblings_only: true, + }, + ], + }, + }, +]; diff --git a/justfile b/justfile new file mode 100644 index 0000000..32247c9 --- /dev/null +++ b/justfile @@ -0,0 +1,73 @@ +alias s := serve + +# List everything +default: + @just --list + +# Serve the site localling +serve: + @echo "Serving the site locally" + @echo "If this fails you might need either to install mkdocs-material or run 'just serve-docker' instead" + mkdocs serve + +# Serve the site locally using Docker +serve-docker: + @echo "Serving the site locally using Docker" + docker run --rm -u "$(id -u):$(id -g)" -v "$PWD":/docs -p 8000:8000 squidfunk/mkdocs-material + +# Make everything ready for a PR +pr: + @just format-check + @just lint-check + @just spell-check + @echo "PR checks complete!" + +# Check for spelling errors +spell-check: + @echo "Checking for spelling errors" + pnpm spell:check + +# Add a word to the dictionary +spell-add *WORDS: + @echo "Adding {{ WORDS }} to the dictionary" + for word in {{ WORDS }}; do echo $word >> project-words.txt; done + +# Sort the dictionary +spell-sort: + @echo "Sorting the dictionary" + sort -o project-words.txt project-words.txt + +# Check for formatting errors +format-check: + @echo "Checking for formatting errors" + pnpm format:check + +# Fix formatting errors +format-fix: + @echo "Fixing formatting errors" + pnpm format:fix + +# Check for lint errors +lint-check: + @echo "Checking for lint errors" + pnpm lint:check + +# Fix lint errors +lint-fix: + @echo "Fixing lint errors" + pnpm lint:fix + +# Install pnpm +pnpm-install: + @echo "Installing pnpm" + wget -qO- https://get.pnpm.io/install.sh | sh + +# Install NPM dependencies +npm-install: + @echo "Installing NPM dependencies" + pnpm install + +# Clean the NPM cache +npm-clean: + @echo "Cleaning NPM cache" + rm -rf node_modules/ .pnpm-store/ diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..48b0a34 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,87 @@ +# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json +site_name: Documentation +site_url: https://docs.stratabtc.org +repo_url: https://github.com/alpenlabs/strata +repo_name: "" +plugins: + - search +theme: + name: material + logo: assets/logo.png + icon: + repo: fontawesome/brands/github + favicon: assets/favicon.png + palette: + - scheme: default + primary: white + accent: custom + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: black + accent: custom + toggle: + icon: material/brightness-4 + name: Switch to light mode + font: + text: Inter + code: Roboto Mono + features: + - navigation.instant + - navigation.footer + - search.suggest + - search.highlight + - toc.follow + - toc.integrate + - content.code.copy + - content.code.annotate +extra: + homepage: https://stratabtc.org + generator: false +markdown_extensions: + - tables + - toc: + permalink: true + - attr_list + - md_in_html + - footnotes + - admonition + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + linenums: true + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.arithmatex: + generic: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format +extra_javascript: + - javascripts/mathjax.js + - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js +extra_css: + - stylesheets/extra.css + +nav: + - Introduction to Strata: index.md + - How Strata Works: + - Specifications: technical/specs.md + - System Architecture: technical/architecture.md + - Transaction Lifecycle: technical/transaction-lifecycle.md + - Bitcoin Bridge: technical/bitcoin-bridge.md + - Node Types: technical/node-types.md + - Comparing Strata and Ethereum: technical/comparing-ethereum.md + - Community: + - Website: https://stratabtc.org + - GitHub: https://github.com/alpenlabs/strata + - Telegram: https://t.me/Strata_Community + - Twitter: https://twitter.com/Strata_BTC diff --git a/package.json b/package.json new file mode 100644 index 0000000..26da152 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "alpen-docs", + "version": "0.1.0", + "description": "Public documentation related to Alpen Labs products.", + "scripts": { + "lint:check": "eslint .", + "lint:fix": "eslint --fix .", + "spell:check": "cspell lint \"**/*.md\"", + "format:check": "prettier --config .prettierrc.yaml --check .", + "format:fix": "prettier --config .prettierrc.yaml --write .", + "sort:project-words": "sort -o project-words.txt project-words.txt" + }, + "keywords": [], + "type": "module", + "author": "", + "license": "MIT", + "devDependencies": { + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.5.0", + "cspell": "^8.9.0", + "eslint": "^9.5.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-markdownlint": "^0.6.0", + "prettier": "^3.3.2" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..3df8d57 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1546 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@eslint/eslintrc': + specifier: ^3.1.0 + version: 3.1.0 + '@eslint/js': + specifier: ^9.5.0 + version: 9.5.0 + cspell: + specifier: ^8.9.0 + version: 8.9.0 + eslint: + specifier: ^9.5.0 + version: 9.5.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@9.5.0) + eslint-plugin-markdownlint: + specifier: ^0.6.0 + version: 0.6.0(eslint@9.5.0) + prettier: + specifier: ^3.3.2 + version: 3.3.2 + +packages: + + '@cspell/cspell-bundled-dicts@8.9.0': + resolution: {integrity: sha512-Dxfuva7zlcI2X/PulDI7bfJBB1De4OuulR2prVpDuGLk3zAiFO7t4d2bmdWxfowhtm1agSqY03uZOTk8fTppuQ==} + engines: {node: '>=18'} + + '@cspell/cspell-json-reporter@8.9.0': + resolution: {integrity: sha512-+m2HoYTqdI76Zt27CyCpFCAxEUlTMnJnC76MpuQEd21C72qXWmaYdcVzJ7GnVXtTY6cofefUy/X3zgkUBW/bqg==} + engines: {node: '>=18'} + + '@cspell/cspell-pipe@8.9.0': + resolution: {integrity: sha512-N3Nv9F/1LyUabd1lda+N7tU+UpY7lp8mZvG7ZTxhoB8vfw/Yf3f8NlQ5awSYear2Q+N0RoGyyLaaqUY6nUQvOQ==} + engines: {node: '>=18'} + + '@cspell/cspell-resolver@8.9.0': + resolution: {integrity: sha512-52FCYcrZZhdAKkGoHss000nUk2mHkujxHJOfh+KMh2p15igmPW0AR7/VFKSS7zVkkLfAhQfWxoqQLkoE+yvccA==} + engines: {node: '>=18'} + + '@cspell/cspell-service-bus@8.9.0': + resolution: {integrity: sha512-R8MlY3dp4my/VZp2xhvkUcXbLsTZUSNuxsOFzpPYLQhtrei0ReEcaDTg2JEU1wfHnREGG8GYlWh9BEryx8AZYA==} + engines: {node: '>=18'} + + '@cspell/cspell-types@8.9.0': + resolution: {integrity: sha512-YeL14G+tIh92WvO5K9+WBCjckRQAApeSNkIavx+7+IF+MUoGPvVbTA881q15zwoPRPtOJQ8wEbI6zJH5ykKFfw==} + engines: {node: '>=18'} + + '@cspell/dict-ada@4.0.2': + resolution: {integrity: sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==} + + '@cspell/dict-aws@4.0.2': + resolution: {integrity: sha512-aNGHWSV7dRLTIn8WJemzLoMF62qOaiUQlgnsCwH5fRCD/00gsWCwg106pnbkmK4AyabyxzneOV4dfecDJWkSxw==} + + '@cspell/dict-bash@4.1.3': + resolution: {integrity: sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw==} + + '@cspell/dict-companies@3.1.2': + resolution: {integrity: sha512-OwR5i1xbYuJX7FtHQySmTy3iJtPV1rZQ3jFCxFGwrA1xRQ4rtRcDQ+sTXBCIAoJHkXa84f9J3zsngOKmMGyS/w==} + + '@cspell/dict-cpp@5.1.10': + resolution: {integrity: sha512-BmIF0sAz2BgGEOwzYIeEm9ALneDjd1tcTbFbo+A1Hcq3zOKP8yViSgxS9CEN30KOZIyph6Tldp531UPEpoEl0Q==} + + '@cspell/dict-cryptocurrencies@5.0.0': + resolution: {integrity: sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==} + + '@cspell/dict-csharp@4.0.2': + resolution: {integrity: sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==} + + '@cspell/dict-css@4.0.12': + resolution: {integrity: sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw==} + + '@cspell/dict-dart@2.0.3': + resolution: {integrity: sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw==} + + '@cspell/dict-data-science@2.0.1': + resolution: {integrity: sha512-xeutkzK0eBe+LFXOFU2kJeAYO6IuFUc1g7iRLr7HeCmlC4rsdGclwGHh61KmttL3+YHQytYStxaRBdGAXWC8Lw==} + + '@cspell/dict-django@4.1.0': + resolution: {integrity: sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==} + + '@cspell/dict-docker@1.1.7': + resolution: {integrity: sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==} + + '@cspell/dict-dotnet@5.0.2': + resolution: {integrity: sha512-UD/pO2A2zia/YZJ8Kck/F6YyDSpCMq0YvItpd4YbtDVzPREfTZ48FjZsbYi4Jhzwfvc6o8R56JusAE58P+4sNQ==} + + '@cspell/dict-elixir@4.0.3': + resolution: {integrity: sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==} + + '@cspell/dict-en-common-misspellings@2.0.2': + resolution: {integrity: sha512-LA8BO0RaoJD+ExHzK5mz+t9RQ0HaBPDxgR4JTfG8YKJP5keO+pFMH9ZMZphKPjW46QYUZb6Ta1HIRikBEOZfYw==} + + '@cspell/dict-en-gb@1.1.33': + resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} + + '@cspell/dict-en_us@4.3.22': + resolution: {integrity: sha512-UegkIQhKkTLGarpYNV5ybW2JHzuxhDMOF9q9TW37iG8YoHp5jeVW3C0p3cH9nHWMwEjPinJFfxBd1LPRxGv5dQ==} + + '@cspell/dict-filetypes@3.0.4': + resolution: {integrity: sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==} + + '@cspell/dict-fonts@4.0.0': + resolution: {integrity: sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==} + + '@cspell/dict-fsharp@1.0.1': + resolution: {integrity: sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==} + + '@cspell/dict-fullstack@3.1.8': + resolution: {integrity: sha512-YRlZupL7uqMCtEBK0bDP9BrcPnjDhz7m4GBqCc1EYqfXauHbLmDT8ELha7T/E7wsFKniHSjzwDZzhNXo2lusRQ==} + + '@cspell/dict-gaming-terms@1.0.5': + resolution: {integrity: sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==} + + '@cspell/dict-git@3.0.0': + resolution: {integrity: sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==} + + '@cspell/dict-golang@6.0.9': + resolution: {integrity: sha512-etDt2WQauyEQDA+qPS5QtkYTb2I9l5IfQftAllVoB1aOrT6bxxpHvMEpJ0Hsn/vezxrCqa/BmtUbRxllIxIuSg==} + + '@cspell/dict-google@1.0.1': + resolution: {integrity: sha512-dQr4M3n95uOhtloNSgB9tYYGXGGEGEykkFyRtfcp5pFuEecYUa0BSgtlGKx9RXVtJtKgR+yFT/a5uQSlt8WjqQ==} + + '@cspell/dict-haskell@4.0.1': + resolution: {integrity: sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==} + + '@cspell/dict-html-symbol-entities@4.0.0': + resolution: {integrity: sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==} + + '@cspell/dict-html@4.0.5': + resolution: {integrity: sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==} + + '@cspell/dict-java@5.0.7': + resolution: {integrity: sha512-ejQ9iJXYIq7R09BScU2y5OUGrSqwcD+J5mHFOKbduuQ5s/Eh/duz45KOzykeMLI6KHPVxhBKpUPBWIsfewECpQ==} + + '@cspell/dict-julia@1.0.1': + resolution: {integrity: sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==} + + '@cspell/dict-k8s@1.0.5': + resolution: {integrity: sha512-Cj+/ZV4S+MKlwfocSJZqe/2UAd/sY8YtlZjbK25VN1nCnrsKrBjfkX29vclwSj1U9aJg4Z9jw/uMjoaKu9ZrpQ==} + + '@cspell/dict-latex@4.0.0': + resolution: {integrity: sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==} + + '@cspell/dict-lorem-ipsum@4.0.0': + resolution: {integrity: sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==} + + '@cspell/dict-lua@4.0.3': + resolution: {integrity: sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==} + + '@cspell/dict-makefile@1.0.0': + resolution: {integrity: sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==} + + '@cspell/dict-monkeyc@1.0.6': + resolution: {integrity: sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==} + + '@cspell/dict-node@5.0.1': + resolution: {integrity: sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==} + + '@cspell/dict-npm@5.0.16': + resolution: {integrity: sha512-ZWPnLAziEcSCvV0c8k9Qj88pfMu+wZwM5Qks87ShsfBgI8uLZ9tGHravA7gmjH1Gd7Bgxy2ulvXtSqIWPh1lew==} + + '@cspell/dict-php@4.0.8': + resolution: {integrity: sha512-TBw3won4MCBQ2wdu7kvgOCR3dY2Tb+LJHgDUpuquy3WnzGiSDJ4AVelrZdE1xu7mjFJUr4q48aB21YT5uQqPZA==} + + '@cspell/dict-powershell@5.0.4': + resolution: {integrity: sha512-eosDShapDgBWN9ULF7+sRNdUtzRnUdsfEdBSchDm8FZA4HOqxUSZy3b/cX/Rdw0Fnw0AKgk0kzgXw7tS6vwJMQ==} + + '@cspell/dict-public-licenses@2.0.7': + resolution: {integrity: sha512-KlBXuGcN3LE7tQi/GEqKiDewWGGuopiAD0zRK1QilOx5Co8XAvs044gk4MNIQftc8r0nHeUI+irJKLGcR36DIQ==} + + '@cspell/dict-python@4.2.1': + resolution: {integrity: sha512-9X2jRgyM0cxBoFQRo4Zc8oacyWnXi+0/bMI5FGibZNZV4y/o9UoFEr6agjU260/cXHTjIdkX233nN7eb7dtyRg==} + + '@cspell/dict-r@2.0.1': + resolution: {integrity: sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==} + + '@cspell/dict-ruby@5.0.2': + resolution: {integrity: sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==} + + '@cspell/dict-rust@4.0.4': + resolution: {integrity: sha512-v9/LcZknt/Xq7m1jdTWiQEtmkVVKdE1etAfGL2sgcWpZYewEa459HeWndNA0gfzQrpWX9sYay18mt7pqClJEdA==} + + '@cspell/dict-scala@5.0.2': + resolution: {integrity: sha512-v97ClgidZt99JUm7OjhQugDHmhx4U8fcgunHvD/BsXWjXNj4cTr0m0YjofyZoL44WpICsNuFV9F/sv9OM5HUEw==} + + '@cspell/dict-software-terms@3.4.6': + resolution: {integrity: sha512-Cap+WL4iM9NgwxdVIa93aDEGKGNm1t+DLJTnjoWkGHXxSBPG8Kcbnlss6mTtwLv9/NYPmQsmJi5qHXruuHx2ow==} + + '@cspell/dict-sql@2.1.3': + resolution: {integrity: sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==} + + '@cspell/dict-svelte@1.0.2': + resolution: {integrity: sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==} + + '@cspell/dict-swift@2.0.1': + resolution: {integrity: sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==} + + '@cspell/dict-terraform@1.0.0': + resolution: {integrity: sha512-Ak+vy4HP/bOgzf06BAMC30+ZvL9mzv21xLM2XtfnBLTDJGdxlk/nK0U6QT8VfFLqJ0ZZSpyOxGsUebWDCTr/zQ==} + + '@cspell/dict-typescript@3.1.5': + resolution: {integrity: sha512-EkIwwNV/xqEoBPJml2S16RXj65h1kvly8dfDLgXerrKw6puybZdvAHerAph6/uPTYdtLcsPyJYkPt5ISOJYrtw==} + + '@cspell/dict-vue@3.0.0': + resolution: {integrity: sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==} + + '@cspell/dynamic-import@8.9.0': + resolution: {integrity: sha512-UYa2Xlf/Bg9b7lUlKn59Z6XhHtE00z5kgzkKCGAdS0W27i2qUZJHW3FfiKfknWLNLzfj7cVUAq2IHjbumbx9ow==} + engines: {node: '>=18.0'} + + '@cspell/strong-weak-map@8.9.0': + resolution: {integrity: sha512-HE0rkwtJ4/4QuXpJW1r4GIK+jhs2SYK4IACf3EE2mJufOWF4YxgfWwKBgztKE/0RDMJcxyvn/ubLUCnNClNfdg==} + engines: {node: '>=18'} + + '@cspell/url@8.9.0': + resolution: {integrity: sha512-FaHTEx6OBVKlkX7VgAPofBZ5vIdxNWYalb0uZwJ5FCc/PCMIF5l91DQGQxRMas3qzRACR911kJamPdeK/3qilw==} + engines: {node: '>=18.0'} + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.10.1': + resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.16.0': + resolution: {integrity: sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.5.0': + resolution: {integrity: sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.12.0: + resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk-template@1.1.0: + resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} + engines: {node: '>=14.16'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + clear-module@4.1.2: + resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + engines: {node: '>=8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + comment-json@4.2.3: + resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + cspell-config-lib@8.9.0: + resolution: {integrity: sha512-1FQketvqo6IktnyC2ishEIzfqSX2DNhsfpb0MIG/nNeG5KvbjSeozOZpfyrALVqhPUJZVWfMP3+N0/hj3AzH+g==} + engines: {node: '>=18'} + + cspell-dictionary@8.9.0: + resolution: {integrity: sha512-IsFyWsn9P979xoJ0PgWHdyjxVcDYe5nVmHMgJRecQ5LLhl2gFkOmsu+aYIh2qlHCLmcbzH31Me2x7Fd+jA6AXw==} + engines: {node: '>=18'} + + cspell-gitignore@8.9.0: + resolution: {integrity: sha512-/iw+iqFLgySqW7xJ+kDHtC0mRjajDM1/jvnu4pUoxU9cRanCEqg2IAA/BET+n3ZEs/etsl8P4MB0lgWE98Z15g==} + engines: {node: '>=18'} + hasBin: true + + cspell-glob@8.9.0: + resolution: {integrity: sha512-j96SMMzT5Nz0nKCUECLkoyPEEms4hXKm/S7Vj80A356TFglTJD/yYiMKfWUamCVPm8UYODCz7W0s/liR7gSBSw==} + engines: {node: '>=18'} + + cspell-grammar@8.9.0: + resolution: {integrity: sha512-oZEOE64lLc0clLGOJeqc5d1Yzc1fUtXQAAeLIrS+uoVM7nA1SqgIEv1JBjp3R++8jQKLjS5n7v16VW5A/yk67w==} + engines: {node: '>=18'} + hasBin: true + + cspell-io@8.9.0: + resolution: {integrity: sha512-8KHERgqlg8KKpn04Owg2VY1Di2dSiwV/v63bUFxsGb8ORGIQ1VcydxtANwWuugUrZvtVrSFsbuU2fK/LRmAnoQ==} + engines: {node: '>=18'} + + cspell-lib@8.9.0: + resolution: {integrity: sha512-k347TQs1QRUyyHWHYQxPJddApos/irFousr9W/M/jEkYTTKzMMfaXK8m20kBSnlJ+BOUMa+f8d+KPEw6QLwtJQ==} + engines: {node: '>=18'} + + cspell-trie-lib@8.9.0: + resolution: {integrity: sha512-fQNQyFoeZA7b66jvhGaUYPzsS6gmPRJa6RcEpw2onP41S+IyLO6egubUu/qq8Hn1ebgJe/0Pc4fzkgv6MfV3tQ==} + engines: {node: '>=18'} + + cspell@8.9.0: + resolution: {integrity: sha512-lDYu5p/XU3rqiNjMV46s92yJ7SfVyzAy03OtCJ94fopegZwFLjqZvqoy509ccP/0sHmiv83oTed8LP6Fm3kjpw==} + engines: {node: '>=18'} + hasBin: true + + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-markdownlint@0.6.0: + resolution: {integrity: sha512-idYAzR2k7tQ+zL6UC17I/zzkqM0t6/k50uGgO39tabryqVkJh8Qe57fhBhe7QN+17yqIVqFB9YJFzBCAOdSXjw==} + engines: {node: '>=10'} + peerDependencies: + eslint: '>=7.5.0' + + eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.5.0: + resolution: {integrity: sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-equals@5.0.1: + resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==} + engines: {node: '>=6.0.0'} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + gensequence@7.0.0: + resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==} + engines: {node: '>=18'} + + get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + + markdownlint-micromark@0.1.9: + resolution: {integrity: sha512-5hVs/DzAFa8XqYosbEAEg6ok6MF2smDj89ztn9pKkCtdKHVdPQuGMH7frFfYL9mLkvfFe4pTyAMffLbjf3/EyA==} + engines: {node: '>=18'} + + markdownlint@0.34.0: + resolution: {integrity: sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==} + engines: {node: '>=18'} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parent-module@2.0.0: + resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.3.2: + resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + engines: {node: '>=14'} + hasBin: true + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + vscode-languageserver-textdocument@1.0.11: + resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} + + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + yaml@2.4.5: + resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@cspell/cspell-bundled-dicts@8.9.0': + dependencies: + '@cspell/dict-ada': 4.0.2 + '@cspell/dict-aws': 4.0.2 + '@cspell/dict-bash': 4.1.3 + '@cspell/dict-companies': 3.1.2 + '@cspell/dict-cpp': 5.1.10 + '@cspell/dict-cryptocurrencies': 5.0.0 + '@cspell/dict-csharp': 4.0.2 + '@cspell/dict-css': 4.0.12 + '@cspell/dict-dart': 2.0.3 + '@cspell/dict-django': 4.1.0 + '@cspell/dict-docker': 1.1.7 + '@cspell/dict-dotnet': 5.0.2 + '@cspell/dict-elixir': 4.0.3 + '@cspell/dict-en-common-misspellings': 2.0.2 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.3.22 + '@cspell/dict-filetypes': 3.0.4 + '@cspell/dict-fonts': 4.0.0 + '@cspell/dict-fsharp': 1.0.1 + '@cspell/dict-fullstack': 3.1.8 + '@cspell/dict-gaming-terms': 1.0.5 + '@cspell/dict-git': 3.0.0 + '@cspell/dict-golang': 6.0.9 + '@cspell/dict-google': 1.0.1 + '@cspell/dict-haskell': 4.0.1 + '@cspell/dict-html': 4.0.5 + '@cspell/dict-html-symbol-entities': 4.0.0 + '@cspell/dict-java': 5.0.7 + '@cspell/dict-julia': 1.0.1 + '@cspell/dict-k8s': 1.0.5 + '@cspell/dict-latex': 4.0.0 + '@cspell/dict-lorem-ipsum': 4.0.0 + '@cspell/dict-lua': 4.0.3 + '@cspell/dict-makefile': 1.0.0 + '@cspell/dict-monkeyc': 1.0.6 + '@cspell/dict-node': 5.0.1 + '@cspell/dict-npm': 5.0.16 + '@cspell/dict-php': 4.0.8 + '@cspell/dict-powershell': 5.0.4 + '@cspell/dict-public-licenses': 2.0.7 + '@cspell/dict-python': 4.2.1 + '@cspell/dict-r': 2.0.1 + '@cspell/dict-ruby': 5.0.2 + '@cspell/dict-rust': 4.0.4 + '@cspell/dict-scala': 5.0.2 + '@cspell/dict-software-terms': 3.4.6 + '@cspell/dict-sql': 2.1.3 + '@cspell/dict-svelte': 1.0.2 + '@cspell/dict-swift': 2.0.1 + '@cspell/dict-terraform': 1.0.0 + '@cspell/dict-typescript': 3.1.5 + '@cspell/dict-vue': 3.0.0 + + '@cspell/cspell-json-reporter@8.9.0': + dependencies: + '@cspell/cspell-types': 8.9.0 + + '@cspell/cspell-pipe@8.9.0': {} + + '@cspell/cspell-resolver@8.9.0': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@8.9.0': {} + + '@cspell/cspell-types@8.9.0': {} + + '@cspell/dict-ada@4.0.2': {} + + '@cspell/dict-aws@4.0.2': {} + + '@cspell/dict-bash@4.1.3': {} + + '@cspell/dict-companies@3.1.2': {} + + '@cspell/dict-cpp@5.1.10': {} + + '@cspell/dict-cryptocurrencies@5.0.0': {} + + '@cspell/dict-csharp@4.0.2': {} + + '@cspell/dict-css@4.0.12': {} + + '@cspell/dict-dart@2.0.3': {} + + '@cspell/dict-data-science@2.0.1': {} + + '@cspell/dict-django@4.1.0': {} + + '@cspell/dict-docker@1.1.7': {} + + '@cspell/dict-dotnet@5.0.2': {} + + '@cspell/dict-elixir@4.0.3': {} + + '@cspell/dict-en-common-misspellings@2.0.2': {} + + '@cspell/dict-en-gb@1.1.33': {} + + '@cspell/dict-en_us@4.3.22': {} + + '@cspell/dict-filetypes@3.0.4': {} + + '@cspell/dict-fonts@4.0.0': {} + + '@cspell/dict-fsharp@1.0.1': {} + + '@cspell/dict-fullstack@3.1.8': {} + + '@cspell/dict-gaming-terms@1.0.5': {} + + '@cspell/dict-git@3.0.0': {} + + '@cspell/dict-golang@6.0.9': {} + + '@cspell/dict-google@1.0.1': {} + + '@cspell/dict-haskell@4.0.1': {} + + '@cspell/dict-html-symbol-entities@4.0.0': {} + + '@cspell/dict-html@4.0.5': {} + + '@cspell/dict-java@5.0.7': {} + + '@cspell/dict-julia@1.0.1': {} + + '@cspell/dict-k8s@1.0.5': {} + + '@cspell/dict-latex@4.0.0': {} + + '@cspell/dict-lorem-ipsum@4.0.0': {} + + '@cspell/dict-lua@4.0.3': {} + + '@cspell/dict-makefile@1.0.0': {} + + '@cspell/dict-monkeyc@1.0.6': {} + + '@cspell/dict-node@5.0.1': {} + + '@cspell/dict-npm@5.0.16': {} + + '@cspell/dict-php@4.0.8': {} + + '@cspell/dict-powershell@5.0.4': {} + + '@cspell/dict-public-licenses@2.0.7': {} + + '@cspell/dict-python@4.2.1': + dependencies: + '@cspell/dict-data-science': 2.0.1 + + '@cspell/dict-r@2.0.1': {} + + '@cspell/dict-ruby@5.0.2': {} + + '@cspell/dict-rust@4.0.4': {} + + '@cspell/dict-scala@5.0.2': {} + + '@cspell/dict-software-terms@3.4.6': {} + + '@cspell/dict-sql@2.1.3': {} + + '@cspell/dict-svelte@1.0.2': {} + + '@cspell/dict-swift@2.0.1': {} + + '@cspell/dict-terraform@1.0.0': {} + + '@cspell/dict-typescript@3.1.5': {} + + '@cspell/dict-vue@3.0.0': {} + + '@cspell/dynamic-import@8.9.0': + dependencies: + import-meta-resolve: 4.1.0 + + '@cspell/strong-weak-map@8.9.0': {} + + '@cspell/url@8.9.0': {} + + '@eslint-community/eslint-utils@4.4.0(eslint@9.5.0)': + dependencies: + eslint: 9.5.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.10.1': {} + + '@eslint/config-array@0.16.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.5 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.1.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.5 + espree: 10.1.0 + globals: 14.0.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.5.0': {} + + '@eslint/object-schema@2.1.4': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + acorn-jsx@5.3.2(acorn@8.12.0): + dependencies: + acorn: 8.12.0 + + acorn@8.12.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-timsort@1.0.3: {} + + balanced-match@1.0.2: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + callsites@3.1.0: {} + + chalk-template@1.1.0: + dependencies: + chalk: 5.3.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@12.1.0: {} + + comment-json@4.2.3: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + + concat-map@0.0.1: {} + + core-util-is@1.0.3: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cspell-config-lib@8.9.0: + dependencies: + '@cspell/cspell-types': 8.9.0 + comment-json: 4.2.3 + yaml: 2.4.5 + + cspell-dictionary@8.9.0: + dependencies: + '@cspell/cspell-pipe': 8.9.0 + '@cspell/cspell-types': 8.9.0 + cspell-trie-lib: 8.9.0 + fast-equals: 5.0.1 + gensequence: 7.0.0 + + cspell-gitignore@8.9.0: + dependencies: + cspell-glob: 8.9.0 + find-up-simple: 1.0.0 + + cspell-glob@8.9.0: + dependencies: + micromatch: 4.0.7 + + cspell-grammar@8.9.0: + dependencies: + '@cspell/cspell-pipe': 8.9.0 + '@cspell/cspell-types': 8.9.0 + + cspell-io@8.9.0: + dependencies: + '@cspell/cspell-service-bus': 8.9.0 + '@cspell/url': 8.9.0 + + cspell-lib@8.9.0: + dependencies: + '@cspell/cspell-bundled-dicts': 8.9.0 + '@cspell/cspell-pipe': 8.9.0 + '@cspell/cspell-resolver': 8.9.0 + '@cspell/cspell-types': 8.9.0 + '@cspell/dynamic-import': 8.9.0 + '@cspell/strong-weak-map': 8.9.0 + '@cspell/url': 8.9.0 + clear-module: 4.1.2 + comment-json: 4.2.3 + cspell-config-lib: 8.9.0 + cspell-dictionary: 8.9.0 + cspell-glob: 8.9.0 + cspell-grammar: 8.9.0 + cspell-io: 8.9.0 + cspell-trie-lib: 8.9.0 + env-paths: 3.0.0 + fast-equals: 5.0.1 + gensequence: 7.0.0 + import-fresh: 3.3.0 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + xdg-basedir: 5.1.0 + + cspell-trie-lib@8.9.0: + dependencies: + '@cspell/cspell-pipe': 8.9.0 + '@cspell/cspell-types': 8.9.0 + gensequence: 7.0.0 + + cspell@8.9.0: + dependencies: + '@cspell/cspell-json-reporter': 8.9.0 + '@cspell/cspell-pipe': 8.9.0 + '@cspell/cspell-types': 8.9.0 + '@cspell/dynamic-import': 8.9.0 + chalk: 5.3.0 + chalk-template: 1.1.0 + commander: 12.1.0 + cspell-gitignore: 8.9.0 + cspell-glob: 8.9.0 + cspell-io: 8.9.0 + cspell-lib: 8.9.0 + fast-glob: 3.3.2 + fast-json-stable-stringify: 2.1.0 + file-entry-cache: 8.0.0 + get-stdin: 9.0.0 + semver: 7.6.2 + strip-ansi: 7.1.0 + vscode-uri: 3.0.8 + + debug@4.3.5: + dependencies: + ms: 2.1.2 + + deep-is@0.1.4: {} + + entities@4.5.0: {} + + env-paths@3.0.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@9.1.0(eslint@9.5.0): + dependencies: + eslint: 9.5.0 + + eslint-plugin-markdownlint@0.6.0(eslint@9.5.0): + dependencies: + eslint: 9.5.0 + markdownlint: 0.34.0 + + eslint-scope@8.0.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.0.0: {} + + eslint@9.5.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) + '@eslint-community/regexpp': 4.10.1 + '@eslint/config-array': 0.16.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.5.0 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.5 + escape-string-regexp: 4.0.0 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + 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.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@10.1.0: + dependencies: + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) + eslint-visitor-keys: 4.0.0 + + esprima@4.0.1: {} + + esquery@1.5.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-equals@5.0.1: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up-simple@1.0.0: {} + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + gensequence@7.0.0: {} + + get-stdin@9.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + globals@14.0.0: {} + + has-flag@4.0.0: {} + + has-own-prop@2.0.0: {} + + ignore@5.3.1: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + ini@4.1.1: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + isexe@2.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + markdown-it@14.1.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + markdownlint-micromark@0.1.9: {} + + markdownlint@0.34.0: + dependencies: + markdown-it: 14.1.0 + markdownlint-micromark: 0.1.9 + + mdurl@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + ms@2.1.2: {} + + natural-compare@1.4.0: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + picomatch@2.3.1: {} + + prelude-ls@1.2.1: {} + + prettier@3.3.2: {} + + punycode.js@2.3.1: {} + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + repeat-string@1.6.1: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + reusify@1.0.4: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + semver@7.6.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + text-table@0.2.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + uc.micro@2.1.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + vscode-languageserver-textdocument@1.0.11: {} + + vscode-uri@3.0.8: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + xdg-basedir@5.1.0: {} + + yaml@2.4.5: {} + + yocto-queue@0.1.0: {} diff --git a/project-words.txt b/project-words.txt new file mode 100644 index 0000000..a865957 --- /dev/null +++ b/project-words.txt @@ -0,0 +1,38 @@ +NUMS +PUSHBYTES +Taproot +Tapscript +Taptree +alpen +bcoin +bibt +bitcoinj +blockquotes +btcd +checkpointing +counterparty +cpfp +cryptosystem +devnet +endhint +hashpower +incentivized +infty +libbitcoin +mainchain +mermaidjs +mkdocs +multisigs +offchain +println +pseudocode +pubkey +satoshis +secp +snarknado +squidfunk +timelock +txid +unspendable +utxo +Ðapp diff --git a/style-guide.md b/style-guide.md new file mode 100644 index 0000000..caea8dc --- /dev/null +++ b/style-guide.md @@ -0,0 +1,317 @@ +# Documentation style guide + +Alpen Labs documentation follow the following guidelines. +Please adhere to these guidelines when contributing to the documentation. + +We are using a simple documentation framework called +[`mkdocs-material`](https://squidfunk.github.io/mkdocs-material/) +that is built on top of `Markdown` files. + +## General guidelines + +- **Clarity**: Write clear and concise documentation. + Only add technical terms or jargons if they add clarity to the concept being + described. At the same time, avoid skipping details for the sake of + conciseness. +- **Consistency**: Ensure consistency in terms, formatting, and style throughout + the documentation. +- **Accuracy**: Keep information accurate and up-to-date. Verify facts and + details before including them in the documentation. +- **Audience**: Consider the target audience (beginners, advanced users, + developers) and tailor the content accordingly. + +## Language and tone + +- **Voice**: Use active voice whenever possible. + - Active: "The system processes the data." + - Passive: "The data is processed by the system." +- **Tone**: Use a friendly and professional tone. +- **Grammar**: Use correct grammar and punctuation. Avoid contractions. +- **Terminology**: Use consistent terminology throughout the documentation. + Define any technical terms or acronyms when first introduced. + +## Bitcoin-related guidelines + +- **Bitcoin**: The word "bitcoin" is not capitalized if referring to either + the asset, the network, or the protocol. "Bitcoin" is capitalized if it is + the first word in a sentence or if it is a proper noun that is part of something's + name e.g. Bitcoin Core. + - The ticker symbol for the native asset of the bitcoin blockchain is BTC. +- **Blockchain**: The word "blockchain" is not capitalized unless it is a proper + noun part of something's name e.g. "Blockchain Inc." + - The word “blockchain” is a one word (i.e. not “block chain”) + [concrete noun](https://medium.com/@ryanshea/blockchain-terminology-a-grammar-usage-guide-ff54c95167bb) + and should always be preceded by either a possessive noun, “a”, or “the” e.g. + “bitcoin’s blockchain”, “a blockchain”, or “the blockchain”. +- **Decentralized applications**: The abbreviation of “decentralized application” + is “dapp”. Not “DApp”, “dApp”, or “Ðapp”. + - There is an ongoing debate over whether the term “decentralized application” + is useful to begin with, at least in user-facing communications. In light of + this, we should generally refer to a so-called "decentralized application" as + an "app" or maybe more specifically "web app" or "mobile app" rather than a "dapp". + If it is actually decentralized in some way, we can describe how in specific + detail if the context calls for it. +- **Zero-knowledge**: The term "zero-knowledge" as in "zero-knowledge proof" + (or "zk" for short) was originally defined as "those proofs that contain no + additional knowledge other than the correctness of the proposition in question". + However the term has since been used colloquially to describe any cryptosystem + that enables sub-linear verification of computation using a validity proof, + whether it is actually zero-knowledge or not. Due to this common usage and + understanding we therefore accept the use of "zero-knowledge" or "zk" as + synonymous with verifiable computation and may use these terms this same way + throughout the documentation. + +## File organization + +- **Directory structure**: Organize documentation files in a logical and + consistent directory structure. + + - Example: + + ```plaintext + docs/ + ├── bridge-specs/ + │ ├── index.md + │ ├── deposit-path.md + │ └── withdrawal-path.md + └── rollup-specs/ + ├── index.md + ├── prover.md + └── consensus-state-machine.md + ``` + +- **File naming**: Use descriptive and consistent file names. Use hyphens to + separate words. + - Example: `basic-usage.md` +- **Index Files**: Use the index files (`index.md`) to provide the table + of contents for the doc. + +## Formatting + +- **Commas**: Always use an Oxford comma (“Note that a, b, and c are…”). +- **Spelling**: Use American English spelling of a word when the spelling + varies by locale. +- **Capitalization**: Page titles and headings should be in sentence case. + This means that the first word is always capitalized and all other words + except proper nouns and acronyms are lowercase. +- **Numbers**: Use numbers for numeric parameters, no matter how short the + number e.g. 1 block, 5 seconds, 10 KB, etc. +- **Line Length**: Keep lines of text to a reasonable length (80 characters) + for readability. +- **Headings**: Use hierarchical headings (H1, H2, H3, H4) to organize content. + - H1: `# Title` + - H2: `## Subtitle` + - H3: `### Section` + - H4: `#### Subsection` +- **Lists**: + - Use unordered lists (`-`) for bullet points. + - Use ordered lists (`1.`) for step-by-step instructions. + Note that ordered lists should start from `1.` for each step. + This ensures that the numbering is consistent across the document while also + producing sane diffs in version control. + - Lists should always be in alphabetical, numerical, or chronological order, unless + there’s a good reason for them not to be. +- **Bullet points** + - Use a period (full stop) after every bullet point that is a sentence. + - Use a period after every bullet point that completes the introductory stem. + - Use no punctuation after bullets that are fragment sentences and do not + complete the stem. + - Use all complete sentences or all fragments, but not a mixture. + - Use no punctuation after bullets that only contain one word e.g. There are + multiple implementations of bitcoin, including: + - Bitcoin Core + - bcoin + - bitcoinj + - btcd + - libbitcoin +- **Emphasis**: + - Use `_italic_` for emphasis. + - Use `**bold**` for strong emphasis. +- **Blockquotes**: Use `>` for blockquotes to highlight important notes or + quotes. +- **Tables**: Use tables for structured data. + + - Example: + + ```markdown + | Header 1 | Header 2 | + | -------- | -------- | + | Cell 1 | Cell 2 | + ``` + +- **Admonitions**: Use `!!!` for admonitions. Please refer to the + [`mkdocs-material` documentation](https://squidfunk.github.io/mkdocs-material/reference/admonitions/). + + - Examples: + + ```markdown + !!! note + + Useful information that users should know, even when skimming content. + + !!! info + + Additional information that provides context or clarification + + !!! tip + + Helpful advice for doing things better or more easily. + + !!! warning + + Urgent info that needs immediate user attention to avoid problems. + + !!! danger + + Advises about risks or negative outcomes of certain actions. + ``` + +- **Equations**: Use `$` for inline equations and `$$` for block equations. + You can also label them if needed for reference. + Example: + + ```markdown + There are $N^2$ different BitVM games. + ``` + + For block equations, use new-line separators. + Example: + + ```markdown + The parameters ought to have the following relationship: + + $$ + d < \frac{p + q}{2} + $$ + ``` + + Finally, here's how you can label equations: + + ```markdown + $$ + \begin{equation} + \int_0^\infty \frac{x^3}{e^x-1}\,dx = \frac{\pi^4}{15} + \label{eq:sample} + \end{equation} + $$ + ``` + +- **Time format**: The format to use for dates is either YYYY-MM-DD if numeric + (e.g 2020-12-31) or Month D(st)(th)(D, YYYY) if spelled out (e.g. January 1st + or December 31, 2020). + - Related: all times are communicated in UTC and specified as such to avoid + the confusion of “Daylight Savings Time”, which is inconsistently implemented + across the world + ([even within the same country](https://en.wikipedia.org/wiki/Daylight_saving_time_in_the_United_States#Local_DST_observance)) + and is [generally a scourge on humanity](https://www.inc.com/jessica-stillman/experts-to-public-daylight-savings-time-is-a-434m-problem-we-could-easily-fix.html). + An exception would be if there is an event being held locally in a specific + time zone and there's no need to specify a time zone because all attendees will + be in that time zone. In this case, the local time zone does not need to be + specified unless the event is also being live-streamed so that people worldwide + can watch online; here, both the local time zone and UTC time should be + specified e.g. “17:00 EDT / 21:00 UTC”. + +## Code and Commands + +- **Inline Code**: Use backticks for inline code snippets. + - Example: `inline code` +- **Code Blocks**: Use triple backticks for multi-line code blocks. + Specify the language for syntax highlighting. + Use annotations to provide context or explanations for code blocks. + Annotations should be prefixed with language-specific comment characters, + and should be followed by a footnote with the same id as the annotation. + + - Examples: + + ```python + def example_fn(): + print("Hello, World!") + ``` + + ```rust + fn example_fn() { + println!("Hello, World!"); + } + ``` + + ```python + # This code has an annotation at the end of the print function call. + # You should add a footnote with the same id as the annotation, i.e. (1). + def example_fn(): + print("Hello, World!") # (1) + ``` + +- **Commands**: Prefix shell commands with `$` to distinguish them from code + blocks. + + - Example: + + ```bash + git clone https://github.com/your-user/your-repo.git + ``` + +## Links and References + +- **Internal Links**: Use relative links for internal references within the + documentation. + - Example: `[Section Title](#section-title)` +- **External Links**: Use absolute URLs for external references. + - Example: `[External Resource](https://example.com)` +- **References**: Cite any external resources, documents, or articles + appropriately. +- **Footnotes**: Use footnotes to add some extra relevant information. These can + be used to display texts when hovering on certain words. Footnotes can be + multiline as well. To start a new line, prefix it with two spaces. + + - Example: + + ```markdown + At least one of the operators must be functional[^1] to prevent theft of + funds from this address. + + [^1]: + We use the term "functional" to describe an operator who is correctly + following the protocol rules. An operator that is not functional is + called "faulty". + ``` + +## Images and Diagrams + +- **Images**: Use clear and relevant images to support the text. + Don't forget to add captions. + + - Example: + + ```markdown +
+ ![Image title](https://dummyimage.com/600x400/){ width="300" } +
Image caption
+
+ ``` + +- **Diagrams**: Use diagrams to illustrate complex concepts. `mkdocs-material` + has support for [`mermaidjs`](https://mermaid.js.org/), which can be included + with the following syntax: + + ```mermaidjs + graph LR + A[Start] --> B{Error?}; + B -->|Yes| C[Hmm...]; + C --> D[Debug]; + D --> B; + B ---->|No| E[Yay!]; + ``` + +## Commit message format + +Make your commit messages descriptive, concise and in the imperative form. +When in doubt, follow these excellent guides: + +- [Write Better Commits, Build Better Projects](https://github.blog/2022-06-30-write-better-commits-build-better-projects/) +- [A Note About Git Commit Messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) + +--- + +**Thank you for contributing to our documentation! +Adhering to this style guide helps maintain high-quality and consistent +documentation.**