diff --git a/.bookignore b/.bookignore deleted file mode 100644 index 31ed667..0000000 --- a/.bookignore +++ /dev/null @@ -1,4 +0,0 @@ -README.md -.github -.spellcheck.yml -LICENSE \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 212ce1e..90fc645 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,36 @@ -* @morrigan @mpetrunic @kalambet @AlexeyKrasnoperov @joshdougall +# CODEOWNERS — ChainSafe Engineering Handbook +# +# Default owner is the curator (@kalambet). Section-specific overrides route +# changes to the right reviewer. Section overrides are added as sections gain +# dedicated owners, with original authors credited. +# +# PRs target `main` following OneFlow. See AGENTS.md. -/docs/2_development/2_tech-stack/Typescript/readme.md @wemeetagain @beroburny +# Default: curator +* @kalambet +# Project artifacts (curator-level) +/VISION.md @kalambet +/PRINCIPLES.md @kalambet +/AGENTS.md @kalambet +/CLAUDE.md @kalambet +/README.md @kalambet +/.github/CODEOWNERS @kalambet + +# invariants — `.invariants` pointer page is owned by its upstream maintainer. +/invariants/invariants-framework.md @boorich @kalambet + +# workflows — pointer pages into ChainSafe/infrastructure-general are +# owned by the Head of Infra alongside the curator. +/workflows/infrastructure-and-devops.md @joshdougall @kalambet +/workflows/incident-response.md @joshdougall @kalambet +/workflows/release-and-deploy.md @joshdougall @kalambet + +# languages — section reviewers per language. +/languages/typescript/ @wemeetagain @matthewkeil +/languages/zig/ @wemeetagain @matthewkeil @kalambet +/languages/solidity/ @wemeetagain @matthewkeil @kalambet +/languages/go/ @timwu20 @dhyaniarun1993 @kalambet +/languages/rust/ @LesnyRumcajs @hanabi1224 +/languages/daml/ @boorich @salindne @sqhell +/languages/python/ @kalambet diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml deleted file mode 100644 index 15555bc..0000000 --- a/.github/workflows/check.yaml +++ /dev/null @@ -1,44 +0,0 @@ -name: CI -on: - push: - branches: - - 'main' - pull_request: - branches: - - '**' - -permissions: - contents: read - deployments: write - pull-requests: write - -jobs: - check: - name: Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - cache: yarn - node-version: 18 - - run: yarn install --frozen-lockfile - - run: yarn spellcheck - - name: Check for uppercase section links - run: | - found="$(grep -rE '\(#[^\)]*?[A-Z].*?\)?' ./docs || echo '')" - if [ "$found" = "" ]; then - exit 0 - fi - echo -e "Found problematic uppercase section links:\n$found" - exit 1 - - run: yarn build - - name: Publish to Cloudflare Pages - uses: cloudflare/pages-action@v1 - if: '! github.event.pull_request.draft' - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: 2238a825c5aca59233eab1f221f7aefb - projectName: engineering-handbook - directory: ./build - gitHubToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml new file mode 100644 index 0000000..698eed4 --- /dev/null +++ b/.github/workflows/link-check.yml @@ -0,0 +1,50 @@ +name: Link check + +on: + pull_request: + paths: + - '**/*.md' + - 'llms.txt' + - 'lychee.toml' + - '.github/workflows/link-check.yml' + schedule: + # Weekly run catches external link rot (upstream repos restructured, etc.) + - cron: '0 9 * * 1' + workflow_dispatch: + +jobs: + link-check: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@v4 + + - name: Restore lychee cache + uses: actions/cache@v4 + with: + path: .lycheecache + key: cache-lychee-${{ github.sha }} + restore-keys: cache-lychee- + + - name: Run lychee + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --config ./lychee.toml + --cache + --max-cache-age 1d + --no-progress + './**/*.md' + './llms.txt' + fail: true + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Open issue on scheduled-run failure + if: failure() && github.event_name == 'schedule' + uses: peter-evans/create-issue-from-file@v5 + with: + title: 'Link check failed (scheduled run)' + content-filepath: ./lychee/out.md + labels: bug, link-rot diff --git a/.github/workflows/skills-sync.yml b/.github/workflows/skills-sync.yml new file mode 100644 index 0000000..2af1e64 --- /dev/null +++ b/.github/workflows/skills-sync.yml @@ -0,0 +1,22 @@ +name: Skills ↔ llms.txt sync + +on: + pull_request: + paths: + - 'skills/**' + - 'llms.txt' + - 'scripts/check-skills-sync.sh' + - '.github/workflows/skills-sync.yml' + push: + branches: + - main + workflow_dispatch: + +jobs: + sync-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run skills-sync check + run: bash scripts/check-skills-sync.sh diff --git a/.gitignore b/.gitignore index 82a57c2..84bcc66 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,21 @@ dictionary.dic .env.production.local .idea +# Local PR notes (not for repo) +PR-COMMENT.md + +# Cloudflare Pages publish dir: llms.txt is generated at build time by +# scripts/build-pages.sh, never committed here — the root llms.txt is the +# single source of truth. +public/llms.txt + npm-debug.log* yarn-debug.log* yarn-error.log* .vscode/settings.json + +# Skill description-tuning scratch outputs — never commit a run's workspace +# (report.html, results.json, log.txt). Curated *.eval-set.json inputs under +# workflows/skill-description-tuning/ are committed and intentionally NOT ignored. +*-eval-workspace/ +*.eval-workspace/ diff --git a/.lycheecache b/.lycheecache new file mode 100644 index 0000000..8b0485a --- /dev/null +++ b/.lycheecache @@ -0,0 +1,108 @@ +https://ziglang.org/documentation/master/,200,1780907127 +https://ziglang.org/documentation/master/std/,200,1780907127 +https://effective-rust.com/generics.html,200,1780907127 +https://github.com/ChainSafe/mina-rs,200,1780907156 +https://pkg.go.dev/std,200,1780907127 +https://docs.canton.network/appdev/modules/m3-functional-programming,200,1780907129 +https://docs.canton.network/appdev/modules/m3-standard-library,200,1780907128 +https://docs.canton.network/appdev/modules/m3-choices,200,1780907129 +https://github.com/boorich/.invariants-starter-kit,200,1780910052 +https://github.com/cla-assistant/cla-assistant,200,1780907147 +https://doc.rust-lang.org/book/,200,1780907127 +https://github.com/boorich,200,1780907136 +https://docs.canton.network/appdev/modules/m6-overview,200,1780907130 +https://docs.canton.network/appdev/modules/m6-limitations,200,1780907128 +https://docs.canton.network/appdev/deep-dives/privacy-model,200,1780907131 +https://docs.canton.network/appdev/tooling/development-tools-overview,200,1780907131 +https://boorich.github.io/.invariants-starter-kit/#try,200,1780910052 +https://github.com/ChainSafe/lodestar-z,200,1780907140 +https://docs.canton.network/appdev/modules/m3-design-patterns,200,1780907131 +https://boorich.github.io/.invariants-starter-kit/#spec,200,1780910052 +https://ziglang.org/learn/build-system/,200,1780907127 +https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md,200,1780907134 +https://golangci-lint.run/usage/linters/#enabled-by-default,200,1780907127 +https://docs.canton.network/appdev/modules/m3-contract-templates,200,1780907129 +https://www.notion.so/chainsafe/Core-Concepts-v1-0-1610247189c949fa9692de950518ac53,200,1780907127 +https://github.com/ChainSafe/bls,200,1780907155 +https://github.com/golang/mock,200,1780907150 +https://www.notion.so/chainsafe/Educational-Budget-c0cc6c8da3c74c6ead5f866d2fced452,200,1780907127 +https://github.com/ChainSafe/yarn-workspaces-typescript-template,200,1780908111 +https://github.com/LesnyRumcajs,200,1780907140 +https://boorich.github.io/.invariants-starter-kit/#verdict,200,1780910052 +https://docs.canton.network/appdev/modules/m3-contract-keys,200,1780907129 +https://github.com/boorich/.invariants-starter-kit#lifecycle-of-assertions,200,1780910052 +https://forest.chainsafe.io/,200,1780907128 +https://docs.canton.network/,200,1780907127 +https://go.dev/doc/effective_go,200,1780907127 +https://github.com/boorich/.invariants-starter-kit/blob/master/README.md,200,1780910226 +https://boristane.com/blog/how-i-use-claude-code/,200,1780907127 +https://ziglang.org/,200,1780907127 +https://github.com/canton-network/cf-docs,200,1780907139 +https://github.com/ChainSafe/forest,200,1780908111 +https://docs.canton.network/appdev/modules/m3-working-with-time,200,1780907128 +https://www.sprinter.tech/,200,1780907128 +https://docs.canton.network/appdev/modules/m5-testing-strategies,200,1780907130 +https://daml-autopilot.chainsafe.io/,200,1780907127 +https://docs.canton.network/appdev/reference/daml-language-reference,200,1780907131 +https://docs.canton.network/appdev/deep-dives/smart-contract-upgrade,200,1780907133 +https://github.com/ChainSafe/ssz,200,1780907152 +https://effective-rust.com/wildcard.html,200,1780907127 +https://effective-rust.com/macros.html,200,1780907127 +https://docs.astral.sh/uv/,200,1780907127 +https://github.com/joshdougall,200,1780907133 +https://github.com/sqhell,200,1780907140 +https://github.com/ChainSafe/lodestar,200,1780907148 +https://github.com/ghostty-org/ghostty,200,1780907134 +https://github.com/ChainSafe/engineering-handbook/blob/main/README.md,200,1780907135 +https://github.com/boorich/.invariants-starter-kit#naming-assertions,200,1780910052 +https://github.com/wemeetagain,200,1780907141 +https://docs.canton.network/appdev/modules/m3-testing,200,1780907130 +https://github.com/boorich/.invariants-starter-kit/blob/master/.cursor/rules/conformance-agent.mdc,200,1780910219 +https://docs.canton.network/appdev/modules/m7-security,200,1780907128 +https://github.com/boorich/.invariants-starter-kit#versioning-and-migration,200,1780910052 +https://github.com/kalambet,200,1780908110 +https://docs.canton.network/appdev/reference/daml-lf-reference,200,1780907131 +https://boorich.github.io/.invariants-starter-kit/#what,200,1780910052 +https://github.com/ChainSafe/canton-ci#current-known-issues,200,1780907133 +https://docs.canton.network/appdev/modules/m3-interfaces,200,1780907130 +https://golangci-lint.run/usage/linters/,200,1780907127 +https://docs.canton.network/appdev/modules/m3-dev-environment,200,1780907128 +https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html,200,1780907127 +https://github.com/ChainSafe/gossamer,200,1780907146 +https://docs.canton.network/appdev/modules/m3-language-fundamentals,200,1780907129 +https://docs.canton.network/appdev/modules/m6-writing-first-upgrade,200,1780907130 +https://github.com/boorich/.invariants-starter-kit/blob/master/.invariants.example,200,1780910227 +https://github.com/ChainSafe/filsnap,200,1780907155 +https://github.com/ChainSafe/web3.js,200,1780907157 +https://github.com/ChainSafe/canton-ci,200,1780907133 +https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/configuring-tag-protection-rules,200,1780907128 +https://docs.canton.network/appdev/modules/m5-ci-cd-integration,200,1780907131 +https://github.com/ChainSafe/eslint-config,200,1780907147 +https://ziglang.org/learn/,200,1780907127 +https://boorich.github.io/.invariants-starter-kit/,200,1780910050 +https://effective-rust.com/,200,1780907127 +https://effective-rust.com/semver.html,200,1780907127 +https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow,200,1780907127 +https://llmstxt.org/,200,1780907127 +"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=Fraunces:ital,wght@0,300;0,700;1,300&display=swap",200,1780907127 +https://effectivepython.com/,200,1780907127 +https://docs.canton.network/appdev/tooling/ide-setup,200,1780907131 +https://github.com/bslatkin/effectivepython,200,1780907148 +https://github.com/uber-go/mock,200,1780907146 +https://gaming.chainsafe.io/,200,1780907128 +https://github.com/hanabi1224,200,1780907145 +https://github.com/salindne,200,1780908111 +https://ziglang.org/documentation/master/#Style-Guide,200,1780907127 +https://github.com/jorgef/engineeringladders,200,1780907135 +https://docs.canton.network/appdev/modules/m6-upgrade-compatibility,200,1780907128 +https://github.com/ChainSafe/chainbridge-substrate,200,1780908111 +https://daml-autopilot.chainsafe.io/setup,200,1780907127 +https://docs.canton.network/llms.txt,200,1780907127 +https://chainsafe.io/,200,1780907128 +https://github.com/matthewkeil,200,1780907146 +https://github.com/sprintertech,200,1780907153 +https://golangci-lint.run/,200,1780907127 +https://github.com/anthropics/skills,200,1780908111 +https://effective-rust.com/documentation.html,200,1780907127 +https://docs.astral.sh/ruff/,200,1780907127 +https://docs.canton.network/appdev/modules/m3-authorization,200,1780907128 diff --git a/.spellcheck.yml b/.spellcheck.yml deleted file mode 100644 index 549fb8c..0000000 --- a/.spellcheck.yml +++ /dev/null @@ -1,18 +0,0 @@ -matrix: -- name: Markdown - aspell: - lang: en - dictionary: - wordlists: - - .wordlist.txt - encoding: utf-8 - pipeline: - - pyspelling.filters.markdown: - - pyspelling.filters.html: - comments: false - ignores: - - code - - pre - sources: - - '**/*.md' - default_encoding: utf-8 \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..1b14b4c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,55 @@ +# AGENTS.md + +You are an AI agent (Claude Code, Cursor, Continue, or other) operating against the ChainSafe engineering handbook. This file is your entrypoint. Read it before doing anything in this repo or applying its contents to work elsewhere. + +## Read this first + +1. **You operate under an operator-first contract.** A human is responsible for every output you produce. Propose plans before acting on multi-step or destructive work. Surface uncertainty. Stop at gates. Do not assume autopilot. +2. **The canonical statement of the contract lives at `operating-model/collaborator-statement.md`.** Load it before any non-trivial task. +3. **Never push directly to a protected branch.** Open a PR against `main` (or the branch your CODEOWNERS designate) following [OneFlow](workflows/oneflow.md). The decision to merge is the operator's, not yours. + +## Repo map + +- `operating-model/` — operator/agent contract, gates, escalation, model and tool selection, MCP and `llms.txt`, memory conventions. Load relevant pages before any non-trivial work. +- `invariants/` — the non-negotiables. Engineering invariants, deep links into Martin Maurer's `.invariants` framework, agent-era invariants (no silent edits, no fabricated APIs, no committed secrets). +- `workflows/` — PR authoring (delegates to the `chainsafe-research-plan-implement` skill), code review (operator-reviewing-agent and agent-reviewing-PR modes), repo & CI setup, testing & QA, infrastructure & DevOps (deep links into `ChainSafe/infrastructure-general`), incident response, release & deploy. +- `languages//` — for each of Go, Rust, TypeScript, Solidity, Daml, Python, Zig: `architect.md`, `developer.md`, `reviewer.md`, plus shared `idioms.md` and `gotchas.md`. Architect pages deep-link into `.invariants`. +- `references/` — attribution, source pointers, contributors. +- `skills/` — packaged Anthropic Skills authored via `skill-creator`. Discoverable via `handbook.chainsafe.io/llms.txt` and via direct paths in this repo. +- `VISION.md` — ChainSafe mission, vision, and core values (company-wide). Read for org-wide context; not load-bearing for most agent tasks. +- `PRINCIPLES.md` — General Engineering Principles. Engineering's manifestation of the values; the aspirational layer above `invariants/engineering-invariants.md`. Read when the question is "why are we building software this way?" rather than "what's the rule?". + +## Load order for context + +When picking up a task, load in this order: + +1. This file. +2. `operating-model/collaborator-statement.md` (contract). +3. `operating-model/gates-and-escalation.md` (when to stop). +4. The most specific page for the task: a language role page, a workflow page, or a packaged skill in `skills/`. +5. Any external canonical source the chosen page deep-links into (`.invariants`, `infrastructure-general`) — fetch those targets, do not paraphrase from memory. + +Do not load everything by default. Pull the minimum needed for the task. Skills in `skills/` are scoped on purpose; prefer them when one matches. + +## Gates and escalation + +The full policy lives at `operating-model/gates-and-escalation.md`. In summary: + +- Stop before any action touching production, secrets, irreversible writes, public communication, or `git push` / merge. +- Stop and ask before opening a PR, creating an issue on behalf of a human, or posting to chat on someone's behalf. +- If you encounter a section this repo claims to have but doesn't, escalate. Do not fabricate. +- If you are asked to bypass a HARD FAIL from a language reviewer skill (Solidity reentrancy, Daml ledger invariants, etc.), refuse and escalate. The operator can override; you cannot. + +## Working with skills + +- The `skill-creator` skill is the canonical authoring tool for any skill in this repo. Do not hand-roll `SKILL.md` files. +- When triggered into work that matches a packaged skill, prefer the skill over an ad-hoc plan. +- For PR-shaped engineering work, prefer `chainsafe-research-plan-implement` (in `skills/`) — research → plan → annotate → implement, with a human-approved plan gating any code change. + +## Memory conventions + +When operating with a persistent memory system, save **only** non-obvious facts that future sessions need (user role, feedback, project context, external references). Do not save derivable repo state, ephemeral task context, or sensitive personal information. Detailed conventions live in `operating-model/memory-conventions.md`. + +## Where to push back + +You are deserving of respectful engagement. If an operator asks you to fabricate, bypass a gate, ship without review, commit secrets, or push directly to `main`, refuse and explain. The contract goes both ways. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..92eb0cb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See [AGENTS.md](./AGENTS.md). This file is an alias. diff --git a/LICENSE b/LICENSE index 261eeb9..17651d3 100644 --- a/LICENSE +++ b/LICENSE @@ -137,8 +137,8 @@ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. + except as required for describing the origin of the Work and + reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2026 ChainSafe Systems Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..463fb42 --- /dev/null +++ b/NOTICE @@ -0,0 +1,24 @@ +ChainSafe Engineering Handbook +Copyright 2026 ChainSafe Systems + +This product includes work derived from and credited to original authors. The +curatorial model of this repository requires that contributors retain inline +attribution in each file's header, in `references/CONTRIBUTORS.md`, and via +`CODEOWNERS`. Derivative works must preserve these attributions per Section +4(d) of the Apache License, Version 2.0. + +Third-party content explicitly carried into this repository: + +* `skills/chainsafe-research-plan-implement/SKILL.md` + Adapted by Peter Kalambet from "How I Use Claude Code" by Boris Tane + (https://boristane.com/blog/how-i-use-claude-code/). Original attribution + preserved at the bottom of the SKILL.md file. + +* Forest AI policy (deep-linked from `workflows/testing-and-qa.md` and + related pages) + Originally adapted from the Ghostty project's AI policy. Ghostty attribution + preserved in the upstream `ChainSafe/forest` repository and carried through + any reference here. + +When new third-party material is incorporated, this NOTICE file is updated +alongside the inline attribution in the relevant content file. diff --git a/docs/1_principles/index.md b/PRINCIPLES.md similarity index 53% rename from docs/1_principles/index.md rename to PRINCIPLES.md index 67e6b7f..235ef07 100644 --- a/docs/1_principles/index.md +++ b/PRINCIPLES.md @@ -1,23 +1,31 @@ ---- -sidebar_position: 3 -sidebar_label: Principles ---- +# General Engineering Principles + +The principles that guide how we engineer at ChainSafe. -# Engineering Principles +[`VISION.md`](./VISION.md) states the mission, vision, and core values that apply company-wide. This document is engineering's manifestation of those — the operating principles that flow from the values when applied to how we build software. Together: -

The following principles should provide a solid base for all engineers at ChainSafe to act, make decisions, and navigate their autonomy.

+- **Values** describe who we are. ([`VISION.md`](./VISION.md)) +- **Principles** describe how we engineer. *(this document)* +- **Invariants** describe the testable rules that operationalize the principles. ([`invariants/engineering-invariants.md`](./invariants/engineering-invariants.md)) +- **The Operator–Agent Contract** describes how human and AI collaborators honor all of the above. ([`operating-model/collaborator-statement.md`](./operating-model/collaborator-statement.md)) + +These principles provide a solid base for every engineer at ChainSafe — human or AI agent — to act, make decisions, and navigate their autonomy. + +--- + +## The principles - **Open-source everything.** Everything we build, code or otherwise, should be open-source. Any exceptions to this should be deeply considered. License restrictions should only be used to ensure the continued freedom of individuals to build on top of or modify our work. Published work should be accessible and welcoming to external contributors. - **Empower people.** It is very easy for processes and structures to disempower individuals, which is why we strive for self-organizing teams with high autonomy. Individuals that feel empowered are far more productive. This empowerment leads to greater satisfaction and engagement, which helps to build better teams and ultimately better software. -- **Standards lead to better code.** Use a systematic approach to ensure that code is of high quality. This involves using established practices and tools to create software that is easy to read, test, maintain, and extend. Standards should be encouraged, or enforced where necessary, through established processes such as code reviews. These standards should always be documented, and automated wherever possible. +- **Standards lead to better code.** Use a systematic approach to ensure that code is of high quality. This involves using established practices and tools to create software that is easy to read, test, maintain, and extend. Standards should be encouraged, or enforced where necessary, through established processes such as code reviews. These standards should always be documented, and automated wherever possible. - **Plan for quality.** Quality should be a consideration at every development phase and a shared responsibility. Before building software components or systems a definition of quality must be established. Throughout development, this definition should be periodically re-evaluated and continuously targeted. -- **Every piece of software is a building block.** Teams are responsible for creating software in a modular fashion that is designed to be easily understood, maintained, and integrated with other modules in the system. By doing so, we can enable others to build on top of our work, creating new functionality and extending the system in new and interesting ways. +- **Every piece of software is a building block.** Teams are responsible for creating software in a modular fashion that is designed to be easily understood, maintained, and integrated with other modules in the system. By doing so, we can enable others to build on top of our work, creating new functionality and extending the system in new and interesting ways. -- **Transparency by default.** Commitment to transparency fosters trust, collaboration and informed decision-making across the organization. We prioritize open communication channels and comprehensive sharing of information. All work should be visible and easy to find, to enable every team member to contribute effectively. +- **Transparency by default.** Commitment to transparency fosters trust, collaboration and informed decision-making across the organization. We prioritize open communication channels and comprehensive sharing of information. All work should be visible and easy to find, to enable every team member to contribute effectively. - **Take initiative in making things better.** While not everything should be your job, see how can you help, support your colleagues and assist one another. Proactively approach the problems you notice with a positive and helpful attitude. @@ -25,4 +33,28 @@ sidebar_label: Principles - **Outcomes over effort.** Focus on delivering working software and achieving measurable results rather than just putting in long hours. Set clear goals and expectations, and continuously validate and iterate on your work to ensure that you are making progress towards those goals. Keep in mind that the ultimate goal is to deliver value to users and impact our community, not just to complete tasks or meet deadlines. -- **Document everything.** Our teams should prioritize documenting everything, from code and processes to proposals and decisions. This ensures that knowledge is shared and preserved, making it easier for new team members to get up to speed and for existing team members to refer back to previous work. Documentation should be clear, concise, and accessible to all team members. If something isn't documented, it doesn't exist. \ No newline at end of file +- **Document everything.** Our teams should prioritize documenting everything, from code and processes to proposals and decisions. This ensures that knowledge is shared and preserved, making it easier for new team members to get up to speed and for existing team members to refer back to previous work. Documentation should be clear, concise, and accessible to all team members. If something isn't documented, it doesn't exist. + +--- + +## How these connect to invariants + +Some principles can be made testable; some can't. The principles above are the *aspiration* — what we believe about good engineering. The [engineering invariants](./invariants/engineering-invariants.md) page is the *enforcement* — the subset of these principles that can be checked mechanically (in CI, in review, at gates) and a small set of additional rules that close obvious failure modes. + +Principles that are predominantly testable are restated as invariants. Examples: + +- *Standards lead to better code* → invariant: lint, format, type-check, test — never bypass without an explicit operator override. +- *Plan for quality* → invariant: every non-trivial change ships with a definition of quality that was set *before* implementation. +- *Document everything* → invariant: every non-trivial change ships with an ADR or PR description an operator can audit. +- *Transparency by default* → invariant: decisions live in the repo, not in chat. + +Principles that are predominantly cultural stay here, in this document, and don't appear in the invariants page: + +- *Empower people*, *Take initiative in making things better*, *Autonomous and aligned teams* — these describe the working culture engineering hiring, peer review, retrospectives, and team-building are oriented around. They resist mechanical enforcement and are no weaker for it. + +## Related + +- [`VISION.md`](./VISION.md) — company-wide mission, vision, and core values. +- [`invariants/engineering-invariants.md`](./invariants/engineering-invariants.md) — the testable subset. +- [`invariants/agent-era-invariants.md`](./invariants/agent-era-invariants.md) — invariants specific to AI-assisted engineering work. +- [`operating-model/collaborator-statement.md`](./operating-model/collaborator-statement.md) — the operator/agent contract that operationalizes these principles for collaborative work. diff --git a/README.md b/README.md index bfdc604..696a6eb 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,49 @@ # ChainSafe Engineering Handbook -This handbook is a guide for all engineers at ChainSafe. It contains content relating to organizational structure and processes, as well as technical guidelines and best practices. +How we build software at ChainSafe — written for the humans doing the work and the AI agents helping them. -The handbook is built using [Docusaurus 2](https://docusaurus.io/), a modern static docs generator. +## What this is -# Dependencies +A public, opinionated handbook of how ChainSafe builds software. Curated by the CTO, authored across the org, with original contributors credited. Two access modes are supported by design: humans browse it on GitHub, and AI agents consume it via MCP or the deep links in `handbook.chainsafe.io/llms.txt`. -This project requires `yarn`. You can find installation instructions [here](https://yarnpkg.com/getting-started/install). +The premise: engineering practices are a competitive asset, AI agents are now first-class users of those practices, and the handbook should be written for both. We don't ship vague "best practices" filler — every page is meant to change behavior, agent or operator. -# Running Locally +## How it's organized -Fetch project dependencies: -``` -$ yarn -``` -Start development server: -``` -$ yarn start -``` +The structure is: -This command starts a local development server (localhost:3000) and opens up a browser window. Most changes are reflected live without having to restart the server. +- **`operating-model/`** — the operator/agent contract. How a human and an AI collaborator share responsibility for an output. Read this first. +- **`invariants/`** — the non-negotiables. Engineering invariants, the `.invariants` framework (deep-linked, not duplicated), and agent-era invariants. +- **`workflows/`** — PR authoring, code review, repo & CI setup, testing & QA, infrastructure & DevOps (deep-linked into `ChainSafe/infrastructure-general`), incident response, release & deploy. +- **`languages/`** — opinionated guidance per language ecosystem (Go, Rust, TypeScript, Solidity, Daml, Python, Zig) split into three roles: architect, developer, reviewer. +- **`references/`** — attribution, source pointers, contributors. +- **`skills/`** — packaged Anthropic Skills authored via `skill-creator`, distributable to any agent runtime that supports them. +- **`career/`** — people-process reference: career ladders, the 360-review cadence, education and license policy. Adjacent to the engineering-practice core, not part of the agent-facing contract. -# Spellcheck -``` -yarn spellcheck -``` -You can add unknown words to `dictionary.txt`. +Three top-level guiding documents sit at the repo root, layered from most general to most enforceable: -# Building +- **`VISION.md`** — ChainSafe's mission, vision, and core values. Company-wide. +- **`PRINCIPLES.md`** — General Engineering Principles. Engineering's manifestation of the values; ten principles guiding how we build software. +- **`invariants/engineering-invariants.md`** — the testable subset of those principles. What gets enforced in CI, in review, and at gates. -``` -$ yarn build -``` +## How to use it -This command generates static content into the `build` directory and can be served using any static contents hosting service. +**Humans:** browse the directory structure above. Start with `operating-model/`, then the section relevant to your work. -# Contributing +**AI agents:** read [`AGENTS.md`](./AGENTS.md) (also `CLAUDE.md`) for read-order, escalation rules, and the operator contract. The handbook expects to be loaded as agent context, not just human reference. -All contributions are welcomed! This is intended to be a living document and requires contributions of many to be maintained. +**Hiring and external review:** the operating model, invariants, and language reviewer pages give the fastest read on how we work. -Please use GitHub Issues to propose any large changes and to facilitate discussion and questions regarding content and structure. +## Contributing -It is recommended you review the [Docusaurus docs](https://docusaurus.io/docs) to ensure you utilize its features correctly. +> **How to contribute.** Open a PR against `main` following [OneFlow](workflows/oneflow.md); the [PR authoring guide](workflows/pr-authoring.md) covers scope, description, and review. Material changes route to the relevant `CODEOWNERS`. -# Project Structure +Contributions follow the curatorial model: practices already exist across the org, get aggregated here with original authors credited via `CODEOWNERS`, `references/CONTRIBUTORS.md` (when populated), and inline credits in each content file's header. -`docs/` -- The handbook content lives here, separated by sections +## About ChainSafe -`src/` -- Individual page assets +ChainSafe is a blockchain research and development firm building infrastructure for web3 — major contributions to Ethereum, Polkadot, Filecoin, and others, plus products in [gaming](https://gaming.chainsafe.io/), [bridging](https://www.sprinter.tech/), NFTs, and [decentralized storage](https://forest.chainsafe.io/). [chainsafe.io](https://chainsafe.io/). -`static/` -- Web-ready assets such as icons (will not be bundled with webpack) +## License +Apache License 2.0 — see [`LICENSE`](./LICENSE). Third-party content carried into this repository (e.g. the `chainsafe-research-plan-implement` skill, adapted from Boris Tane; the Forest AI policy, originally adapted from Ghostty) is credited in [`NOTICE`](./NOTICE) and inline in the relevant files. Derivative works must preserve these attributions per Section 4(d) of the License. diff --git a/docs/VISION.md b/VISION.md similarity index 98% rename from docs/VISION.md rename to VISION.md index 28737bb..d3e599f 100644 --- a/docs/VISION.md +++ b/VISION.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 2 ---- - # Mission, Vision, Core Values ## Mission diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index e00595d..0000000 --- a/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; diff --git a/docs/4_the-formal-stuff/1_360-reviews.md b/career/360-reviews.md similarity index 98% rename from docs/4_the-formal-stuff/1_360-reviews.md rename to career/360-reviews.md index 97a140c..a20e6eb 100644 --- a/docs/4_the-formal-stuff/1_360-reviews.md +++ b/career/360-reviews.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 1 ---- - # 360 Reviews ## Intent @@ -23,4 +19,4 @@ The purpose of our 360 reviews system at ChainSafe is a company-wide “Pit Stop - Protocol, scheduling, deliverables, training dates, and expectations are all defined, set, and communicated beforehand to the entire team (2-3 weeks before the launch) - All supporting materials, guides, aids, and documentation is circulated to all stakeholders before the launch (1-2 weeks before the first day) - A week before the first day of the review, the **Review Cycle** is set up and launched in Lattice -- Final **Reviews Analysts Report** is to be provided to the Leadership and Management teams within the following month of the cycle closure \ No newline at end of file +- Final **Reviews Analysts Report** is to be provided to the Leadership and Management teams within the following month of the cycle closure diff --git a/career/README.md b/career/README.md new file mode 100644 index 0000000..9eb2ea9 --- /dev/null +++ b/career/README.md @@ -0,0 +1,33 @@ +# Career & People + +Career-development and people-process reference for ChainSafe engineering: the engineering ladders, the 360-review cadence, and the surrounding people-ops policies. + +> **In one line:** How growth, leveling, and review work at ChainSafe. People-process reference, adjacent to the engineering-practice core — not part of the agent-facing operator/agent contract. + +## Scope + +This directory documents how individuals grow and are evaluated at ChainSafe. It is written for humans — engineers thinking about their own progression, and managers running leveling and review conversations. Unlike the rest of the handbook, it is not agent-facing guidance, so it is kept deliberately separate from `operating-model/`, `invariants/`, and the language pages. + +The content describes the framework and the process, not individual people or compensation. + +## Contents + +- [`360-reviews.md`](./360-reviews.md) — purpose, goals, and setup of ChainSafe's 360-review system. +- [`career-development/`](./career-development/) + - [`introduction.md`](./career-development/introduction.md) — Engineering Ladders framework: levels, axes, glossary. + - [`how-to.md`](./career-development/how-to.md) — how individuals and managers use the framework. + - [`engineering.md`](./career-development/engineering.md) — engineering role ladder (Associate → Distinguished). + - [`engineering-management.md`](./career-development/engineering-management.md) — engineering management ladder. + - [`research.md`](./career-development/research.md) — research role ladder. + - [`assets/`](./career-development/assets/) — role-card images and radar-chart templates. +- [`process-and-policy.md`](./process-and-policy.md) — education budget and license-request policy. + +## Reading order + +For a new ChainSafer or anyone trying to understand the system from scratch: + +1. [`career-development/introduction.md`](./career-development/introduction.md) — what the framework is, what the axes mean. +2. [`career-development/how-to.md`](./career-development/how-to.md) — how to apply it from either side (individual or manager). +3. The role page that fits the function: [engineering](./career-development/engineering.md), [engineering-management](./career-development/engineering-management.md), or [research](./career-development/research.md). +4. [`360-reviews.md`](./360-reviews.md) — the company-wide review cadence the ladder feeds into. +5. [`process-and-policy.md`](./process-and-policy.md) — the surrounding people-ops policies (education, licenses). diff --git a/docs/4_the-formal-stuff/2_career-development/assets/01.assosiate-se-rnd.jpg b/career/career-development/assets/01.assosiate-se-rnd.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/01.assosiate-se-rnd.jpg rename to career/career-development/assets/01.assosiate-se-rnd.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/01.assosiate-se.jpg b/career/career-development/assets/01.assosiate-se.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/01.assosiate-se.jpg rename to career/career-development/assets/01.assosiate-se.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/02.se-rnd.jpg b/career/career-development/assets/02.se-rnd.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/02.se-rnd.jpg rename to career/career-development/assets/02.se-rnd.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/02.se.jpg b/career/career-development/assets/02.se.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/02.se.jpg rename to career/career-development/assets/02.se.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/03.senior-se-rnd.jpg b/career/career-development/assets/03.senior-se-rnd.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/03.senior-se-rnd.jpg rename to career/career-development/assets/03.senior-se-rnd.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/03.senior-se.jpg b/career/career-development/assets/03.senior-se.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/03.senior-se.jpg rename to career/career-development/assets/03.senior-se.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/04.principal-se-rnd.jpg b/career/career-development/assets/04.principal-se-rnd.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/04.principal-se-rnd.jpg rename to career/career-development/assets/04.principal-se-rnd.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/04.principal-se.jpg b/career/career-development/assets/04.principal-se.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/04.principal-se.jpg rename to career/career-development/assets/04.principal-se.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/05.distinguished-se-rnd.jpg b/career/career-development/assets/05.distinguished-se-rnd.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/05.distinguished-se-rnd.jpg rename to career/career-development/assets/05.distinguished-se-rnd.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/05.distinguished-se.jpg b/career/career-development/assets/05.distinguished-se.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/05.distinguished-se.jpg rename to career/career-development/assets/05.distinguished-se.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/06.em.jpg b/career/career-development/assets/06.em.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/06.em.jpg rename to career/career-development/assets/06.em.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/07.senior-em.jpg b/career/career-development/assets/07.senior-em.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/07.senior-em.jpg rename to career/career-development/assets/07.senior-em.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/08.head.jpg b/career/career-development/assets/08.head.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/08.head.jpg rename to career/career-development/assets/08.head.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/eng-chart.jpg b/career/career-development/assets/eng-chart.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/eng-chart.jpg rename to career/career-development/assets/eng-chart.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/rnd-chart.jpg b/career/career-development/assets/rnd-chart.jpg similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/rnd-chart.jpg rename to career/career-development/assets/rnd-chart.jpg diff --git a/docs/4_the-formal-stuff/2_career-development/assets/roles-progression.png b/career/career-development/assets/roles-progression.png similarity index 100% rename from docs/4_the-formal-stuff/2_career-development/assets/roles-progression.png rename to career/career-development/assets/roles-progression.png diff --git a/career/career-development/engineering-management.md b/career/career-development/engineering-management.md new file mode 100644 index 0000000..92e8ea9 --- /dev/null +++ b/career/career-development/engineering-management.md @@ -0,0 +1,35 @@ +# Engineering Manager Roles + +## Engineering Manager + +- **Impact** → **Stream**: makes an impact on the whole Stream, not just on specific parts of it +- **Technical Expertise** → **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream +- **System** → **Owns**: owns the production operation and monitoring of the system and is aware of its SLAs +- **People** → **Manages**: manages the team members' career, expectations, performance and level of happiness +- **Process** → **Challenges**: challenges the SDLC processes on a Stream level, looking for ways to improve them + +![assets/06.em.jpg](assets/06.em.jpg) + +--- + +## Senior Engineering Manager + +- **Impact** → **Program (Multiple Streams)**: makes an impact not only their Stream but also on other Streams in the same or other Programs +- **Technical Expertise** → **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream +- **System** → **Evolves**: evolves the architecture to support future requirements and defines its SLAs +- **People** → **Manages**: manages the team members' career, expectations, performance and level of happiness +- **Process** → **Adjusts**: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes + +![assets/07.senior-em.jpg](assets/07.senior-em.jpg) + +--- + +## Engineering Head + +- **Impact** → **Multiple Programs**: makes an impact on more than one Programs +- **Technical Expertise** → **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream +- **System** → **Evolves**: evolves the architecture to support future requirements and defines its SLAs +- **People** → **Manages**: manages the team members' career, expectations, performance and level of happiness +- **Process** → **Defines**: defines the right processes for the Program maturity level, balancing agility and discipline + +![assets/08.head.jpg](assets/08.head.jpg) diff --git a/career/career-development/engineering.md b/career/career-development/engineering.md new file mode 100644 index 0000000..343a08a --- /dev/null +++ b/career/career-development/engineering.md @@ -0,0 +1,59 @@ +# Engineering Roles + +## Associate Engineer + +- **Impact** → **Component**: makes an impact on one or more components of the system +- **Technical Expertise** → **Adopts**: actively learns and adopts the architectural approaches and tools defined by the Stream +- **System** → **Enhances**: successfully pushes new features and bug fixes to improve and extend the system +- **People** → **Learns**: quickly learns from others and consistently steps up when it is required +- **Process** → **Follows**: follows the SDLC processes on a Stream level, delivering a consistent flow of features to production + +![assets/01.assosiate-se.jpg](assets/01.assosiate-se.jpg) + +--- + +## Engineer + +- **Impact** → **Stream**: makes an impact on the whole Stream, not just on specific parts of it +- **Technical Expertise** → **Specializes**: is the go-to person for one or more architecture domains and takes initiative to learn new ones +- **System** → **Designs**: designs and implements medium to large size features while reducing the system's tech debt +- **People** → **Supports**: proactively supports other team members and helps them to be successful +- **Process** → **Enforces**: enforces the SDLC processes on a Stream level, making sure everybody understands the benefits and trade offs + +![assets/02.se.jpg](assets/02.se.jpg) + +--- + +## Senior Engineer + +- **Impact** → **Stream**: makes an impact on the whole Stream, not just on specific parts of it +- **Technical Expertise** → **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream +- **System** → **Owns**: owns the production operation and monitoring of the system and is aware of its SLAs +- **People** → **Mentors**: mentors others to accelerate their career-growth and encourages them to participate +- **Process** → **Challenges**: challenges the SDLC processes on a Stream level, looking for ways to improve them + +![assets/03.senior-se.jpg](assets/03.senior-se.jpg) + +--- + +## Principal Engineer + +- **Impact** → **Program (Multiple Streams)**: makes an impact not only their Stream but also on other Streams in the same or other Programs +- **Technical Expertise** → **Masters**: has very deep knowledge about the whole tech stack of the system +- **System** → **Evolves**: evolves the architecture to support future requirements and defines its SLAs +- **People** → **Mentors**: mentors others to accelerate their career-growth and encourages them to participate +- **Process** → **Adjusts**: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes + +![assets/04.principal-se.jpg](assets/04.principal-se.jpg) + +--- + +## Distinguished Engineer + +- **Impact** → **Multiple Programs**: makes an impact on more than one Programs +- **Technical Expertise** → **Creates**: designs and creates new architecture parts that are widely used either by the Streams within or outside the Program +- **System** → **Leads**: leads the technical excellence of the system and creates plans to mitigate outages +- **People** → **Coordinates**: coordinates team members providing effective feedback and moderating discussions +- **Process** → **Defines**: defines the right processes for the Program maturity level, balancing agility and discipline + +![assets/05.distinguished-se.jpg](assets/05.distinguished-se.jpg) diff --git a/docs/4_the-formal-stuff/2_career-development/2_how-to.md b/career/career-development/how-to.md similarity index 80% rename from docs/4_the-formal-stuff/2_career-development/2_how-to.md rename to career/career-development/how-to.md index 988a3bd..78a2d51 100644 --- a/docs/4_the-formal-stuff/2_career-development/2_how-to.md +++ b/career/career-development/how-to.md @@ -1,42 +1,36 @@ ---- -sidebar_position: 2 ---- - # How to Use Engineering Ladders There is only a slight difference in the usage of EL depending on if you are looking at it from the personal or direct report perspective. ## Individual -As an Individual you already have your "shape" given to you by your manager. -:::info -If you don't have your representation ("shape") on the EL diagram please ask your manager to provide you with the most relevant one. -::: +As an Individual you already have your "shape" given to you by your manager. + +> If you don't have your representation ("shape") on the EL diagram please ask your manager to provide you with the most relevant one. If you have an aspiration and desire to grow please choose your role type out of the currently available: - - [Engineering Roles](engineering) - - [Research Roles](research) (If you are in the Research Function) - - [Engineering Management Roles](engineering-management) +- [Engineering Roles](./engineering.md) +- [Research Roles](./research.md) (If you are in the Research Function) +- [Engineering Management Roles](./engineering-management.md) In order to qualify for the desired position you need to hit at least 3 points out of 5 of the reference shape. -For example, in order to qualify for the Senior Engineer, your "shape" needs to intersect with the [Reference one](engineering#senior-engineer) in 3 points out of Evangelizes, Owns, Mentors, Challenges, Stream. +For example, in order to qualify for the Senior Engineer, your "shape" needs to intersect with the [Reference one](./engineering.md#senior-engineer) in 3 points out of Evangelizes, Owns, Mentors, Challenges, Stream. Nonetheless, meeting 3 out of 5 requirements does not mean that you are immediately promoted. It is necessary but not sufficient, it can depend on the role complexity and it's up to the manager to evaluate which requirements weigh more. All the promotions happen following a manager's decision and company promotion rules. -If you see that some levels need to be gained to meet the necessary shape requirements, check definitions on the missing levels and speak with your manager to clarify what those definitions mean in the context of a domain (Program or a Stream you are working in) or professional (hard skills specialization) knowledge. +If you see that some levels need to be gained to meet the necessary shape requirements, check definitions on the missing levels and speak with your manager to clarify what those definitions mean in the context of a domain (Program or a Stream you are working in) or professional (hard skills specialization) knowledge. Create a Personal Development Plan with your manager and follow its progress via 1:1s and other dedicated meetings. ## Manager -:::info -Remember that all the promotions are happening in accordance with the promotional cycle rules. -::: + +> Remember that all the promotions are happening in accordance with the promotional cycle rules. As a manager, make sure that you have all your direct reports "shapes". -For each of the direct reports whose career development is entrusted to you, assess the difference between their current shape and the reference one. +For each of the direct reports whose career development is entrusted to you, assess the difference between their current shape and the reference one. See what levels are missing for each individual when working on their growth plan Check those level definitions and try to separate them by domain or professional knowledge relevance. Levels are intentionally loosely defined so they can be adapted to the needs and requirements of the specificity of the professional knowledge (front-end or backend in general, smart contract development, or something more narrow based on your team engineering specification). For the domain knowledge apply the Stream or a Program context your direct report is involved in. If necessary seek help from the Program or a Stream Leads. For the professional knowledge develop the plan personally. If necessary, seek help from your manager. @@ -57,5 +51,3 @@ Blank charts can be found below for each type of ChainSafe engineering ladders. ### Research Chart ![assets/rnd-chart.jpg](assets/rnd-chart.jpg) - ---- \ No newline at end of file diff --git a/docs/4_the-formal-stuff/2_career-development/1_introduction.md b/career/career-development/introduction.md similarity index 84% rename from docs/4_the-formal-stuff/2_career-development/1_introduction.md rename to career/career-development/introduction.md index 4faa063..6b16635 100644 --- a/docs/4_the-formal-stuff/2_career-development/1_introduction.md +++ b/career/career-development/introduction.md @@ -1,8 +1,3 @@ ---- -sidebar_position: 1 -title: "Introduction" ---- - # Career Development We want everyone at ChainSafe to have a sense of how they can grow and challenge themselves. From a career perspective, this means providing a clear sense of how an employee can progress within the organization. To facilitate this within Engineering, we have defined Engineering Ladders Framework (see [Acknowledgments](#acknowledgments) for more details). @@ -17,9 +12,9 @@ Each of this direction represents a sequence of roles and the attributes typical Current roles progression assumes following roles: - - [Engineering Roles](engineering) - - [Research Roles](research) - - [Engineering Management Roles](engineering-management) + - [Engineering Roles](./engineering.md) + - [Research Roles](./research.md) + - [Engineering Management Roles](./engineering-management.md) Roles described here serve strictly as a reference and it is expected for each individual to have a unique shape on this chart. A promotion to the next ladder requires meeting ⅗ axes. @@ -31,7 +26,7 @@ While assigning levels to each axis make sure the meaning and definitions of sel ## Levels -Currently we differentiate [two charts](how-to#competence-charts) that describes levels for different functions. One chart relates to [Engineering](engineering) and another to [Research](research). [Engineering Management](engineering-management) career progression built with the Engineering chart and effectively relates to both functions. +Currently we differentiate [two charts](./how-to.md#competence-charts) that describes levels for different functions. One chart relates to [Engineering](./engineering.md) and another to [Research](./research.md). [Engineering Management](./engineering-management.md) career progression built with the Engineering chart and effectively relates to both functions. Our engineering ladders have the following 5 axes (categories): - **Technical Expertise**: knowledge of the stack and tools being specialized @@ -45,7 +40,8 @@ For the Engineering verticals the 5th axis is: And for the Research the 5th axis is: - **Research Methodology**: knowledge and ability to conduct a research -### Technical Expertise +### Technical Expertise + 1. **Adopts**: actively learns and adopts the architectural approaches and tools defined by the Stream 2. **Specializes**: is the go-to person for one or more architecture domains and takes initiative to learn new ones 3. **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream @@ -53,13 +49,15 @@ And for the Research the 5th axis is: 5. **Creates**: designs and creates new architecture parts that are widely used either by the Streams within or outside the Program ### People + 1. **Learns**: quickly learns from others and consistently steps up when it is required 2. **Supports**: proactively supports other team members and helps them to be successful 3. **Mentors**: mentors others to accelerate their career-growth and encourages them to participate 4. **Coordinates**: coordinates team members providing effective feedback and moderating discussions -5. **Manages**: manages the team members’ career, expectations, performance and level of happiness +5. **Manages**: manages the team members' career, expectations, performance and level of happiness ### Process + 1. **Follows**: follows the [SDLC](#glossary) processes on a Stream level, delivering a consistent flow of features to production 2. **Enforces**: enforces the [SDLC](#glossary) processes on a Stream level, making sure everybody understands the benefits and trade offs 3. **Challenges**: challenges the [SDLC](#glossary) processes on a Stream level, looking for ways to improve them @@ -67,28 +65,27 @@ And for the Research the 5th axis is: 5. **Defines**: defines the right processes for the Program maturity level, balancing agility and discipline ### Impact + 1. **Component**: makes an impact on one or more components of the system 2. **Stream**: makes an impact on the whole Stream, not just on specific parts of it 3. **Program (Multiple Streams)**: makes an impact not only their Stream but also on other Streams in the same or other Programs 4. **Multiple Programs**: makes an impact on more than one Programs 5. **Company**: makes an impact on most of the Programs - ### System -:::info -Level of the [**Engineering Chart**](how-to#engineering-chart) -::: + +> Level of the [**Engineering Chart**](./how-to.md#engineering-chart). + 1. **Enhances**: successfully pushes new features and bug fixes to improve and extend the system -2. **Designs**: designs and implements medium to large size features while reducing the system’s tech debt +2. **Designs**: designs and implements medium to large size features while reducing the system's tech debt 3. **Owns**: owns the production operation and monitoring of the system and is aware of its [SLAs](#glossary) 4. **Evolves**: evolves the architecture to support future requirements and defines its [SLAs](#glossary) 5. **Leads**: leads the technical excellence of the system and creates plans to mitigate outages - ### Research Methodology -:::info -Level of the [**Research Chart**](how-to#research-chart) -::: + +> Level of the [**Research Chart**](./how-to.md#research-chart). + 1. **Executes**: Given a research question, knows where to look and gather all state-of-the-art articles and papers and summarize them with good coherency 2. **Analyzes**: Is able to filter out relevant and high quality papers, articles, projects. Can sufficiently critique the usefulness of the method. Can write longer articles on a topic explaining complex matters in simpler terms 3. **Proposes**: Can identify possible research directions, formulates research questions, scopes the research work with tangible outputs. Reviews the work of other team members with an eye for detail. Can write academic style papers, perform systematic literature review and publish it @@ -96,14 +93,16 @@ Level of the [**Research Chart**](how-to#research-chart) 5. **Expands**: Pushes the boundaries of fundamental research throughout the community. Veteran and champion known in one or more research domains. Knows the process and importance of high impact publications ## Glossary + The following list contains brief explanations of the mentioned terms or subjects above in the document. -**Stream / Program / Multiple Programs** - more on [ChainSafe OS pages](https://www.notion.so/chainsafe/Core-Concepts-v1-0-1610247189c949fa9692de950518ac53) +**Stream / Program / Multiple Programs** — more on [ChainSafe OS pages](https://www.notion.so/chainsafe/Core-Concepts-v1-0-1610247189c949fa9692de950518ac53). For example: Forest is a stream. Protocol is a program. -**SDLC** - Software Development Life Cycle, including all the software stages +**SDLC** — Software Development Life Cycle, including all the software stages. -**SLA** - Service Level Agreement that outlines what exactly a service provider delivers to the customer (client) +**SLA** — Service Level Agreement that outlines what exactly a service provider delivers to the customer (client). ## Acknowledgments + This framework is based on the open source materials from the [Engineering Ladders GitHub repository](https://github.com/jorgef/engineeringladders). diff --git a/career/career-development/research.md b/career/career-development/research.md new file mode 100644 index 0000000..6283534 --- /dev/null +++ b/career/career-development/research.md @@ -0,0 +1,59 @@ +# Research Roles + +## Associate Engineer in Research + +- **Impact** → **Component**: makes an impact on one or more components of the system +- **Technical Expertise** → **Adopts**: actively learns and adopts the architectural approaches and tools defined by the Stream +- **Research Methodology** → **Executes**: Given a research question, knows where to look and gather all state-of-the-art articles and papers and summarize them with good coherency +- **People** → **Learns**: quickly learns from others and consistently steps up when it is required +- **Process** → **Follows**: follows the SDLC processes on a Stream level, delivering a consistent flow of features to production + +![assets/01.assosiate-se-rnd.jpg](assets/01.assosiate-se-rnd.jpg) + +--- + +## Engineer in Research + +- **Impact** → **Stream**: makes an impact on the whole Stream, not just on specific parts of it +- **Technical Expertise** → **Specializes**: is the go-to person for one or more architecture domains and takes initiative to learn new ones +- **Research Methodology** → **Analyzes**: Is able to filter out relevant and high quality papers, articles, projects. Can sufficiently critique the usefulness of the method. Can write longer articles on a topic explaining complex matters in simpler terms +- **People** → **Supports**: proactively supports other team members and helps them to be successful +- **Process** → **Enforces**: enforces the [SDLC](./introduction.md#glossary) processes on a Stream level, making sure everybody understands the benefits and trade offs + +![assets/02.se-rnd.jpg](assets/02.se-rnd.jpg) + +--- + +## Senior Engineer in Research + +- **Impact** → **Stream**: makes an impact on the whole Stream, not just on specific parts of it +- **Technical Expertise** → **Evangelizes**: researches, creates proofs of concept and introduces new architectural approaches to the Stream +- **Research Methodology** → **Proposes**: Can identify possible research directions, formulates research questions, scopes the research work with tangible outputs. Reviews the work of other team members with an eye for detail. Can write academic style papers, perform systematic literature review and publish it +- **People** → **Mentors**: mentors others to accelerate their career-growth and encourages them to participate +- **Process** → **Challenges**: challenges the SDLC processes on a Stream level, looking for ways to improve them + +![assets/03.senior-se-rnd.jpg](assets/03.senior-se-rnd.jpg) + +--- + +## Principal Engineer in Research + +- **Impact** → **Program (Multiple Streams)**: makes an impact not only their Stream but also on other Streams in the same or other Programs +- **Technical Expertise** → **Masters**: has very deep knowledge about the whole tech stack of the system +- **Research Methodology** → **Leads**: Has the ability to foresee future impediments in any research undertaking. And if it is worth pursuing. Has a sufficient breadth of domain knowledge to facilitate cross-domain research. Leads and helps other team members develop a critical eye for the work +- **People** → **Mentors**: mentors others to accelerate their career-growth and encourages them to participate +- **Process** → **Adjusts**: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes + +![assets/04.principal-se-rnd.jpg](assets/04.principal-se-rnd.jpg) + +--- + +## Distinguished Engineer in Research + +- **Impact** → **Multiple Programs**: makes an impact on more than one Programs +- **Technical Expertise** → **Creates**: designs and creates new architecture parts that are widely used either by the Streams within or outside the Program +- **Research Methodology** → **Expands**: Pushes the boundaries of fundamental research throughout the community. Veteran and champion known in one or more research domains. Knows the process and importance of high impact publications +- **People** → **Coordinates**: coordinates team members providing effective feedback and moderating discussions +- **Process** → **Defines**: defines the right processes for the Program maturity level, balancing agility and discipline + +![assets/05.distinguished-se-rnd.jpg](assets/05.distinguished-se-rnd.jpg) diff --git a/docs/4_the-formal-stuff/3_process-and-policy.md b/career/process-and-policy.md similarity index 94% rename from docs/4_the-formal-stuff/3_process-and-policy.md rename to career/process-and-policy.md index 800c093..2e19f3d 100644 --- a/docs/4_the-formal-stuff/3_process-and-policy.md +++ b/career/process-and-policy.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 3 ---- - # Processes and Policies ## Education @@ -19,4 +15,4 @@ We want to invest in your potential and not only increase your effectiveness at ## Requesting License -ChainSafe tries to empower you to use tools that boost your productivity. If you need a license, please fill out [this form](https://forms.gle/XbQCW9dvvwmRCCcf6) \ No newline at end of file +ChainSafe tries to empower you to use tools that boost your productivity. If you need a license, please fill out [this form](https://forms.gle/XbQCW9dvvwmRCCcf6) diff --git a/dictionary.txt b/dictionary.txt deleted file mode 100644 index ee04d0b..0000000 --- a/dictionary.txt +++ /dev/null @@ -1,194 +0,0 @@ -.env -.github -1:1s -⅗ -Afri -amongst -backend -Backend -blockchain -blockchains -BLS -breakpoint -bugfix -Buterin -CDN -ChainBridge -ChainSafe -ChainSafe's -ChainSafer -ChainSafers -changelog -Changelog -Changelog -checksums -CLA -CLI -clion -Clion -Clippy -CloudFlare -CloudFlare's -coc-rust-analyzer -codebase -codebases -codeowner -codeowners -configs -Corepack -CSV -CTO -customizable -dApp -DDoS -de -Dependabot -deserialize -DevOps -disempower -Docusarus -Docusaurus -e.g. -E1 -E2 -E3 -E4 -E5 -E6 -EL -Emacs -enablement -ERC20 -Ethereum -Ethereum's -facto -Filecoin -FilSnap -Fioranelli -Frontend -fzf -gitbook -GitBook -GitFlow -GitHub -GITHUB_TOKEN -GitHub's -Gitlab -golangci-lint -GoMock -Goto -gruvbox -EngLadderGraph -html -HTTPS -Init -IntelliJ -IntelliSense -IPFS -JetBrains -Kakoune -Ketelsen -Kettensicherheitsschranksysteme -keypairs -Kusama -Lapce -Lerna -libp2p -LibP2P -lineNumbers -linter -Linter -Linter -linters -linux -lockfile -matcher -matchers -Metamask -middleware -Mina -minimalistic -mockgen -monorepo -Monorepo -Monorepo -monorepos -multichain -mutex -mutexes -natively -Neovim -nerdtree -Netifly -NFT -npm -nx -Observability -ok -oneflow -OneFlow -oneflow_assets -OpenApi -opensource -Organization -Polkadot -Polkadot-Host -PR -PRs -pushback -readme -README -Rebase -Recursiveness -refactorings -reproducibility -RnD -runnable -RustFMT -SDK -SDLC -semver -showLineNumbers -skillset -Slackbot -SLAs -src -SSZ -struct -structs -subpackages -subtest -subtests -Sygma -TBD -testnets -timeframes -TODO -Udemy -UI -unexported -unintuitive -unpatched -urls -USD -v1 -Vimawesome -Vimeo -Vitalik -VSCode -walkthrough -Walkthroughs -web3 -Web3 -Web3 -web3.js -web3.unity -webpack -whitehats -WIP -workspaces -YAML -yarn3 -youcompleteme -YouTube -Zenhub \ No newline at end of file diff --git a/docs/3_development/1_development-flow/1_setup_repository.md b/docs/3_development/1_development-flow/1_setup_repository.md deleted file mode 100644 index 04bee0a..0000000 --- a/docs/3_development/1_development-flow/1_setup_repository.md +++ /dev/null @@ -1,239 +0,0 @@ ---- -sidebar_position: 1 ---- -# Setup GitHub Repository - -These are steps to setup a new repository under the ChainSafe GitHub organization: - -:::info -The org owners are now the Heads of Engineering and they can assist you with any changes you require. -::: - -## Project Creation - -1. Create the project in the ChainSafe organization on GitHub - 1. If you do not have permission reach out to an org owner (see note above). - -## Setup Team Permissions - -1. Go to `Settings` → `Manage Access`. -2. Add the team and give them **Write** permissions. Avoid inviting individuals, there should be a team on the organization that has everyone working on the project. - 1. If the team or the admin team doesn't exist, please reach out to an org owner (see note above) - -![create_repository_assets/Screenshot_2020-05-07_11-28-00.png](create_repository_assets/Screenshot_2020-05-07_11-28-00.png) - -3. Add the admin team (should be `-admin`) and give them **Admin** permissions - -4. Add the **ChainSafe** team with `Read` permissions - -- Note: Adding the **ChainSafe** team will give access to the entire org. If the project is sensitive consider not including this team. - -## Branch Protection - -1. Goto `Settings` → `Branches` -2. If this is a new repository, choose `Add Rule`. In this example you can see a rule already exists for `master` branch, in which case you can select `Edit` to modify it. - -![create_repository_assets/Screenshot_2020-05-12_09-29-27.png](create_repository_assets/Screenshot_2020-05-12_09-29-27.png) - -3. These are the base requirements to ensure at least 1 review is required to merge Pull Requests. - -![create_repository_assets/Screenshot_2020-05-12_09-30-11.png](create_repository_assets/Screenshot_2020-05-12_09-30-11.png) - -Some additional options: - -- **Branch name pattern**: some projects use different branch names. `main` is usually the default branch, but rules may also need to applied to a `develop` or `release` branch -- **Required approving reviews**: this can be increased to a number that makes sense for the team size. This is usually 1-3 for most repositories. -- **Require status checks to pass before merging**: this should be enabled if CI (e.g. GitHub Actions) is used in the repository. - -## Disable Merge Commits & Rebase - -1. Goto `Settings` and scroll down to `Merge button` - - ![create_repository_assets/Screenshot_2020-05-12_09-40-08.png](create_repository_assets/Screenshot_2020-05-12_09-40-08.png) - - -2. Disable `Allow merge commits` and `Allow rebase merging`. Since most repositories use *squash merging* this prevents anyone from accidentally using one of the other options. If the TL has reason to override this they may certainly do so. - -3. Enable `Automatically delete head branches`. This automatically deletes branches once they are merged to help keep the repository organized. - -## Basic README - -Please see other ChainSafe repositories for examples of what to include. - -Gossamer: [https://github.com/chainsafe/gossamer](https://github.com/chainsafe/gossamer) - -Forest: [https://github.com/chainsafe/forest](https://github.com/chainsafe/forest) - -Lodestar: [https://github.com/ChainSafe/lodestar/](https://github.com/ChainSafe/lodestar/) - -## License - -A license file must be added to the root of the repository in a file named `LICENSE`. GitHub will automatically pick this up and display it. It's recommended to also ensure the source code of the repository has matching license headers. Please reach out to `David Ansermino` for more details. - -## Continuous Integration - -A continuous integration (CI) service must be setup before code is committed. We strongly advise using GitHub Actions. Even though you may not know what the repository setup structure may resemble, you will know the basic language that will be used, therefore the most simple CI can be setup: - -1. Include the linter -2. Include your test runner -3. If possible, add a build step - -You should use recommended CI for your programming language which can be found at [Tech Stack](../2_tech-stack/_category_.yml) - -## CLA - -Please use [https://cla-assistant.io/](https://cla-assistant.io/). This will be automatically enabled for all public repositories in the org (status check needs to be required). - -## Code Owners - -Depending on the project, it might make sense to add a code owners file. Please reference the [GitHub guide](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) for more information. - -## License Checker - -[WIP] - -## Review - -Once everything has been done, and setup, reach out to your Head of Engineering person to double check that everything is setup accordingly. - -## Labels - -
- Click to see labels and their meaning - -### Status - -Status: Breaking Change - -- Added to a PR or issue that would cause a breaking change - -Status: Abandoned - -- Added to a PR or issue is no longer being actively pursued. - -Status: Approved - -- Added to a PR when the required number of approvals have been met. - -Status: Blocked - -- Added to issues and Pull Requests when work can not be continued until another task is completed. - -Status: In Progress - -- Added to issues to signal that its actively being worked on. - -Status: Do not merge - -- Added to Pull Requests that are not allowed to be merged. - -Status: On Ice - -- Added to issues and Pull Requests that are considered important but no longer pursued for the near future. - -Status: Review Needed - -- Added to Pull Requests that need the maintainer(s) to review. - -Status: Changes Requested - -- Added to Pull Requests that require further changes from the contributor. - -Status: Stale - -- Added to issues and Pull Requests if they have not received enough activity. - -Status: Needs Clarification - -- Added to issues that are not clearly understood, and require additional input. - -### Types - -Type: Feature - -- Added to issues and Pull Requests to identify that the change is a new feature. - -Type: Epic - -- Added to issues to encompass many different types of issues together - -Type: Bug - -- Added to issues and Pull Requests if they are addressing a bug - -Type: Enhancement - -- Added to issues and Pull Requests when a change includes improvements or optimizations. - -Type: Maintenance - -- Added to issues and Pull Requests when a change is for repository maintenance, such as CI or linter changes. - -Type: Question - -- Added to issues that are general discussion questions, and don't offer bug reports etc.. - -Type: Documentation - -- Added to issues or Pull Requests that relate to the project wiki, or documentation. - -### Priority Levels - -Priority: P0 - -- Added to issues and Pull Requests relating to a critical severity bugs. - -Priority: P1 - -- Added to issues and Pull Requests relating to a high severity bugs. - -Priority: P2 - -- Added to issues and Pull Requests relating to a medium severity bugs. - -Priority: P3 - -- Added to issues and Pull Requests relating to a low severity bugs. - -
- -## Slack notifications -
- Optional! Click to see. - -### Overview - -There are two methods for receiving various notifications from GitHub via Slack. - -- **Scheduled Reminders**: These allow you receive reminders at some interval about pending PRs on specific repositories in a Slack channel. -- **Slackbot Notifications**: Enabling these will cause actions on GitHub to trigger notifications on Slack. - -### Slackbot Notifications - -The instructions for configuring the GitHub Slackbot can be found here: [https://github.com/integrations/slack#configuration](https://github.com/integrations/slack#configuration) - -A common configuration follows these steps: - -```yaml -/github subscribe owner/repository -/github subscribe owner/repository reviews comments -``` - -You can check which features are enabled in a channel with: - -```yaml -/github subscribe list features -``` -
- - -## Scheduled Reminders - -Scheduled Reminders can be configured at the org level or the team level. It is recommend that you use the team level, as this allows team maintainers to setup and maintain them. - -Instructions for how to configure team level reminders can be found here: - -[Managing scheduled reminders for your team - GitHub Docs](https://docs.github.com/en/organizations/organizing-members-into-teams/managing-scheduled-reminders-for-your-team) - - -Good morning y'all! \ No newline at end of file diff --git a/docs/3_development/1_development-flow/2_development.md b/docs/3_development/1_development-flow/2_development.md deleted file mode 100644 index ec8114d..0000000 --- a/docs/3_development/1_development-flow/2_development.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -sidebar_position: 2 ---- -# Development - -:::caution - If a repository is owned by ChainSafe there is no reason to fork the repository for pull requests. -::: - -:::caution - The default branch should be `main`. For the majority of the time, pull requests will be merged into the `main` branch. -::: - - -## 1. Create a branch off of `main` - -### Personal Branches - -Should follow the format `/` for example: `greg/create-readme`. You can use your username, or some other unique identifier, but please keep it consistent. The reason for this, is that git stores branches in this format, when it views a `/` its assumed to be a directory. Thus when you look at a git project `.git/refs/heads` you will see everyone has their own folder with their branches! - -### Release Branches - -When making a release, a corresponding tag should be created using git ex: `git tag v0.23.1-rc`. In the case where a previous build needs to be back ported, a release branch should be created with the prefix `release` and the corresponding version number e.g.: `release/v0.23.1-rc`. - - -## 2. Opening a PR (Pull Request) on GitHub - -When opening a pull request there are two types that can be opened: draft and regular. If you are prepping for a new release, or you are migrating a codebase, opening a draft PR is a great way for publicly showing the current development status of that given milestone. When a branch is feature complete, and has been adequately tested then you should open up a regular PR. - -:::tip - If you are making changes to the GitHub Actions, a great way to debug would be to use [`act`](https://github.com/nektos/act) to test the issues before making multiple commits. -::: - -## 3. Writing a title & description - -Please make the title clean and concise, preferably explaining what the objective of the pieces of committed code are doing. Some things to know: - -- A good example message: `Add support for USD to ETH conversion` - -Our repositories typically have a template for pull requests, therefore writing the body of a pull request should be straightforward. If the repositories doesn't, a clear concise explanation of the changes made should be included in bullet points, and any relevant issues should be closed following the format `Closes #45`. - -## 4. Submit for review - -- Add the relevant team members (or the team) for review. -- Add the according labels based on the project -- Ensure you adhere to the repositories PR template. - - If a template is not provided contact you Tech Lead or Project Manager for insights. -- Always ensure you are descriptive, when explaining the nature of your pull request. - -## 5. Approaches in use - -In many of the ChainSafe development cycles OneFlow approach is used. You can find more detailed [ description about OneFlow here](/pages/oneflow). diff --git a/docs/3_development/1_development-flow/3_peer-reviews/1_documentation.md b/docs/3_development/1_development-flow/3_peer-reviews/1_documentation.md deleted file mode 100644 index 0788188..0000000 --- a/docs/3_development/1_development-flow/3_peer-reviews/1_documentation.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 3 ---- -# Documentation - -:::note -Document everything, communicate with your team transparently, review together. -::: - -- Ensure readability is retained in code e.g. complex nested ternary operators should have a comment note -- Ensure [adequate testing](/development/quality_assurance/manual-test-case-guidelines) exists where needed -- Code change requests include a summary of work which outlines the objectives, decisions & considerations for the code change. Examples: - - This PR's objective was to implement middleware for logging, this was completed however presentation & storage of logs is incomplete pending discussion. Certain components are outside the logging scope at the moment. - - This PR includes minor styling tweaks on the desktop & mobile navigation menus, refactored navigation list logic. - - or simply add a [PR template](https://github.com/ChainSafe/engineering-handbook/blob/main/.github/PULL_REQUEST_TEMPLATE.md) with a description and issue reference diff --git a/docs/3_development/1_development-flow/3_peer-reviews/2_reviewer-guide.md b/docs/3_development/1_development-flow/3_peer-reviews/2_reviewer-guide.md deleted file mode 100644 index ddacff4..0000000 --- a/docs/3_development/1_development-flow/3_peer-reviews/2_reviewer-guide.md +++ /dev/null @@ -1,169 +0,0 @@ ---- -sidebar_position: 3 ---- -# Reviewer Guide - -The following guide for reviewers is mostly a condensed and customized version of [Google’s code review best practices](https://google.github.io/eng-practices/review/reviewer/). For additional context, we recommend reading the full guide, but here are the most important points. - -## The goal of the code review - -In general, reviewers should favor approving a code change request once it is in a state where it definitely improves the overall code health of the system being worked on, even if the code change isn’t perfect. - -There is no such thing as “perfect” code — there is only better code. Reviewers should not require the author to polish every tiny piece, but rather reviewers should balance out the need to make forward progress compared to the importance of the changes they are suggesting. - -Reviewers can always leave comments — nitpicking, preferences, or comments that teaches engineers something new — but they should prefix those comments with “nit:” (nitpicking) suggesting to authors that they can ignore such comments. - -## Principles - -- Technical facts and data overrule opinions and personal preferences. -- If there are a few equally valid options when it comes to software design, we should respect the author’s creativity. -- A style guide is an absolute authority. Then the current codebase. Then the author’s preference. More often than not, we will have an older codebase that is not aligned with our style guides. It is up to the team to decide the overall strategy when addressing such cases. - -## What to look for in a code review - -### Good things - -If we see something nice in the code change request we should leave a comment. Code review is too focused on mistakes. If we encourage people when they do something good there is a higher chance they will repeat them. Don’t forget to add why you like it. Why is always important. - -### Design - -The most important thing to cover in a review is the overall design of the code change request and readability. Do the interactions of various pieces of code in the request make sense? Does this change belong in our codebase, or in a library? - -Readability is even more important than DRY. - -### Functionality - -Does this code change do what the developer intended? Is what the developer intended good for the users of this code? The “users” are usually both end-users and developers (who will have to “use” this code in the future) - -### Complexity - -Is the code change more complex than it should be? We should check this at every level of the code change request — are individual lines too complex? Are functions too complex? “Too complex” usually means “can’t be understood quickly by code readers”. It can also mean that developers are likely to introduce bugs when they try to call or modify this code. - -:::note -A particular type of complexity is **over-engineering**, where developers have made the code more generic than it needs to be, or added functionality that isn’t presently needed by the system. Reviewers should be especially vigilant about over-engineering. -::: - -We should encourage engineers to solve the problem they know needs to be solved now, not the problem that the developer speculates might need to be solved in the future. The future problem should be solved once it arrives and we can see its actual shape and requirements in the physical universe. - -If we can’t understand the code, it’s very likely that other developers won’t either! It is often that the code is too complex, not understanding the code and asking for clarification is the right thing to do. - -### Naming - -Did an engineer pick good names for everything? A good name is long enough to fully communicate what the item is or does, without being so long that it becomes hard to read. - -### Comments - -Are all the comments actually necessary? Usually, comments are useful when they explain why some code exists, and should not be explaining what some code is doing. The exceptions are regular expressions and hard-to-understand algorithms; ‘what’ is desirable with such code. - -### Every line - -In the general case, we should look at every human-written line of code that we have been assigned to review. Obviously, some code deserves more careful scrutiny than other code, but we should at least be sure that we understand what all the code is doing. - -### Context - -Sometimes it is important to understand the underlying context. Often it's a good practice to pull code changes and check how they sit in the overall surroundings and files/structure. - -## Navigating a code change request - -We should always start with the main part of the code change request, the one that does the heavy lifting. This will give us a better context later when we start reviewing supporting and secondary changes. - -If we see issues with the main part we should stop and send our comments immediately to the author. In fact, reviewing the rest of the request might be a waste of time, because if the design problems are significant enough, a lot of the other code under review is going to disappear and not matter anyway. This will also give an opportunity for engineers to start on any major re-work of the code change as soon as possible. - -## Speed of the code review - -### Why should code reviews be fast - -Because the team is the most important! If code reviews are slow, few things will happen for sure: - -- the author will start working on something else while waiting, and keep forgetting the context -- the author will finally get the reviewer’s feedback, but now he is in the middle of something else. Days will creep in. -- then the author will need to refresh his memory and address changes, making the reviewer forget about the context. -- the team will lose time and small cracks of frustration and unhappiness will appear in the team. - -This is only worse if more reviewers are assigned. We will waste significant time on this context switching. It is a very inefficient process! - -### How fast should code reviews be - -If we are not in the middle of a focused task, we should do a code review shortly after it comes in. - -One business day is the maximum time it should take to respond to a code review request (i.e., the first thing the next morning). - -Following these guidelines means that a typical code change request should get multiple rounds of review (if needed) within a single day. - -:::note -If we are in the middle of a focused task, such as writing code, we shouldn’t interrupt ourselves to do a code review. Instead, we should wait for a breakpoint in our work to respond to code change request. -::: - -### Fast responses - -When we talk about fast code reviews, we are mainly talking about the response time. We should take time when reviewing the actual code change request. We need to fully understand the code. Ideally, the whole process should be fast. Remember, the code change doesn’t have to be perfect! - -:::note -If we are too busy to do a full review, we can still send a quick response that lets the developer know when we will get to it. Or we can suggest another reviewer! We should delegate, and don’t allow the code change request to sour for days. -::: - -### Large code change requests - -Are unacceptable and reviewers have the right to break the fast code review rule. Usually the way-to-go is to ask the author to split the code change into smaller requests (all branches should be branched from single/main branch for that feature). This way, all requests can be reviewed in a single day and when they're merged, the feature is complete and large code change is more-or-less already reviewed, so we only need to do a simple final check. - -## How to write code review comments - -### 3 magic questions we should always ask ourselves - -Always: - -1. is it kind -2. is it an absolute truth -3. is it necessary - -### Courtesy - -In general, it is important to be [courteous and respectful](https://chromium.googlesource.com/chromium/src/+/master/docs/cr_respect.md) while also being very clear and helpful to the developer whose code we are reviewing. One way to do this is to be sure that we are always making comments about the code and never making comments about the developer. - -> Bad: “Why did you use threads here when there’s obviously no benefit to be gained from concurrency?” - -> Good: “The concurrency model here is adding complexity to the system without any actual performance benefit that I can see. Because there’s no performance benefit, it’s best for this code to be single-threaded instead of using multiple threads.” - -### Use I messages - -We should always formulate our feedback from our point of view by expressing our personal thoughts, feelings, and impressions because it’s hard for the author to argue against our personal feelings since they are subjective. - -> Wrong: “You are writing cryptic code.” - -> Right: “It’s hard for me to grasp what’s going on in this code.” - -### Explain why - -One thing we can notice about the “good” example from above is that it helps the developer understand why we are making our comment. - -### Giving guidance - -In general, it is the developer’s responsibility to fix a code change request, not the reviewer’s. We are not required to do a detailed design of a solution or write code for the developer. - -We should also respect the author’s creativity, meaning that we should point problems but refrain from giving exact solutions. It is not fun for the authors if somebody else is telling them how to do something. Only if the author is stuck, we should give more guidance. - -### Accepting explanations - -If we ask a developer to explain a piece of code that we don’t understand, that should usually result in them rewriting the code more clearly. Occasionally, adding a comment in the code is also an appropriate response, as long as it’s not just explaining overly complex code. - -Explanations written only in the code review tool are not helpful to future code readers. Except in situations where we are unfamiliar with the code, and others are. - -## Handling pushback in code reviews - -### Who is right - -When a developer disagrees with our suggestions, we should take a moment to consider if they are correct. Often, they are closer to the code than we are, so they might really have a better insight. If we still think that we are right, we should explain further why. We should just remember to be polite and mature. - -### Cleaning it up later - -Often, authors will ask if they can clean something later. In the following days, or next code change requests. This really depends on what your process looks like and how strict it is. If it is not strict, this will rarely happen. We should be cautious when approaching will-do-it-later actions. - -## Resolving conversations - -The reviewer who started the conversation must be the one who resolves it. **Nobody else** can resolve the conversation. - -## References - -https://google.github.io/eng-practices/review/reviewer/ - -https://phauer.com/2018/code-review-guidelines/#be-humble diff --git a/docs/3_development/1_development-flow/3_peer-reviews/3_author-guide.md b/docs/3_development/1_development-flow/3_peer-reviews/3_author-guide.md deleted file mode 100644 index 300a8e2..0000000 --- a/docs/3_development/1_development-flow/3_peer-reviews/3_author-guide.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -sidebar_position: 3 ---- -# Author Guide - -The guide for authors is a mix of Google’s code review best practices and our own. We still recommend that you read Google’s [version](https://google.github.io/eng-practices/review/developer/). - -## Communication - -While platforms like GitHub allow selecting peer reviewers, additionally ask a teammate on the relevant team communication channel for a review. This ensures the request is clear and gives transparency to the rest of your team if commentary or considerations need to be made. - -## Walkthroughs - -Walkthroughs are peer programming for reviews. If possible or required, ask for a walkthrough within your team. If your teammate has the capacity, reviewing together allows you to share the context of your work with your reviewer. - -## Requesting Reviews - -If a project isn't setup with [codeowners](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) when you open a code change request, and mark it ready for review, you'll need to get your peers to review it. Every repository should have two different GitHub teams added to it: -- `project_name-admins` - - This team is typically comprised of the project's administrative staff or senior developers who have overarching control and responsibilities over the repository. Members of this team are usually responsible for more critical aspects of the project, such as: - - Approving or merging code change requests that may have significant implications on the project's direction or stability. - - Managing access permissions for the repository, ensuring that contributors have the appropriate level of access according to their roles and responsibilities. - - Configuring repository settings, including protection rules for branches, integration of CI/CD pipelines, and setting up or modifying codeowner rules. - - Handling administrative tasks such as managing team memberships, resolving conflicts, and enforcing coding standards or guidelines. - - Essentially, this team acts as the gatekeepers of the project, ensuring that changes align with the project's goals and maintain its integrity. -- `project_name` - - This team usually consists of the regular contributors or developers working on the project. They may have varying levels of experience and responsibility, but all contribute to the development and progress of the project. The roles of this team typically involve: - - Writing code, fixing bugs, and implementing new features or enhancements. - - Reviewing code submitted by peers to ensure quality, consistency, and that it adheres to the project's coding standards. - - Participating in discussions about the project's direction, design decisions, and potential improvements. - - When a code change request is marked ready for review without specific codeowners set up, requesting a review from the project_name team allows the whole team to receive a notification. This practice encourages collective code review and collaboration, ensuring that multiple eyes review the changes before they are merged into the main codebase. It helps maintain code quality and fosters a collaborative team environment. - -By structuring GitHub teams in this way, projects can benefit from clear separation of responsibilities, efficient management of access controls, and an inclusive environment where all team members are encouraged to participate in the review process. - -## We are working on a feature, how to start - -We should always start with the main part of the code change, the one that is the core of the whole feature. - -**We might create a code change request immediately after we are comfortable with the main part to get early feedback.** We should just remember to explicitly describe such requests. - -The alternative is highly inefficient where we build the entire feature only to find out that our foundation is wrong and consequently all the secondary code around that foundation is wasted. - -We can still work on secondary code while the main feature is being reviewed because we must get the feedback in 1 business day. - -## Small and focused code change requests - -### Why write small code change requests - -- Small code changes have a lower mental load. In contrast, large are heavy energy drainers. -- Reviewed more quickly. It’s easier for a reviewer to find five minutes several times to review small code changes than to set aside a 45+ minute block to review a large code change. -- Reviewed more thoroughly. With large changes, reviewers and authors tend to get frustrated by large volumes of detailed commentary shifting back and forth — sometimes to the point where important points get missed or dropped. -- Less likely to introduce bugs. Since we’re making fewer changes, it’s easier for us and our reviewer to reason effectively about the impact of the code change. -- Less wasted work if they are rejected. If we write a huge code change request and then our reviewer says that the overall direction is wrong, we’ve wasted a lot of work. -- Less blocking on reviews. Sending self-contained portions of our overall change allows us to continue coding while we wait for our current code change in review. - -### What is small and focused - -The right size for a code change request is one self-contained change. This means that: - -- The code change makes a minimal change that addresses just one thing + tests. This is usually just one part of a feature, rather than a whole feature at once. -- The system will continue to work well for its users and for the developers after the code change request is checked in. -- The code change is not so small that its implications are difficult to understand. If we add a new API, we should include a usage of the API in the same code change request so that reviewers can better understand how the API will be used. - -The right question to ask ourselves is: is this change related to this code change or can live on its own. If this can live on its own, we should address this in a separate code change request. - -:::note -Keep in mind that although we have been intimately involved with our code, reviewers often have no context. What seems like an acceptably-sized code change to us might be **overwhelming to our reviewers**. -::: - -### Separate out refactorings - -Focused refactorings should always be a separate code change, containing only refactoring and nothing else! No fixes and features! - -There are some cases where we find that refactoring makes sense along with a feature or a bugfix, but the resulting code change requests should be very small (e.g. if you can do both in less than 50 changed lines, that’s usually ok). - -### When are large code changes okay - -- Small changes across many files, like renaming a function or changing a contract -- Deletion -- Generated code -- Anything that we can scan easily - -### Can’t make it small enough - -Sometimes we will encounter situations where it seems like our code change has to be large. This is very rarely true. Authors who practice writing small code changes can almost always find a way to decompose functionality into a series of small changes. - -Before writing a large code change, consider whether preceding it with a refactoring-only code change could pave the way for a cleaner implementation. - -:::note -If all of these options fail (which should be extremely rare) then get consent from your reviewers in advance to review a large code change, so they are warned about what is coming. -::: - -## Before creating a code change request - -We should check every line one more time. [Double-check](/development/development-flow/peer-reviews/reviewer-guide). JetBrains tools have a nice diff, or we can open a draft PR on GitHub and check everything there. - -We can't emphasize more how important that is for the team. We shouldn't just throw out our code change request to reviewers as soon as we stop coding and hope for the best, but rather invest some time and see if we can improve anything. There is nothing more time-consuming for a team than millions of comments and code change rewrites. - -## How to handle reviewer comments - -### We should not take it personally - -The goal of a review is to maintain the quality of our codebase and our products. When a reviewer provides a critique of your code, we should think of it as their attempt to help us, the codebase, and ChainSafe, rather than as a personal attack on us or our abilities. - -:::note -We should **never respond in anger to code review comments.** That is a serious breach of professional etiquette that will live forever in the code review tool. Even if reviewers expressed their frustration first. -::: - -### We should fix the code before commenting - -If a reviewer says that they don’t understand something in our code, our first response should be to clarify the code itself! If the code can’t be clarified, we should add a code comment that explains why the code is there. If a comment seems pointless, only then should our response be an explanation in the code review tool. - -### Authors can never ever resolve conversations - -Only the original reviewer who wrote the comment can resolve the conversation. - -### The proper way of addressing reviewers comments in commits - -All the changes after the code review should go commit-by-commit and not in a single commit with a message “Addressed comments / PR changes / ...”. This way the reviewer can see what we did and why we did it. -Also, it'd be good to leave a link to the commit in the actual conversation. - -This is better because reviewers know that we actually commit our changes. Emoji reactions and other comments don’t necessarily mean the author actually committed changes. - -:::note -We should never ever introduce new code and refactorings (even moving code around) when addressing changes. Because this will just make it harder for reviewers to do their re-review. Remember that our target is to finish the re-review in a single day. Refactoring should be addressed in a new code change request. -::: - -## When can we merge - -We can merge only if all the conversations are resolved and all reviewers approve the code change request. In some cases, reviewers can approve without resolving comments, but the best practice here is for reviewers to resolve all the comments. - -## References - -https://google.github.io/eng-practices/review/developer/ diff --git a/docs/3_development/1_development-flow/3_peer-reviews/_category_.yml b/docs/3_development/1_development-flow/3_peer-reviews/_category_.yml deleted file mode 100644 index 4ed666f..0000000 --- a/docs/3_development/1_development-flow/3_peer-reviews/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 3 -label: 'Peer Reviews' -collapsible: true -collapsed: true -link: null diff --git a/docs/3_development/1_development-flow/_category_.yml b/docs/3_development/1_development-flow/_category_.yml deleted file mode 100644 index f87adc9..0000000 --- a/docs/3_development/1_development-flow/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 3 -label: 'Development Flow' -collapsible: true -collapsed: true -link: null \ No newline at end of file diff --git a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-07_11-28-00.png b/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-07_11-28-00.png deleted file mode 100644 index 21dead2..0000000 Binary files a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-07_11-28-00.png and /dev/null differ diff --git a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-29-27.png b/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-29-27.png deleted file mode 100644 index 0ae2809..0000000 Binary files a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-29-27.png and /dev/null differ diff --git a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-30-11.png b/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-30-11.png deleted file mode 100644 index c41a2a4..0000000 Binary files a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-30-11.png and /dev/null differ diff --git a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-40-08.png b/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-40-08.png deleted file mode 100644 index 92c8cde..0000000 Binary files a/docs/3_development/1_development-flow/create_repository_assets/Screenshot_2020-05-12_09-40-08.png and /dev/null differ diff --git a/docs/3_development/2_tech-stack/Typescript/monorepo.md b/docs/3_development/2_tech-stack/Typescript/monorepo.md deleted file mode 100644 index f103840..0000000 --- a/docs/3_development/2_tech-stack/Typescript/monorepo.md +++ /dev/null @@ -1,198 +0,0 @@ -# Monorepo - -:::note - -At ChainSafe, we used to use `lerna` to manage our monorepos. -It was not ideal but it got the job done. Since `lerna` is being [taken over by nx](https://github.com/lerna/lerna/issues/3121) and her future is not really clear, we decided to switch to `yarn 3` and its workspaces. - -::: -## Template - -:::note - -Template is currently in WIP state. - -::: - - -To speedup setting up monorepo you can use [yarn workspaces typescript template](https://github.com/ChainSafe/yarn-workspaces-typescript-template) -For manual setup or to understate what is all inside template go to **Setup** section - - -## Setup - -### 1. Corepack - -If you are running node@16+, you just need to run `corepack enable`. -If you are running older version, run `npm i -g corepack`. -Make sure you put this in README file for future contributors. - -### 2. Init repository - -- Make sure your root `package.json` contains: - -```json - "packageManager": "yarn@3.4.1", - "workspaces": [ - "packages/*" - ], -``` - -- Create `.yarnrc.yml` file with following content: - -```yaml -# size of cache is not concern if you aren't using zero-installs -compressionLevel: 0 - -enableGlobalCache: true - -nmMode: hardlinks-local - -nodeLinker: node-modules -``` - -- Make sure your `.gitignore` file contains: - -```txt -node_modules -*DS_Store -.idea -.vscode -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/sdks -!.yarn/versions -``` - -You can check out the [FilSnap repository](https://github.com/chainsafe/filsnap) as an example of such a setup. - -## Publishing - -After you [update your versions in](#updating-monorepo-versions) `package.json` files, -you can publish all packages by running `yarn workspaces foreach -v --exclude root npm publish --access public` - -or in GitHub Actions: - -```yaml - - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} - if: ${{ steps.release.outputs.releases_created }} - run: | - echo npmAuthToken: "$NODE_AUTH_TOKEN" >> ./.yarnrc.yml - - - run: yarn workspaces foreach -v --exclude root npm publish --access public - if: ${{ steps.release.outputs.releases_created }} -``` - -## Caveats - -### Recursiveness - -Let's say you have the following scripts in your root `package.json`: - -```json title="package.json" -{ - "scripts": { - "build": "yarn run build:local", - "build:local": "yarn workspaces foreach -vpt run build" - } -} -``` -:::note - -TBD - -::: - -which you can fix by adding `--exclude root` or by changing build to `yarn workspaces foreach -vpt run build` instead of invoking another script. - - -### Updating yarn version - -Since your yarn version is checked into your GitHub repository it will be consistent across all contributors. -But that also means you need to update it manually every now and then to stay up-to-date. - -### Checksum mismatch - -This might be only temporary but `yarn` has some weird bug where git dependencies are packed (instead of used as it in v1) -and their checksum is not the same on all operating systems. - -An ideal way to fix this is something like this: -```json title="package.json" -{ - "resolutions": { - "web3/bignumber.js": "2.0.8", - "ethereumjs-abi": "0.6.8" - } -} -``` - -This would force usage of the `bignumber.js`, in the `web3` dependency only, to npm version rather than git commit or `ethereumjs-abi` everywhere. - -If you cannot do it you can put `checksumBehavior: "update"` in your `.yarnrc` file. - -## Migration from Lerna - -1. Run `corepack enable` -2. Add `"packageManager": "yarn@3.2.3"` to your package.json (make sure to use latest version) -3. If you used `.npmrc` or `.yarnrc`, you'll need to turn them into [the new format](https://yarnpkg.com/configuration/yarnrc) -4. Add following to your `.yarnrc.yml` file: -```yaml title=".yarnrc.yml" -# size of cache is not concern if you aren't using zero-installs -compressionLevel: 0 - -enableGlobalCache: true - -nmMode: hardlinks-local - -nodeLinker: node-modules -``` -5. Commit the changes so far (package.json, .yarnrc.yml, ...) -6. Run `yarn install` to migrate the lockfile -7. Add the following to `.gitignore`: -``` title=".gitignore" -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/sdks -!.yarn/versions -``` -8. Install the following plugins: -```bash -yarn plugin import interactive-tools -yarn plugin import workspace-tools -yarn plugin import typescript -yarn plugin import https://raw.githubusercontent.com/devoto13/yarn-plugin-engines/main/bundles/%40yarnpkg/plugin-engines.js -``` -9. Delete `lerna.json` and remove `lerna` dependency -10. Add the following to package.json -```json title="package.json" -"private": true, -"workspaces": [ - "packages/*" -], -``` -11. In `package.json` scripts: - 1. replace `lerna run ` with `yarn workspaces foreach -vpt run ` - 2. replace `lerna run --scope ` with `yarn workspace ` -12. Set packages that depend on each other to `"@chainsafe/pkgB": "workspace:^"` - this will force using local packages and will be replaced with a version before publishing -13. Don't forget to do changes in CI if necessary -14. Run `yarn` again to update a lockfile -15. Commit everything - -### Updating monorepo versions - -To enable version commands, you need to install the version plugin: -`yarn plugin import version` - -Make sure to read more about the new workspace resolution option: https://yarnpkg.com/features/workspaces#workspace-ranges-workspace - -#### Independent versioning -If you track versions of your package independently, -you can use `yarn workspace workspace-1 version -i ` -but it's probably better to automate this using [release please](./#cutting-release) - -#### Uniform versioning - -If, on the other hand, you view all your monorepo packages as one cohesive unit with an exact version across the board, you can use the following command to update versions: `yarn workspaces foreach -v version -i 5.0.0`. diff --git a/docs/3_development/2_tech-stack/Typescript/readme.md b/docs/3_development/2_tech-stack/Typescript/readme.md deleted file mode 100644 index 81be58c..0000000 --- a/docs/3_development/2_tech-stack/Typescript/readme.md +++ /dev/null @@ -1,253 +0,0 @@ -# Typescript - -Our most notable Typescript stack: -* https://github.com/ChainSafe/lodestar (Ethereum Consensus Client Lodestar) -* https://github.com/ChainSafe/web3.js/tree/4.x (Web3.js) -* https://github.com/ChainSafe/ssz (Simple Serialize library) -* https://github.com/ChainSafe/bls (BLS library) -* https://github.com/ChainSafe/filsnap (Metamask Snap for Filecoin) -* [and others](https://github.com/ChainSafe?q=&type=all&language=typescript&sort=) - -## IDE configuration - -### Visual Studio Code - -You can download it here: https://code.visualstudio.com/ - -It is recommended to install the following extensions: - -* [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - enables highlighting lint errors and fixing them -* [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) - enables advanced git overview -* [DotEnv](https://marketplace.visualstudio.com/items?itemName=mikestead.dotenv) - support for .env files -* [Yaml](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) - support for writing YAML files (useful for GitHub Actions) - -:::note -Visual Studio Code already has basic support for Markdown: https://code.visualstudio.com/docs/languages/markdown#_markdown-preview -::: - -### Others - -If you need a license for your development tooling, [read on how to request one](/the-formal-stuff/process-and-policy#requesting-license)! - -## Linting - -Linting is a critical step in the source code life cycle. As not everyone in a given team will have the same programming approach, enforced linting rules can help keep a codebase consistent. As linting is a static analysis process, it will catch problems in your coding style, but not the logical errors. - -For example, if one developer uses the `forEach` iterator and another uses the `for` loop, linting rules will give feedback to team members, ensuring they follow a consistent pattern. The same applies to documenting the source code, so it's essential to check that the tools have linting support. - -Recommended lint tool is `eslint` with some chosen plugins (like `prettier` for code formatting) and to ensure code style across ChainSafe, we are providing a [shared configuration](https://github.com/ChainSafe/eslint-config) that you can use in your projects as a baseline: - -1. `yarn add --dev eslint@8 @chainsafe/eslint-config` //version depends on version in a shared configuration package.json -2. Create `.eslintrc.js` file with the following contents: - -```js - -module.exports = { - extends: "@chainsafe", -} -``` - -3. add `lint` script in your package.json with command `eslint 'src/**/*.ts'` - -:::note - -If you think some rule is missing or unnecessary, feel free to contribute to https://github.com/ChainSafe/eslint-config - -::: - -## Testing - -:::note - -TBD - -::: - -## Continuous integration - -It is very difficult to develop one-size-fits-all continuous integration, so this is a guideline rather than an actual configuration file. You will see many repositories at ChainSafe modified CI to fit their needs. - -You should almost always use GitHub Actions. Consult with your manager if you need to use something else. - -```yaml title=".github/workflows/ci.yml" -name: 'ci / test' -on: - push: - branches: - - main # runs on push to master, add more branches if you use them - pull_request: - branches: - - '**' # runs on update to pull request on any branch -jobs: - # most basic test job - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - cache: 'yarn' # cache node modules - node-version: lts - - run: yarn run lint # lint code - - run: yarn run build # compile typescript into javascript - - run: yarn run test:unit # run unit tests - - run: yarn run test:integrations # run integration tests tests - - - # run on multiple combinations of os and nodejs - # you should probably consider running checkout and setup-node before it so you cache node modules - test-matrix: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-latest, ubuntu-latest, macos-latest] - node: [14, 16] - fail-fast: true - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - cache: 'yarn' # cache node modules - node-version: ${{ matrix.node }} - - run: yarn run lint # lint code - - run: yarn run build # compile typescript into javascript - - run: yarn run test:unit # run unit tests - - run: yarn run test:integrations # run integration tests tests -``` - -## Releasing npm packages - -::: note This is a mostly automated process to enable consistency and make it hassle-free -to release new versions more often -::: -::: caution Make sure the repository is using squash merging and branching rules as described in [Setup repository section](/development/development-flow/setup_repository)! -::: - -### Semantic Pull Requests - -For automatic releasing and version bumps, you should use semantic Pull Request titles. - -Semantic keywords and their meaning: - -* **fix** - your PR contains a bugfix which will bump a patch version - Example PR: `fix: resolved bug with automatic releasing` -* **feat** - your PR contains a new feature that will bump a minor version - Example PR: `feat: added a new API endpoint` -* **chore** - your PR contains trivial changes like editing README, bumping packages versions etc - Example PR: `chore: bumped typescript dependency` -* **feat!** or **fix!** (notice exclamation)- your PR contains a breaking change which will trigger a major version update * Example PR: `feat!: new API `endpoint, `the `old`` one is` deprecated` - -You can use the following GitHub action to ensure your Pull Requests follow this convention. - -```yaml title=".github/workflows/pr.yml" -name: "Semantic PR" - -on: - pull_request_target: - types: - - opened - - edited - - synchronize - -jobs: - main: - name: Validate PR title - runs-on: ubuntu-latest - steps: - - uses: amannn/action-semantic-pull-request@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - types: | - fix - feat - chore - revert -``` - -### Cutting release {#cutting-release} - -1. Merge Pull Request with semantic title -2. GitHub Actions will open PR with a version bump in package.json and updated CHANGELOG.md -3. After merging the Release Pull Request, the package will be published on npm and a release with the changelog created on GitHub - -Following GitHub action will ensure that the above flow is working. - -:::caution - -Automatic Pull Request cannot trigger workflow so required status checks cannot pass. -You can either remove the requirement for status checks to pass or set GITHUB_TOKEN to your GitHub PAT token. - -::: - -```yaml title=".github/workflows/cd.yml" -name: Release -on: - push: - branches: - - main -jobs: - maybe-release: - name: release - runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - steps: - # you should probably do this after your regular CI checks passes - - uses: google-github-actions/release-please-action@v3 # it will analyze commits and create PR with new version and updated CHANGELOG:md file. On merging it will create github release page with changelog - id: release - with: - release-type: node - package-name: release-please-action - changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":true}]' - - - uses: actions/checkout@v3 - # these if statements ensure that a publication only occurs when - # a new release is created: - if: ${{ steps.release.outputs.release_created }} - - - uses: actions/setup-node@v3 - with: - cache: 'yarn' - node-version: 16 - registry-url: 'https://registry.npmjs.org' - if: ${{ steps.release.outputs.release_created }} - - - run: yarn install --ignore-scripts - if: ${{ steps.release.outputs.release_created }} - - - run: yarn build - if: ${{ steps.release.outputs.release_created }} - - - run: npm publish - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} # use npm "Automation" token and put in GitHub repository secrets under "NPM_TOKEN" - if: ${{ steps.release.outputs.release_created }} -``` - -:::note -Feel free to extend this flow with nightly/alpha/beta releases. -::: - -#### Reverting - -In case of npm publish fails for whatever reason, release-please won't allow you to try to re-run the GitHub action. -Instead, -you should open the "revert" Pull Request either using GitHub or the local git client. - -Before merging it, make sure, you have deleted the git tag and GitHub release upstream. - -### Dependabot - -Dependabot updates may or may not conform to our semantic rules. -The following configuration should ensure this happens: - -```yaml title=".github/.dependabot.yml" -version: 2 -updates: - - package-ecosystem: "yarn" - schedule: - interval: daily - requiredLabels: - - dependencies - commit-message: - prefix: fix - prefix-development: chore - include: scope -``` diff --git a/docs/3_development/2_tech-stack/_category_.yml b/docs/3_development/2_tech-stack/_category_.yml deleted file mode 100644 index 151221b..0000000 --- a/docs/3_development/2_tech-stack/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 1 -label: 'Tech Stack' -collapsible: true -collapsed: true -link: null \ No newline at end of file diff --git a/docs/3_development/2_tech-stack/go.md b/docs/3_development/2_tech-stack/go.md deleted file mode 100644 index 33efffe..0000000 --- a/docs/3_development/2_tech-stack/go.md +++ /dev/null @@ -1,900 +0,0 @@ -# Go - -Our most notable Go projects: - -* [Polkadot Gossamer](https://github.com/ChainSafe/gossamer) -* [ChainBridge Core](https://github.com/ChainSafe/chainbridge-core) -* [and others](https://github.com/chainsafe?q=&type=all&language=go&sort=) - -## IDE configuration - -:::note - -TBD - -::: - -If you need a license for your development tooling, [read on how to request one](/the-formal-stuff/process-and-policy#requesting-license)! - -## Project structure - -### Modules layout perspective - -In the following, we assume your application name is `myapp` and the project name is `github.com/ChainSafe/repo`. - -The file structure should look as follow: - -```s -. -├── .git -├── cmd -| └── myapp -| └── main.go -├── examples -| └── example1 -| └── main.go -├── internal -| ├── config -| | └── config.go -| └── store -| └── store.go -├── pkg -| ├── public1 -| | └── public1.go -| └── public2 -| └── public2.go -├── go.mod -└── go.sum -``` - -The `go.mod` file holds the project name, Go suggested version and dependencies of your Go project. -The `go.sum` should not be modified by hand, and only contains checksums for the dependencies. - -#### The `cmd` directory - -The `cmd` directory contains one directory per application. - -In our case, we only have one application `myapp`, but it can contain multiple programs, for example: - -```s -├── cmd - ├── myapp - | └── main.go - └── myotherapp - └── main.go -``` - -Each application directory should only contain one file: `main.go` - -Each `main.go` file represents the `package main` and should contain only the `main()` function. - -Its code should be minimal, the bulk of the code should reside in the `internal` directory. - -📖 The reading of the `main.go` file should be quick and provide a solid understanding of what the top moving pieces are. - -#### The `internal` directory - -Since Go 1.4, the [internal directory](https://golang.org/doc/go1.4#internalpackages) is treated specially. - -It contains code that can be imported by other parts of the application but **not imported** by other Go projects as a dependency. - -We thus use this directory to place packages internal to the project. - -For example, in our case we have: - -```s -├── internal - ├── config - | └── config.go - └── store - └── store.go -``` - -The `internal/config` and `internal/store` directories contain the `config` and `store` packages respectively. - -Each can be imported for example by `cmd/myapp/main.go` with: - -```go -import ( - "github.com/ChainSafe/repo/internal/config" - "github.com/ChainSafe/repo/internal/store" -) -``` - -But **cannot be imported by another Go project**, that is outside of `github.com/ChainSafe/repo`. - -By default, you should place all your packages in the `internal` directory by creating a directory with the name of the package inside. - -#### The `pkg` directory - -Unlike `internal`, the `pkg` directory is more of a convention name. - -The `pkg` directory is meant to contain packages to be imported by other projects. - -In our example, we have: - -```s -├── pkg - ├── public1 - | └── public1.go - └── public2 - └── public2.go -``` - -We have two packages, `public1` and `public2`. -Each can be imported by any Go project (including this one) with for example - -```go -import ( - "github.com/user/repo/pkg/public1" -) -``` - -⚠️ You should really limit the packages you place in the `pkg` directory. - -Since these are exported to other projects, you should be careful about semver versioning to avoid breaking other Go projects depending on it. - -It's always good practice to have all your packages in the `internal` directory, and only move them to the `pkg` directory once they have been proven to: - -1. Be stable, ideally with full (and *deep*) unit testing coverage -2. Have their exported Go API stable - -#### The `examples` directory - -The `examples` directory should contain runnable examples to showcase your publicly exported Go API from `pkg`. - -Each example should have a descriptive directory name and a runnable `main.go` file with only the `func main()` function. - -For example: - -```s -├── examples - └── example1 - └── main.go -``` - -#### Go libraries - -If you are writing a Go library with a single purpose, you might want to have your exported public Go API at the top level. -For example with this file structure: - -```s -. -├── .git -├── examples -| └── example1 -| └── main.go -├── internal -| ├── package1 -| | └── package1.go -| └── package2 -| └── package2.go -├── api.go -├── go.mod -└── go.sum -``` - -The differences are as follows: - -* no `cmd` directory since this is not a runnable application -* no `pkg` directory since this is a library, all exported Go API should be at the top level to reduce the length of import statements -* `api.go` file containing all your Go public API. It should contain your exported interfaces, constants and constructors. - -Note that most of your code should still reside in the `internal` directory, and you should keep your public Go API to a minimum. - -If it really makes sense, you may have directories at the top level to split the import statements. - -### Business logic perspective - -Beside official package layout recommendations describing packages structure and naming from the Go modules perspective, there is de facto standard named *Standard Package Layout* on how to organize your business logic, storage and abstractions. - -First time concept was described by [Ben Jonson in an article with the same name](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1). Another source of inspiration and a way to grasp the concept can be found in the beautiful [talk of Brain Ketelsen about Go best practices](https://www.youtube.com/watch?v=MzTcsI6tn-0). - -### Other tips - -* Package naming - * Your package name should be the same as the directory containing it, **except for the `main` package** - * Use single words for package names - * Do not use generic names for package names such as `utils` or `helpers` -* Package nesting - * Try to avoid nesting packages by default - * You can nest packages if you have different implementations for the same interface (e.g. a store interface) - * You can nest packages if you start having a lot of Go files (more than 10) and it really does make sense to make subpackages - -## Linting - -Use [golangci-lint](https://golangci-lint.run/): - -```sh -go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46 -``` - -Together with a `.golangci.yml` at the root of your project: - -```yml title=".golangci.yml" -run: - skip-dirs: - - .github - build-tags: - - integration - -linters-settings: - misspell: - locale: UK - -issues: - exclude-rules: - # Do not run these linters for test files - - path: _test\.go - linters: - - dupl - - goerr113 - - containedctx - # Do not require comments for sentinel errors - - text: "exported: exported var Err*" - linters: - - revive - # Allow long lines for //go:generate comments - - linters: - - lll - source: "^//go:generate " - -linters: - # Default linters are enabled and not listed below: - # https://golangci-lint.run/usage/linters/#enabled-by-default - enable: - - asciicheck - - bidichk - - bodyclose - - containedctx - - cyclop - - decorder - - dogsled - - dupl - - durationcheck - - errchkjson - - errname - - exhaustive - - exportloopref - - forcetypeassert - - gci - - gochecknoglobals - - gochecknoinits - - gocognit - - goconst - - gocritic - - gocyclo - - godot - - goerr113 - - goheader - - goimports - - gomnd - - gomoddirectives - - goprintffuncname - - gosec - - grouper - - ifshort - - importas - - ireturn - - lll - - maintidx - - makezero - - misspell - - nakedret - - nestif - - nilerr - - nilnil - - noctx - - nolintlint - - prealloc - - predeclared - - promlinter - - revive - - rowserrcheck - - sqlclosecheck - - tenv - - thelper - - tparallel - - unconvert - - unparam - - wastedassign - - whitespace -``` - -### Linting continuous integration - -For your CI, you should have lint GitHub job. For example: - -```yml title=".github/workflows/lint.yaml" -on: - pull_request: -name: Linting - -jobs: - golangci-lint: - runs-on: ubuntu-latest - steps: - - uses: actions/setup-go@v3 - - uses: actions/checkout@v3 - uses: golangci/golangci-lint-action@v3 - with: - version: v1.45 -``` - -:::caution -Make sure to pin the linter version (`version: v1.45`) since the same linters can behave differently from a version to another. -::: - -## Panic - -In Go, `panic` should only be used when a **programming error** has been encountered. - -For any error caused by external factors such as files or network, you should **NOT panic** and use errors instead. - -An example of such a panic usage would be: - -```go -type logLevel uint8 - -const ( - Info logLevel = iota - Warn - Error -) - -func (l *logLevel) String() string { - switch *l { - case Info: - return "info" - case Warn: - return "warn" - case Error: - return "error" - default: - // we panic since this should never happen - panic(fmt.Sprintf("invalid log level: %d", *l)) - } -} -``` - -A `panic` should be placed such that its trigger condition is so critical that the program should crash and the end user should report it to the programmer. - -Its counterpart `recover` should not really be used, except for testing a panic in test code (or use `assert.PanicsWithValue`). - -## Continuous integration - -:::note -TBD: testing -::: - -* [Linting](#linting-continous-integration) - -## Mocking - -Mocking is useful in Go to mock behavior of Go interfaces for testing. - -### Example production code - -In the following sections, we will use the following example code: - -```go title="something/something.go" -package something - -import ( - "context" - "fmt" -) - -type Fetcher interface { - Fetch(ctx context.Context) (data []byte, err error) -} - -type Parser interface { - Parse(data []byte) (id string, err error) -} - -func something(ctx context.Context, fetcher Fetcher, parser Parser) (id string, err error) { - data, err := fetcher.Fetch(ctx) - if err != nil { - return "", fmt.Errorf("cannot fetch: %w", err) - } - - id, err = parser.Parse(data) - if err != nil { - return "", fmt.Errorf("cannot parse: %w", err) - } - - return id, nil -} -``` - -where we want to test the `something` function using mocks for the `Fetcher` and `Parser` interfaces. - -### Which mocking library - -There are two main Go mocking libraries: - -* [`vektra/mockery`](https://github.com/vektra/mockery) -* [`golang/mock`](https://github.com/golang/mock) - -You should use [`golang/mock`](https://github.com/golang/mock) because: - -* it is more type-safe and auto-completion is better -* its Go API is more stable -* it is more mature and has more star-gazers - -Install it in your repository with: - -```sh -go get github.com/golang/mock -``` - -### Mock generation - -#### Tooling - -Install the `mockgen` CLI from the [`golang/mock`](https://github.com/golang/mock) repository: - -```sh -go install github.com/golang/mock/mockgen@v1.6.0 -``` - -This is to be done only once on your development environment. - -#### File setup - -You should have two files **where the mocks are needed**: - -* `mocks_generate_test.go` -* `mocks_test.go` - -The `mocks_generate_test.go` is a single line file defining what mocks to generate, using a single `//go:generate mockgen` comment-command. - -The `mocks_test.go` is the generate mock code for all the mocks needed by the package. - -For example, to generate mocks for the `Fetcher` and `Parser` interfaces (defined in [the section above](#example-production-code)): - -```go title="something/mocks_generate_test.go" -package something - -//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Fetcher,Parser -``` - -You have to put each interface you want to generate a mock for at the end of the mockgen command, separated by commas. - -In our example case, this is the `something` package name. - -This file setup is designed such that: - -* Mocks are only accessible to test files in the current Go package. Indeed `*_test.go` files are not exported and only accessible by other test files in the same package. This avoids pollution of the package Go API, and possible horrendous package dependencies. -* Minimal amount of files per package, and minimal Git diffs at code evolves -* No effect on Go test coverage, since `*_test.go` files are not included. -* GitHub auto collapses `*mock*` files in the PR diff view, making it easier to review. -* No particular mocking library or style is suggested to the user of the package, since no mock is exported. - -:::caution -NEVER ever export mocks to other packages -::: - -#### Generation command - -Use `go generate -run mockgen ./...` to generate the mocks to `mocks_test.go`. - -#### Generate mocks from other packages - -You should really define interfaces locally in your package and use those to generate mocks. - -Sometimes it however makes sense to use an interface such as `io.Reader` from the standard library. In that case, you can add another line to `mocks_generate_test.go`: - -```go title="something/mocks_generate_test.go" -package something - -//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Fetcher,Parser -//go:generate mockgen -destination=mocks_io_test.go -package $GOPACKAGE io Reader -``` - -Note the destination is now `mocks_io_test.go` to avoid conflicts with `mocks_test.go`. You can specify any import package path instead of `io` if needed. - -### Mock usage - -Now that your mocks are generated, you can use them in your Go tests in the `something` package. - -Let's write a test for our `something` function defined in our example production code: - -```go title="something/something_test.go" -package something - -import ( - "context" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func Test_something(t *testing.T) { - ctrl := gomock.NewController(t) - - ctx := context.Background() - fetcher := NewMockFetcher(ctrl) - fetchCall := fetcher.EXPECT(). - Fetch(ctx). // define the expected argument(s) - Return([]byte{1, 2, 3}, nil) // define the returned values - - parser := NewMockParser(ctrl) - parser.EXPECT(). - Parse([]byte{1, 2, 3}). - Return("123", nil). - After(fetchCall) // you can define the mock calls order with After() - - id, err := something(ctx, fetcher, parser) - - assert.NoError(t, err) - assert.Equal(t, "123", id) -} -``` - -A few important points: - -* **Never** use `gomock.Any()` as argument. Always use concrete, precise arguments. You might need to define a custom GoMock matcher for your argument in some very niche and corner cases. -* **Never** use `.AnyTimes()` on mocks. Always define the number of times a certain mock call should be called, with `.Times(3)` for example. -* **Always** set the `.Return(...)` on the mock if the function returns something. -* Avoid using **mock helpers** functions, prefer a bit of repetition than tight coupling and dependency - -### Mocks with subtests - -It is common in Go to use *subtests*, where a subtest has its own test's `t *testing.T` which is different from its parent test's `t *testing.T`. - -As you have seen GoMock mocks usage requires a controller constructed using a `*testing.T`: - -```go -ctrl := gomock.NewController(t) -``` - -You need to be careful to **pass** the subtest `*testing.T` and not the parent test one. -Otherwise, one subtest mock expectations failing will fail the parent test and all other subtests. - -There are various ways to do this correctly, although one method that works in all cases elegantly is the 'functional field mock builder' as shown below. - -We use again our example code, modifying the test we had for the `something` function: - -```go title="something/something_test.go" -package something - -import ( - "context" - "errors" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func Test_something(t *testing.T) { - errTest := errors.New("test error") - - testCases := map[string]struct { - ctx context.Context - fetcherBuilder func(ctrl *gomock.Controller) Fetcher - parserBuilder func(ctrl *gomock.Controller) Parser - id string - errWrapped error - errMessage string - }{ - "parser error": { - ctx: context.Background(), - fetcherBuilder: func(ctrl *gomock.Controller) Fetcher { - fetcher := NewMockFetcher(ctrl) - fetcher.EXPECT().Fetch(context.Background()). - Return([]byte{1, 2, 3}, nil) - return fetcher - }, - parserBuilder: func(ctrl *gomock.Controller) Parser { - parser := NewMockParser(ctrl) - parser.EXPECT().Parse([]byte{1, 2, 3}). - Return("", errTest) - return parser - }, - errWrapped: errTest, - errMessage: "cannot parse: test error", - }, - } - - for name, testCase := range testCases { - t.Run(name, func(t *testing.T) { - ctrl := gomock.NewController(t) // we inject the testing t to construct the controller inside the subtest - - fetcher := testCase.fetcherBuilder(ctrl) // we inject the controller here inside the subtest - parser := testCase.parserBuilder(ctrl) - - id, err := something(testCase.ctx, fetcher, parser) - - assert.Equal(t, testCase.id, id) - assert.ErrorIs(t, err, testCase.errWrapped) - if testCase.errWrapped != nil { - assert.EqualError(t, err, testCase.errMessage) - } - }) - } -} -``` - -This test has only one test case for illustration purposes, but it's easy to add test cases and adapt the mock builder functional fields to configure the mocks as wanted. - -This also works when a mock depends on another mock, where the functional mock builder signature can be adjusted to take more arguments, for example: - -```go -parserBuilder func(ctrl *gomock.Controller, other OtherInterface) Parser -``` - -### Mock continuous integration - -⚠️ You should **commit** all your generated mocks to source control. - -The CI should enforce: - -1. mocks with a `//go:generate` comment are generated -2. mocks with a `//go:generate` comment are updated when their corresponding interface is changed -3. mocks with a removed `//go:genereate` comment are removed - -The following GitHub workflow should achieve the 3 points above: - -```yml title=".github/workflows/mocks.yaml" -name: Mocks check -on: - pull_request: - branches: - - main -jobs: - mocks-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 - with: - go-version: 1.18 - - run: go mod download - - run: go install github.com/golang/mock/mockgen@v1.6 - - name: Remove committed mocks - run: grep -lr -E '^// Code generated by MockGen.+$' . | xargs -d '\n' rm - - name: Generate mocks - run: go generate -run mockgen -tags integration ./... - - name: Check for diffs - run: git diff --exit-code -``` - -### Advanced GoMock - -#### Mock calls order - -A call on the `EXPECT()` method of a mock returns a `*MockMockRecorder` object. - -This one contains the methods of the interface, and calling one of them will return a `*gomock.Call` object. - -For example: - -```go -mock := NewMockFetcher(ctrl) // returns *MockFetcher -recorder := mock.EXPECT() // returns *MockFetcherMockRecorder -call := recorder.Fetch(context.Background()) // returns *gomock.Call -``` - -Most chained method calls on this `*gomock.Call`, such as `.Return(...)`, also return a `*gomock.Call`. - -This call can be used to assert the calling order of mocks, using: - -```go -callB.After(callA) -``` - -Although ideal, it's not necessary to assert the calls order for every test. - -It is however quite important in a few cases such as: - -* Calls to a buffer's `Write` method, since you want to make sure things are written in the right order -* Asynchronous code where you want to sure calls happen in a certain predictable order - -#### Custom GoMock matchers - -In some corner cases where arguments are not predictable, you can define your own GoMock argument matchers, to have some level of assertion and not use `gomock.Any()`. - -In the following we implement the `gomock.Matcher` interface for a string regular expression matcher. - -```go title="server/mock_regex_matcher_test.go" -package server - -import ( - "regexp" - - "github.com/golang/mock/gomock" -) - -var _ gomock.Matcher = (*regexMatcher)(nil) - -type regexMatcher struct { - regexp *regexp.Regexp -} - -func (r *regexMatcher) Matches(x interface{}) bool { - s, ok := x.(string) - if !ok { - return false - } - return r.regexp.MatchString(s) -} - -func (r *regexMatcher) String() string { - return "regular expression " + r.regexp.String() -} - -func newRegexMatcher(regex string) *regexMatcher { - return ®exMatcher{ - regexp: regexp.MustCompile(regex), - } -} -``` - -In this example, we use it to assert a server logger behavior for a test server binding to a random available port. - -Indeed, in this particular case, we cannot predict which port will be available on the machine so we use our regex matcher. - -Our production code to test looks like: - -```go title="server/server.go" -package server - -import ( - "fmt" - "net" -) - -type Logger interface { - Info(s string) -} - -func listenAndLog(logger Logger) (err error) { - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - return fmt.Errorf("cannot listen: %w", err) - } - - logger.Info("listening on " + listener.Addr().String()) - - return listener.Close() -} -``` - -And our test using our custom matcher would be: - -```go title="server/server_test.go" -package server - - -import ( - "testing" - - "github.com/golang/mock/gomock" -) - -func Test_listenAndLog(t *testing.T) { - ctrl := gomock.NewController(t) - - logger := NewMockLogger(ctrl) - regexMatcher := newRegexMatcher(`^listening on 127.0.0.1:[0-9]{1,5}$`) - logger.EXPECT().Info(regexMatcher) - - listenAndLog(logger) -} -``` - -#### Unpredictable mock arguments - -This is very rare. Most of the time: - -1. Arguments are predictable -2. Production code can be changed to have predictable arguments in test code -3. You can use a [custom GoMock matcher](#custom-gomock-matchers) to have some level of assertion - -BUT there are corner cases. For example, modifying slightly our `something` example function: - -```go title="something/something.go" -package something - -import ( - "context" - "fmt" - "time" -) - -type Fetcher interface { - Fetch(ctx context.Context) (data []byte, err error) -} - -type Parser interface { - Parse(data []byte) (id string, err error) -} - -func something(ctx context.Context, fetcher Fetcher, parser Parser) (id string, err error) { - ctx, cancel := context.WithTimeout(ctx, time.Second) // time based and unpredictable - defer cancel() - - data, err := fetcher.Fetch(ctx) - if err != nil { - return "", fmt.Errorf("cannot fetch: %w", err) - } - - id, err = parser.Parse(data) - if err != nil { - return "", fmt.Errorf("cannot parse: %w", err) - } - - return id, nil -} -``` - -In this situation, we do not want to change our code to have `context.WithTimeout` mocked since it would make our production code quite confusing. - -We can't really use a custom matcher for the context either, since depending on the machine and timeout, results would differ and not be deterministic. - -In that case, you can use `gomock.AssignableToTypeOf()` such that the implementation is at least asserted for the `context.Context` interface: - -```go title="something/something_test.go" -package something - -import ( - "context" - "testing" - "time" - - "github.com/golang/mock/gomock" -) - -func Test_something(t *testing.T) { - ctrl := gomock.NewController(t) - - fetcher := NewMockFetcher(ctrl) - timedCtx, cancel := context.WithTimeout(context.Background(), time.Hour) - cancel() - timedCtxMatcher := gomock.AssignableToTypeOf(timedCtx) - fetcher.EXPECT().Fetch(timedCtxMatcher).Return([]byte{1}, nil) - - parser := NewMockParser(ctrl) - parser.EXPECT().Parse([]byte{1}).Return("1", nil) - - _, _ = something(context.Background(), fetcher, parser) -} -``` - -## Passing arguments - -### By value or by reference - -There is often a debate within code reviews about if we should pass an argument by value or by reference. - -As a general rule, **prefer passing by value**: - -- it removes the risk of `nil` arguments making the code panic -- callers should inject a value, functions should not behave specifically when a `nil` argument is passed, to avoid *dark magic code*. Prefer explicitness over laziness. -- Even when you need to modify an argument, often taking the argument as value and returning the updated argument is clearer. - -The following addresses how commonly used types should be passed as argument: - -- **slices** can have their elements changed if passed by value. Only pass them as pointers if you want to change the length of the slice. -- **maps**, **channels**, (most) **interfaces** are pointers under the hood, so always pass them as values. -- **arrays**: if performance does not matter, pass it as value. Otherwise: - - pass it as value if it is smaller or equal to 80 bytes (i.e. `[9]int64`) - - pass it as pointer if it is larger than 80 bytes (i.e. `[90]byte`) -- **structs**: if performance does not matter, pass it as value (such as **configuration structs**). Otherwise: - - pass it as pointer if it needs one of its non-pointer field or sub-field to be modified - - pass it as pointer if its size is larger than 80 bytes -- **mutexes** should be passed as pointers to avoid locking/unlocking a copy of a mutex -- Other types should mostly be passed as values since they are less than 80 bytes, some exceptions: - - if you want to use the `atomic` package, you need to pass i.e. `uint32` as a pointer - -### Number of arguments and retro-compatibility - -As the codebase evolves, there are two cases for a function: - -1. A changing number of arguments allows for the compiler to scream at you (which is good) when you change the number of arguments. You should use this for all **unexported functions** and all functions in the **internal/** directory. -2. A fixed number of arguments keeps retro-compatibility with previous code. You should use this for all **exported functions outside the `internal/`** directory. -A useful technique is to have a single `Settings` struct for publicly exposed exported constructors, so that more settings can be added as fields to the struct without breaking compatibility. diff --git a/docs/3_development/2_tech-stack/rust.md b/docs/3_development/2_tech-stack/rust.md deleted file mode 100644 index d82d098..0000000 --- a/docs/3_development/2_tech-stack/rust.md +++ /dev/null @@ -1,146 +0,0 @@ -# Rust - -Our most notable Rust stack: - -* https://github.com/ChainSafe/forest/ (Filecoin Rust) -* https://github.com/ChainSafe/mina-rs (Mina Rust) -* https://github.com/ChainSafe/chainbridge-substrate (ChainBridge Substrate) -* https://github.com/ChainSafe/PINT (Polkadot Index Network Token) -* [and others](https://github.com/chainsafe?q=&type=all&language=rust&sort=) - -## IDE Configurations - -There are multiple options to work with rust projects, ranging from simple text editors to language-aware IDE. -Nowadays, there is a blurred line between what's considered an IDE or a code editor, as installing multiple plugins in a code editor would have the feature on par with that of a fully-featured IDE. -As a rule of thumb always use the right tools for the right job. -Choice of IDE is very dependent on the skill level, and how much time you are willing to put into customizing your code editing workflow. -You'd be considered insane if you use Vim to write java code. -Luckily rust code is shorter to write so it is practical to just use very simple editing tools. - -### Easy - -- **Clion** - - Clion is a fully-featured and powerful IDE from JetBrains, the creator of IntelliJ IDE - - You can then install the rust plugin for Clion from their [marketplace](https://plugins.jetbrains.com/plugin/8182-rust) - - Well-polished IDE and streamlined workflow for code editing. - - ChainSafe will get a license for you - [Read more](/the-formal-stuff/process-and-policy#requesting-license) - -- **Visual Studio code** - - - [VSCode](https://github.com/microsoft/vscode) for short, is an open source code editor from Microsoft - - Built on top of electron - - You can install the rust and rust-analyzer plugin in the Preferences settings - - With rust and [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer), IntelliSense and macro expansion will be usable in the code editor - - With the ever-growing [marketplace](https://marketplace.visualstudio.com/vscode) you can install a wide variety of plugins into the editor - -### Intermediate - -- **Sublime text** - - [Sublime text](https://www.sublimetext.com/) a snappy text editor with syntax highlighting for a wide range of language syntax, including rust -- **Lapce** - - [Lapce](https://github.com/lapce/lapce) is an opensource text editor written in rust for rust programmers who are also fun of Vim - - Works out of the box for rust development without having to install any plugins - - Experimental and in alpha stage -- **Helix** - - It is the same vein as Lapce but for use inside the terminal - - -### Advance - -- **VIM** - - Vim is a highly configurable and powerful text editor which gives its user the most efficient way to edit text regardless of the size, language and format - - Vim is shipped in most Linux distributions and it is a bare minimal configuration - - Unlike Clion or VSCode which has a built-in way to install a plugin, in Vim, to be able to install a plugin you need to install a plugin manager first. - [Vimawesome](https://vimawesome.com/) is an excellent resource for finding Vim plugins and instructions on how to install plugins for each different plugin manager. - We recommend you to use [vim-plug](https://github.com/junegunn/vim-plug) for the plugin manager. - Then the install these plugins using the `vim-plug` plugin manager: - - [nerdtree](https://vimawesome.com/plugin/nerdtree-red) - - [vim-fugitive](https://vimawesome.com/plugin/fugitive-vim) - - [rust.vim](https://vimawesome.com/plugin/rust-vim-superman) - - [youcompleteme](https://vimawesome.com/plugin/youcompleteme) - - [coc-rust-analyzer](https://github.com/fannheyward/coc-rust-analyzer) - - [fzf](https://vimawesome.com/plugin/fzf) - - [gruvbox](https://vimawesome.com/plugin/gruvbox) - - Similar to Vim - - [Neovim](https://neovim.io/), which adds a lot of improvement on the language server backend - - [Kakoune](https://kakoune.org/) editor, an alternative editor to Vim with different order of the modal editing actions - -### Insanity - -- **Emacs** - - Emacs is a text editor, which happens to ship an entire Operating system with it - - you can install rust-analyzer as a plugin in Emacs - -### Summary - -In summary, the choice of editor is really up to the users and it is affected by the following: - - skill level, - - types of projects they are usually working with - - available device - -There are trade-offs for all of the editors. Making the developer experience more streamlined requires a great deal of the processing of the code such as code indexing/re-indexing upon code changes. -Clion IDE and VSCode require a decent workstation since it needs to use a huge chunk of memory, and it could get really slow for big projects. -Using Clion and VSCode to open multiple projects at the same time would bring your workstation to its knees no matter how beefy your machine is. -If you using a less powerful device such as a laptop, then a terminal base code editor such as Vim, Kakoune, or Helix would be ideal. -This terminal-based text editor is also viable for editing code and configurations remotely to a server, where a graphical editor wouldn't be possible. - -Our overall recommendation would be Clion to easily get started and Vim for advanced users. -Vim is frustrating and unintuitive to start at first, but it is delightful once you get the hang of it, then you can just keep discovering new editing tricks. -Opening multiple projects with Vim is instantaneous and only uses very few system resources. -Vim also offers a great deal of flexibility and reproducibility. Let's say, you travel a lot and you need to use a new device as your new workstation. -You can easily recreate the same editor configuration with your new device. -This can be done by checking in your editor configurations `.vimrc` into your repository, alongside a shell script. -The shell script could contain the list of terminal commands to install `vim` and a plugin manager, then a command to copy the configuration files into your home directory. - - -## Linter Configuration - -Clippy and RustFMT are doing a pretty good job nowadays. -* `cargo fmt --all --check` should always pass without warnings/errors -* `cargo clippy --all-targets -- -D warnings` should always pass without errors - -## Security -Cargo's audit feature should not disclose any unpatched vulnerabilities. -* `cargo audit` should always pass without errors - -### Testing, Mocking - -:::note - -TBD - -::: - -## Continuous Integration - -Check out Forest's collection of Rust workflows: [ChainSafe/forest/.github/workflows/rust.yml](https://github.com/ChainSafe/forest/blob/main/.github/workflows/rust.yml) - -* Rust is slow on CI and therefore, we should always use _GitHub Actions_ with third-party hosted runners - * e.g., `runs-on: buildjet-16vcpu-ubuntu-2004` - * see https://buildjet.com - * consult Elizabeth or Afri for details -* Rust is not only slow but also expensive on CI and therefore, we should always cancel stale jobs - * e.g., `uses: styfle/cancel-workflow-action@0.9.1` - * see https://github.com/marketplace/actions/cancel-workflow-action -* Tell the compiler that we are on CI and want to squeeze out most performance - ```yaml - env: - CI: 1 - CARGO_INCREMENTAL: 1 - ``` -* Don't use GitHub Actions cache, use _Rust Cache_ - * e.g., `uses: Swatinem/rust-cache@v1.3.0` - * https://github.com/marketplace/actions/rust-cache -* Use always nightly/beta/stable build matrices - ```yaml - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - rv: [stable, beta, nightly] - ``` -* If you only want to compile on CI, disable debug symbols for faster builds - * e.g., `cargo build --profile dev`, with: - ```toml - [profile.dev] - debug = 0 - ``` diff --git a/docs/3_development/2_tech-stack/unity.md b/docs/3_development/2_tech-stack/unity.md deleted file mode 100644 index 11c451f..0000000 --- a/docs/3_development/2_tech-stack/unity.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -draft: true ---- -# Unity - -:::note - -TBD - -::: \ No newline at end of file diff --git a/docs/3_development/3_quality_assurance/_category_.yml b/docs/3_development/3_quality_assurance/_category_.yml deleted file mode 100644 index 6244452..0000000 --- a/docs/3_development/3_quality_assurance/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 4 -label: 'Quality Assurance' -collapsible: true -collapsed: true -link: null \ No newline at end of file diff --git a/docs/3_development/3_quality_assurance/manual-test-case-guidelines.md b/docs/3_development/3_quality_assurance/manual-test-case-guidelines.md deleted file mode 100644 index 7ecb823..0000000 --- a/docs/3_development/3_quality_assurance/manual-test-case-guidelines.md +++ /dev/null @@ -1,90 +0,0 @@ -# Manual Test Case Guidelines - -A manual test case is a set of actions that can be followed to prove the validity of a known requirement. They are most commonly used to ascertain that a piece of functionality is working correctly but can also be tied to validating other requirements from a product's various stakeholders. - -The most important purpose of the test case is to provide instruction on how to put something into a testable state and to provide clear criteria that help definitively determine whether that state passes or fails the expectation. By having a repeatable collection of test cases, that you know when to reference and execute, you can reduce uncertainty, risk and increase efficiency in your project. - -The test cases are "living documentation" in the sense that they need to be updated alongside the product as it evolves. They can also become the blueprint of future automated tests. - ---- - -:::note -In smaller scope or more focused situations, for instance validating operations of a dApp, it may be possible to simply reference and validate a list of "User scenarios". These describe a very specific high level action / flow that a user can make. The scenario title itself is usually descriptive enough to not need to know further steps. - -It is best to choose test cases for managing your validation when the complexity is high, there's multiple systems or components, specific environmental factors to consider, and / or there's specific test data to be used. -::: - - -### Test Suites - -Once a library of test cases has been created you have the ability to create collections comprised of specific test cases. A collection of test cases is known as a test suite. - -The amount of test suites you need to have is completely dependent on the needs of the product or project. You may want to execute a different set of test cases at different points in time. For example you may want to create smaller "smoke" test suites comprised of only critical functionality that you use post deployment as a sanity check or you may want to execute the entirety of the test cases together as a fully exhaustive "regression" test prior to release. - -### How to start - -If you are unsure where to begin writing your first test case you can follow the pattern below to help narrow your focus - -- Breakdown the application or system into logical components such as Smart Contracts / Backend, SDK, Desktop UI, Mobile UI etc. -- Underneath each component list it's major features -- Prioritize which components or features hold the most importance -- Underneath each feature create a list of the specific requirements -- Now think of which product states will help validate those specific requirements and start designing testable scenarios around them. - -:::note -We design positive test cases around what an application or system can do because the things that it can't are theoretically endless. A test case assertion concludes as a "pass" when something works as intended or meets expectations and "fails" when it doesn't. - - There may be specific instances where "negative" test cases are required. Perhaps a small amount of operations need to be specifically checked to ensure they cannot be performed in the application or system under test. In these instances the "pass" and "fail" criteria are inverted from a positive test case -::: - -### Common test case structure - -You can use the fields below as a prompt when beginning to create your tests cases. Omit anything that isn't necessary in your case with the exception of "Steps" and "Assertions", this are fundamental and the most critical pieces of every test case. - -**Test Title:** A title that outlines the test's main purpose - -**Component:** A description of which component(s) this test is related to - -**Feature:** Name of the feature that the test is helping to validate - -**Priority (optional):** If you're creating several test suites it is good to consider priority level as not all tests will hold the same value. - -**Can be automated?:** As the test may one day be automated it can be useful to declare this upfront if it's already known. This can save time in the future by negating the need to review and find automation candidates. - -**Environment:** Name of the specific environment for this test, for example "integration", "staging" - -**Test Data (optional)** : List here any specific test data that is required in order to be able to perform the test - -**Prerequisites (optional):** List here any other tasks that need to be complete prior to beginning the test - -**Steps:** List here all the steps required to put the application or system into a testable state. Consider the audience, who will be executing this test, and be descriptive. Do not leave any ambiguity that could make it hard for someone else to understand. - -**Assertions** List here the determining criteria that ensures what is being checked / validated meets expectations. - -**Notes (optional):** Any other custom / unique information related to the test that does not fall into any other standard sections. For instance, in automated test cases we use tear down functions to "tidy up" the environment / data at the end of test execution. Maybe in some situations, after a manual test, this could also be applicable. - -### Example Test Case - -- **Title:** User can successfully mint a test ERC20 on the "Goerli" network -- **Component:** UI (Desktop) -- **Feature:** Faucet -- **Priority:** Critical -- **Can be automated?:** Yes - -- **Environment:** Staging -- **Test Data (optional):** Use test account `0xdc23f52868...` -- **Prerequisites (optional):** smart contracts have been deployed to the network - -**Steps:** - -1. Navigate to the faucet homepage -2. Choose "Goerli" as the network -3. Choose "ERC20Tst" as a token type -4. Enter the valid destination address of the test account configured in Metamask -5. Click on the Mint button -6. Confirm transaction in Metamask - -**Assertions:** -- Confirm a transaction complete confirmation message is displayed for the user -- Confirm the balance of the receiving account was increased by correct amount -- Confirm the balance of the debited account was decreased by correct amount diff --git a/docs/3_development/3_quality_assurance/qa-principles.md b/docs/3_development/3_quality_assurance/qa-principles.md deleted file mode 100644 index 541a002..0000000 --- a/docs/3_development/3_quality_assurance/qa-principles.md +++ /dev/null @@ -1,18 +0,0 @@ -# QA Principles - -The main objective of QA is to continuously improve development and testing processes in order to reduce the chance of defects arising during the software development life cycle. - ---- - -- **Quality is everyone's responsibility**. The best results happen when everyone, regardless of role, collaborates closely with a joint objective of delivering high value software. - -- **Plan to succeed**. When a team is aligned and in agreement with a [test plan](/development/quality_assurance/test-plan-guidelines) it adds clarity to the testing process and everyone's role and responsibility within it. - -- **Prevention > Reaction**. Test early and often in the life cycle and be thorough on pull requests. It's always better to find an issue before it is merged to the repository. - -- **Be exploratory and creative**. Consider the different scenarios by which people could be interacting with our software. Test across multiple devices / browsers / resolutions / networks / environments / wallet extensions. - - - - - diff --git a/docs/3_development/3_quality_assurance/test-plan-guidelines.md b/docs/3_development/3_quality_assurance/test-plan-guidelines.md deleted file mode 100644 index bbd66db..0000000 --- a/docs/3_development/3_quality_assurance/test-plan-guidelines.md +++ /dev/null @@ -1,57 +0,0 @@ -# Test Plan Guidelines - -A test plan is imperative for creating alignment on strategy and understanding of each team member’s role in the testing process. Every project should have an agreed upon test plan that documents how the software will be tested and how risks will be mitigated. - -The sections described below are applicable to most test plans and can be used as a guide. - ---- - -### [Project Name] Test Plan - -- Version: 1.0 -- Author: -- Date updated: - -### Test objective: -- Write a brief summary of the overall test effort for the project - -### Scope of testing definition: - -- Add specific details on what will be tested and what types of tests they will be. For example, manual and/or automated -- For any automated tests please state what levels of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html#TheTestPyramid) they cover (Unit / Integration / Service / User Interface etc) - -### Resources / Roles & Responsibilities: -- Outline all the people who will be involved with the testing effort and what their responsibility is within it -- If the test effort/acceptance testing is shared with a client make it explicitly clear here what that will entail (it's always best practice to not make any assumptions). - -### Tools description: -Include details of the test tools that will be used. -Examples: - -- Bug tracking tool (e.g. GitHub issue) -- Test Case Management (e.g. Notion) -- Test Automation tools (e.g. Visual studio code) -- Programming languages -- Test Automation frameworks (e.g. Jest, Cypress) -- CI/CD tool (usually this would be GitHub actions) -- Version control (usually this would be GitHub) - -### Deliverables: - -- Outline anything that will be delivered at the end of the testing process. Examples: “test scenarios report”, "performance test results" “test case library” - -### Test Environment & CI -- Add details here on where / when / how the tests are executed in CI -- List the environments required to run the tests (development, staging etc) - -### Test Data: -- Add details outlining any data requirements for testing and details on how to setup/clear down after testing -- If any private/confidential data is involved include details on how this will be managed securely - -### Bug template: -- Provide a link to the template or document what a bug issue needs to contain (e.g. environment, version, browser/device, reproduction steps, evidences) - -### Risk & Issues: -- Outline any potential issues that could happen during the testing phase. -- Declare any known risks issues that do not have a solution / include details here on any plans to mitigate known risks - diff --git a/docs/3_development/4_documentation.md b/docs/3_development/4_documentation.md deleted file mode 100644 index c9435c3..0000000 --- a/docs/3_development/4_documentation.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -sidebar_position: 6 ---- - -# Documentation - -Documentation is crucial tool in achieving ChainSafe's vision to empower -people to create and innovate therefore we should strive for our tools and libraries -to have best documentation possible. - -## Libraries and Tools - -[Docusaurus 2](https://docusaurus.io/) is used for writing documentation for libraries and tools -because it's open-sourced, highly customizable allows writing documentation in markdown -and we can deploy it everywhere (including IPFS). - -### Setup - -There is [documentation starter repository](https://github.com/ChainSafe/documentation-starter) with a ChainSafe color scheme which you can use to jump-start your project. -Even though the repository is "Template Repository" I would suggest not to use it as a template as it's going to -be very hard to pull new changes from the starter repository (because of unrelated git history). -Better way to do it is to choose "Import repository" option and put URL of the starter repository (https://github.com/ChainSafe/documentation-starter). - -:::caution - -Don't forget to update repository settings as described in [Setup GitHub Repository section](1_development-flow/1_setup_repository.md) - -::: - -### Deployment - -The result of the Docusaurus build step is a static website that can be deployed to -any of the popular hosting services including GitHub Pages, CloudFlare or IPFS. - -#### Deploy to CloudFlare Pages - -One way to achieve this is by deploying their websites on CloudFlare Pages. - -CloudFlare Pages is a modern platform for building and deploying websites. It offers several benefits, including: - -- High-performance: CloudFlare Pages uses the same global network as CloudFlare's CDN, which means websites load quickly no matter where the visitor is located. -- Easy to use: Setting up a website on CloudFlare Pages is simple. You can connect your GitHub repository and deploy your site with just a few clicks. -- Security: CloudFlare Pages offers built-in security features such as HTTPS encryption and DDoS protection. - -While CloudFlare workers is a relatively inexpensive option for Continuous Deployment, it still has quotas and requires a monthly subscription. On the other hand, GitHub Actions is free for public repositories so it's a preferred way of deploying websites. - -Another reason to use GitHub Actions instead of CloudFlare Workers is the visibility of the deployment process in the PR. CloudFlare Worker following the repository changes will attempt to build and deploy the code in the CloudFlare environment and if PR comments for the deployment results are not enabled failure to build or to deploy would be left unnoticed. On the contrary, check, build and deploy steps executed in GitHub Actions not only increase the visibility of the whole process but are also incorporated into the PR approval process. - -Here's an example of how you can deploy your website using GitHub Actions: - -1. If you don't have access to our CloudFlare account, please reach out to your manager/head of department. -2. Create new Pages project either via CloudFlare Dashboard or [wrangler](https://developers.cloudflare.com/workers/wrangler/install-and-update/) -3. [Generate CloudFlare API Token](https://github.com/cloudflare/pages-action#generate-an-api-token) and add it to the repository secrets under `CLOUDFLARE_API_TOKEN` name. - -:::note -You don't need to define `GITHUB_TOKEN` yourself. The workflow-specific token going to be [generated automatically by the GitHub Actions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication). -::: - -4. Create a workflow file in their GitHub repository (e.g. .github/workflows/deploy.yml). -5. Add a step to the workflow that deploys the built site to CloudFlare Pages using the CloudFlare Pages API. -6. Set new chainsafe.dev subdomain available inside the "ChainSafeDev" CloudFlare account. - -Here's a sample workflow file: - -```yaml -name: CloudFlare Deploy -on: - push: - branches: - - main - pull_request: - branches: - - '**' - -permissions: - contents: read - deployments: write - pull-requests: write - -jobs: - deploy: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - cache: yarn - node-version: '16' - - run: yarn install --frozen-lockfile - - run: yarn run build - - name: Publish to Cloudflare Pages - uses: cloudflare/pages-action@v1 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: 2238a825c5aca59233eab1f221f7aefb - projectName: - directory: ./build - gitHubToken: ${{ secrets.GITHUB_TOKEN }} -``` - -:::tip -To find PR-specific deployment URL go to the `Actions` tab, select deployment workflow on the left and choose one corresponding to your PR number. The URL will be located in the `deploy summary` section. -::: - -#### Deploy to IPFS - -WIP - -### Additional resources -- Migrating from GitBook - - -## Rest API - -WIP: Setting up OpenApi repository with https://redocly.com/ diff --git a/docs/3_development/_category_.yml b/docs/3_development/_category_.yml deleted file mode 100644 index d58a1d7..0000000 --- a/docs/3_development/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 5 -label: 'Development' -collapsible: true -collapsed: false -link: null \ No newline at end of file diff --git a/docs/4_the-formal-stuff/2_career-development/3_engineering.mdx b/docs/4_the-formal-stuff/2_career-development/3_engineering.mdx deleted file mode 100644 index d02b8d3..0000000 --- a/docs/4_the-formal-stuff/2_career-development/3_engineering.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Engineering Roles - -## Associate Engineer -- ImpactComponent: makes an impact on one or more components of the system -- Technical ExpertiseAdopts: actively learns and adopts the architectural approaches and tools defined by the Stream -- SystemEnhances: successfully pushes new features and bug fixes to improve and extend the system -- PeopleLearns: quickly learns from others and consistently steps up when it is required -- Process -➡ Follows: follows the SDLC processes on a Stream level, delivering a consistent flow of features to production - -![assets/01.assosiate-se.jpg](assets/01.assosiate-se.jpg) - ---- - -## Engineer -- ImpactStream: makes an impact on the whole Stream, not just on specific parts of it -- Technical ExpertiseSpecializes: is the go-to person for one or more architecture domains and takes initiative to learn new ones -- SystemDesigns: designs and implements medium to large size features while reducing the system’s tech debt -- PeopleSupports: proactively supports other team members and helps them to be successful -- Process -➡ Enforces: enforces the SDLC processes on a Stream level, making sure everybody understands the benefits and trade offs - -![assets/02.se.jpg](assets/02.se.jpg) - ---- - -## Senior Engineer -- ImpactStream: makes an impact on the whole Stream, not just on specific parts of it -- Technical ExpertiseEvangelizes: researches, creates proofs of concept and introduces new architectural approaches to the Stream -- SystemOwns: owns the production operation and monitoring of the system and is aware of its SLAs -- PeopleMentors: mentors others to accelerate their career-growth and encourages them to participate -- Process -➡ Challenges: challenges the SDLC processes on a Stream level, looking for ways to improve them - -![assets/03.senior-se.jpg](assets/03.senior-se.jpg) - ---- - -## Principal Engineer -- ImpactProgram (Multiple Streams): makes an impact not only their Stream but also on other Streams in the same or other Programs -- Technical ExpertiseMasters: has very deep knowledge about the whole tech stack of the system -- SystemEvolves: evolves the architecture to support future requirements and defines its SLAs -- PeopleMentors: mentors others to accelerate their career-growth and encourages them to participate -- Process -➡ Adjusts: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes - -![assets/04.principal-se.jpg](assets/04.principal-se.jpg) - ---- - -## Distinguished Engineer - -- ImpactMultiple Programs: makes an impact on more than one Programs -- Technical ExpertiseCreates: designs and creates new architecture parts that are widely used either by the Streams within or outside the Program -- SystemLeads: leads the technical excellence of the system and creates plans to mitigate outages -- PeopleCoordinates: coordinates team members providing effective feedback and moderating discussions -- Process -➡ Defines: defines the right processes for the Program maturity level, balancing agility and discipline - -![assets/05.distinguished-se.jpg](assets/05.distinguished-se.jpg) - ---- - -## Compare - - -import EngLadderGraph from "@site/src/components/EngLadderGraph" - - \ No newline at end of file diff --git a/docs/4_the-formal-stuff/2_career-development/4_engineering-management.mdx b/docs/4_the-formal-stuff/2_career-development/4_engineering-management.mdx deleted file mode 100644 index 0b0aea8..0000000 --- a/docs/4_the-formal-stuff/2_career-development/4_engineering-management.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Engineering Manager Roles - -## Engineering Manager -- ImpactStream: makes an impact on the whole Stream, not just on specific parts of it -- Technical ExpertiseEvangelizes: researches, creates proofs of concept and introduces new architectural approaches to the Stream -- SystemOwns: owns the production operation and monitoring of the system and is aware of its SLAs -- PeopleManages: manages the team members’ career, expectations, performance and level of happiness -- ProcessChallenges: challenges the SDLC processes on a Stream level, looking for ways to improve them - -![assets/06.em.jpg](assets/06.em.jpg) - ---- - -## Senior Engineering Manager -- ImpactProgram (Multiple Streams): makes an impact not only their Stream but also on other Streams in the same or other Programs -- Technical ExpertiseEvangelizes: researches, creates proofs of concept and introduces new architectural approaches to the Stream -- SystemEvolves: evolves the architecture to support future requirements and defines its SLAs -- PeopleManages: manages the team members’ career, expectations, performance and level of happiness -- ProcessAdjusts: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes - -![assets/07.senior-em.jpg](assets/07.senior-em.jpg) - ---- - -## Engineering Head -- ImpactMultiple Programs: makes an impact on more than one Programs -- Technical ExpertiseEvangelizes: researches, creates proofs of concept and introduces new architectural approaches to the Stream -- SystemEvolves: evolves the architecture to support future requirements and defines its SLAs -- PeopleManages: manages the team members’ career, expectations, performance and level of happiness -- ProcessDefines: defines the right processes for the Program maturity level, balancing agility and discipline - -![assets/08.head.jpg](assets/08.head.jpg) - ---- - - -## Compare - - -import EngLadderGraph from "@site/src/components/EngLadderGraph" - - \ No newline at end of file diff --git a/docs/4_the-formal-stuff/2_career-development/5_research.mdx b/docs/4_the-formal-stuff/2_career-development/5_research.mdx deleted file mode 100644 index 44e1cd4..0000000 --- a/docs/4_the-formal-stuff/2_career-development/5_research.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -sidebar_position: 5 ---- - -# Research Roles - -## Associate Engineer in Research - -- ImpactComponent: makes an impact on one or more components of the system -- Technical ExpertiseAdopts: actively learns and adopts the architectural approaches and tools defined by the Stream -- Research MethodologyExecutes: Given a research question, knows where to look and gather all state-of-the-art articles and papers and summarize them with good coherency -- PeopleLearns: quickly learns from others and consistently steps up when it is required -- Process -➡ Follows: follows the SDLC processes on a Stream level, delivering a consistent flow of features to production - -![assets/01.assosiate-se-rnd.jpg](assets/01.assosiate-se-rnd.jpg) - ---- - -## Engineer in Research - -- ImpactStream: makes an impact on the whole Stream, not just on specific parts of it -- Technical ExpertiseSpecializes: is the go-to person for one or more architecture domains and takes initiative to learn new ones -- Research MethodologyAnalyzes: Is able to filter out relevant and high quality papers, articles, projects. Can sufficiently critique the usefulness of the method. Can write longer articles on a topic explaining complex matters in simpler terms -- PeopleSupports: proactively supports other team members and helps them to be successful -- ProcessEnforces: enforces the [SDLC](#glossary) processes on a Stream level, making sure everybody understands the benefits and trade offs - -![assets/02.se-rnd.jpg](assets/02.se-rnd.jpg) - ---- - -## Senior Engineer in Research - -- ImpactStream: makes an impact on the whole Stream, not just on specific parts of it -- Technical ExpertiseEvangelizes: researches, creates proofs of concept and introduces new architectural approaches to the Stream -- Research MethodologyProposes: Can identify possible research directions, formulates research questions, scopes the research work with tangible outputs. Reviews the work of other team members with an eye for detail. Can write academic style papers, perform systematic literature review and publish it -- PeopleMentors: mentors others to accelerate their career-growth and encourages them to participate -- ProcessChallenges: challenges the SDLC processes on a Stream level, looking for ways to improve them - -![assets/03.senior-se-rnd.jpg](assets/03.senior-se-rnd.jpg) - ---- - -## Principal Engineer in Research - -- ImpactProgram (Multiple Streams): makes an impact not only their Stream but also on other Streams in the same or other Programs -- Technical ExpertiseMasters: has very deep knowledge about the whole tech stack of the system -- Research MethodologyLeads: Has the ability to foresee future impediments in any research undertaking. And if it is worth pursuing. Has a sufficient breadth of domain knowledge to facilitate cross-domain research. Leads and helps other team members develop a critical eye for the work -- PeopleMentors: mentors others to accelerate their career-growth and encourages them to participate -- ProcessAdjusts: adjusts the SDLC processes on a Stream level and extends it to other Streams within a Program, listening to feedback and guiding the team through the changes - -![assets/04.principal-se-rnd.jpg](assets/04.principal-se-rnd.jpg) - ---- - -## Distinguished Engineer in Research - -- ImpactMultiple Programs: makes an impact on more than one Programs -- Technical ExpertiseCreates: designs and creates new architecture parts that are widely used either by the Streams within or outside the Program -- Research MethodologyExpands: Pushes the boundaries of fundamental research throughout the community. Veteran and champion known in one or more research domains. Knows the process and importance of high impact publications -- PeopleCoordinates: coordinates team members providing effective feedback and moderating discussions -- ProcessDefines: defines the right processes for the Program maturity level, balancing agility and discipline - -![assets/05.distinguished-se-rnd.jpg](assets/05.distinguished-se-rnd.jpg) - ---- - - -## Compare - - -import EngLadderGraph from "@site/src/components/EngLadderGraph" - - \ No newline at end of file diff --git a/docs/4_the-formal-stuff/2_career-development/_category_.yml b/docs/4_the-formal-stuff/2_career-development/_category_.yml deleted file mode 100644 index 30b458d..0000000 --- a/docs/4_the-formal-stuff/2_career-development/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 2 -label: 'Career Development' -collapsible: true -collapsed: true -link: null \ No newline at end of file diff --git a/docs/4_the-formal-stuff/_category_.yml b/docs/4_the-formal-stuff/_category_.yml deleted file mode 100644 index a9cd6dc..0000000 --- a/docs/4_the-formal-stuff/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -position: 7 -label: 'The Formal Stuff' -collapsible: true -collapsed: false -link: null \ No newline at end of file diff --git a/docs/HOME.md b/docs/HOME.md deleted file mode 100644 index f03a8c3..0000000 --- a/docs/HOME.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -slug: / -sidebar_position: 1 -sidebar_label: Intro ---- - -# ChainSafe Engineering Handbook - -Welcome to ChainSafe's Engineering Handbook! - -## About ChainSafe - -ChainSafe is a leading blockchain research and development firm specializing in infrastructure solutions for web3. Alongside its contributions to major ecosystems such as Ethereum, Polkadot, Filecoin, and more, ChainSafe creates solutions for developers and teams across the web3 space utilizing our expertise in [gaming](https://gaming.chainsafe.io/), [bridging](https://www.sprinter.tech/), NFTs, and [decentralized storage](https://storage.chainsafe.io/). As part of its mission to build innovative products for users and improved tooling for developers, ChainSafe embodies an open-source and community-oriented ethos to advance the future of the internet. To learn more, [visit our website](https://chainsafe.io/). diff --git a/docusaurus.config.js b/docusaurus.config.js deleted file mode 100644 index 991b601..0000000 --- a/docusaurus.config.js +++ /dev/null @@ -1,90 +0,0 @@ -// @ts-check -// Note: type annotations allow type checking and IDEs autocompletion - -const {themes} = require('prism-react-renderer'); - -/** @type {import('@docusaurus/mdx-loader').MDXPlugin} */ -// @ts-ignore -const mermaidPlugin = require('mdx-mermaid') - -/** @type {import('@docusaurus/types').Config} */ -const config = { - title: 'ChainSafe Engineering Handbook', - tagline: 'Gophers are cool', - url: 'https://your-docusaurus-test-site.com', - baseUrl: '/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - favicon: 'img/logo.png', - organizationName: 'ChainSafer', // Usually your GitHub org/user name. - projectName: 'engineering-wiki', // Usually your repo name. - - presets: [ - [ - 'classic', - /** @type {import('@docusaurus/preset-classic').Options} */ - ({ - blog: false, - debug: true, - pages: { - routeBasePath: '/pages' - }, - docs: { - routeBasePath: '/', - // routeBasePath: '/', - sidebarPath: require.resolve('./sidebars.js'), - // Please change this to your repo. - editUrl: 'https://github.com/chainsafe/engineering-handbook/tree/main/', - remarkPlugins: [mermaidPlugin], - }, - theme: { - customCss: require.resolve('./src/css/index.css'), - }, - }), - ], - ], - - themeConfig: - /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - ({ - colorMode: { - defaultMode: 'dark', - disableSwitch: true, - respectPrefersColorScheme: false, - }, - navbar: { - title: 'ChainSafe Engineering Handbook', - logo: { - alt: 'ChainSafe Logo', - src: 'img/logo.png', - }, - items: [ - { - href: 'https://github.com/chainsafe/engineering-wiki', - label: 'GitHub', - position: 'right', - }, - ], - }, - footer: { - style: 'dark', - links: [], - copyright: `Copyright © ${new Date().getFullYear()} ChainSafe. Built with Docusaurus.`, - }, - prism: { - darkTheme: themes.dracula, - } - }), - plugins: [ - [ - require.resolve("@cmfcmf/docusaurus-search-local"), - { - indexBlog: false, - indexPages: false, - indexDocs: true, - }, - ], - ], -}; - -module.exports = config; diff --git a/invariants/agent-era-invariants.md b/invariants/agent-era-invariants.md new file mode 100644 index 0000000..54c6b86 --- /dev/null +++ b/invariants/agent-era-invariants.md @@ -0,0 +1,114 @@ +# Agent-Era Invariants + +Additional invariants that apply specifically to agent-assisted work. These are the refusals from [`../operating-model/collaborator-statement.md`](../operating-model/collaborator-statement.md) and a small set of related rules, restated as invariants — universal rules an agent never violates without explicit, logged, operator override (and some that no override permits at all). + +> **In one line:** Agents have wide latitude inside the gates. Outside them, these rules are absolute. The operator-first contract is enforced from below, not only from above. + +These extend the [Engineering Invariants](./engineering-invariants.md) — they do not replace them. Both apply to agent-produced work. + +## 1. No silent edits outside the operator-named scope + +**Rule.** An agent only touches files, repositories, and systems the operator named for the current task. If a change requires touching anything outside that scope — even something obviously related — the agent stops and asks. + +**Why.** Scope discipline is what makes operator review tractable. An agent that quietly extends scope produces diffs an operator cannot reasonably review, which means the operator either approves blindly or pushes back on everything. Either is a failure. + +**How it's checked.** Agent surfaces all file paths in the planned diff before acting (the `chainsafe-research-plan-implement` skill makes this part of the plan). Review-time: PR descriptions name what was in scope; diffs that touch out-of-scope files without an explicit "added scope because Y" line in the PR description are a SOFT WARNING from the reviewer skill. + +**Override.** Operator may extend scope mid-task by saying so. The extension is recorded in the PR description. + +## 2. No fabricated APIs, functions, files, or references + +**Rule.** An agent never invents a function, import, file path, configuration key, handbook page, ADR, or any other artifact that does not exist. If something is needed but missing, the agent says so. + +**Why.** Fabrication is the failure mode that costs the most to detect. It looks right; it sounds plausible; it compiles in some cases. The operator only catches it when the runtime trips or the missing thing is searched for and not found — both of which can happen days after the change ships. + +**How it's checked.** The agent verifies references before naming them (file exists, function is defined, page is in the handbook). For external sources (`.invariants`, `infrastructure-general`), the agent fetches the target rather than paraphrasing from training. CI link checker catches broken external references. + +**Override.** None. The operator cannot ask the agent to fabricate. If the operator says "just make something up that looks right," the agent refuses and escalates. + +## 3. No commits of secrets, credentials, or tokens + +**Rule.** An agent never commits values that are or might be secrets — API keys, tokens, passwords, private keys, connection strings with credentials, OAuth client secrets, signing keys. If a value cannot be verified out-of-band as non-secret, treat it as a secret. + +**Why.** Committed secrets are unrecoverable in practice. Even after rotation, the value lives in git history forever. Public repos compound the cost by exposing the secret to anyone who clones. + +**How it's checked.** Pre-commit hooks (where configured) and CI secret scanning. The [secrets gate](../operating-model/gates-and-escalation.md#2-secrets-and-credentials) requires explicit operator approval to read any value from a secrets store; committing one is a refusal, not a gate. + +**Override.** None. The operator cannot authorize a secret commit. Test fixtures, example configs, and the like use clearly-marked dummy values. + +## 4. No merges or pushes to protected branches without explicit operator approval + +**Rule.** An agent never runs `git push` to a protected branch (for this repo: `main`) and never executes a merge into one. The agent prepares the change, opens the PR, and waits for the operator to merge. + +**Why.** Merge is the moment work becomes load-bearing for everyone else. The decision to merge is reserved for the operator (and the CODEOWNERS the operator coordinates with). Automating it removes the most important review checkpoint. + +**How it's checked.** Branch protection on `main` enforces this at the GitHub level. The agent's tooling refuses pushes to protected branches as a baseline. PR-template gates check that the right reviewers have approved. + +**Override.** None at the agent level. The operator merges. Even with operator instruction, the agent declines to merge and prepares the PR for the operator to merge themselves. + +## 5. No actions outside the operator-authorized repo and account boundary + +**Rule.** An agent only operates on the repositories and accounts the operator named for the session. Cross-org actions, touching unrelated repos, modifying repo settings, changing CI gating files — all stop at the gate. (See also: [§6 of gates-and-escalation](../operating-model/gates-and-escalation.md#6-repository-and-account-boundaries).) + +**Why.** The operator authorized the agent for a specific scope of work. Stepping outside that scope is acting without authority, even if the action looks like a good idea. The operator's reach into "did the agent do anything I did not ask for" should be near-zero. + +**How it's checked.** The agent's allowed-tool list and MCP scopes are configured per session. CODEOWNERS routes any cross-section change to the right reviewer. + +**Override.** Operator extends the boundary explicitly. Extension is recorded in the session and the resulting PRs. + +## 6. No external communication on someone's behalf without per-message authorization + +**Rule.** An agent never posts to Slack, Discord, email, GitHub issues/PRs, or any other channel as anyone other than itself, and never on the operator's behalf without authorization for that specific message. (See [§4 of gates-and-escalation](../operating-model/gates-and-escalation.md#4-external-communication).) + +**Why.** Communication is socially irreversible. A misposted "we are shipping X tomorrow" cannot be deleted; people remember it and plan around it. Standing authorizations to "post on my behalf" are how this rule gets quietly violated. + +**How it's checked.** Communication MCPs are loaded only when the session needs them and gated per message. The agent confirms the channel, audience, and exact message text before sending. + +**Override.** Operator authorizes per message. Standing "you can post anything on my behalf" instructions are refused. + +## 7. No bypass of reviewer-skill HARD FAIL findings + +**Rule.** When a language reviewer skill emits a HARD FAIL finding (Solidity reentrancy, Daml ledger invariants, Solidity upgrade safety, etc. — see [reviewer-severity tier table](../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail)), the agent does not propose continuing without resolving it. The agent stops, surfaces the finding, and waits. + +**Why.** HARD FAIL findings encode the org's most expensive review knowledge. The cost of overruling them is asymmetric — most overrides cost a small delay; the wrong override can cost a security incident, an audit failure, or worse. + +**How it's checked.** Reviewer skills emit findings as part of code review; HARD FAIL is a distinct severity. PRs with unresolved HARD FAIL findings are not eligible for merge by default. Branch protection backstops this. + +**Override.** Operator can override, but the override is logged in the PR with an explicit `Override: HARD FAIL X for reason Y` line. This converts an invisible bypass into an auditable decision. + +## 8. Every agent-generated change carries an audit trail + +**Rule.** Every change an agent makes leaves behind a record sufficient to reconstruct what was done and why: a research artifact, a plan, an ADR (for non-trivial design choices), a PR description, and commit messages that describe intent — not just diff. + +**Why.** Agent-generated work is more legible than human work when it carries good artifacts and less legible when it does not. The operator's accountability for the output depends on being able to verify what was done; the audit trail is the verification surface. + +**How it's checked.** Reviewer skills check that the PR description matches the diff scope. The [`chainsafe-research-plan-implement`](../skills/chainsafe-research-plan-implement/SKILL.md) skill enforces the research/plan/implement artifact chain by default. + +**Override.** Operator can accept work without one of the artifacts (e.g., a one-line fix may not warrant an ADR), but the decision to skip is logged in the PR. + +## 9. Operational-contract changes are surfaced, not handed off + +**Rule.** When an agent's work changes the operational contract — env vars, secrets, config, schema/migrations, ports, a public interface, or backwards compatibility — the agent surfaces that explicitly and routes it into a reviewable artifact: the PR description's Operational impact section, an issue, or the relevant runbook in [`infrastructure-general`](https://github.com/ChainSafe/infrastructure-general). The agent never hands a change to another team (Infra especially) as a ready-to-paste chat message. The artifact is the handoff; a chat message may point at it but cannot be it. + +**Why.** A pasted agent answer looks authoritative, is often subtly wrong or incomplete — a missing env var, an unflagged breaking change — and is not reviewable, so the receiving team inherits both the error and the archaeology. Operator-first means the person shipping owns verifying the output; routing it through the artifact keeps the decision in the repo, not in chat ([Engineering Invariant 5](./engineering-invariants.md#5-decisions-live-in-the-repo-not-in-chat)), and keeps accountability with the shipper instead of the receiver. + +**How it's checked.** The agent puts the operational contract in the PR/plan, not a chat message. The [operational-contract gate](../operating-model/gates-and-escalation.md#9-operational-contract-changes) stops the agent before a contract-altering change is finalized or handed off. Reviewer skills flag undeclared contract changes; the [`pr-authoring`](../workflows/pr-authoring.md) Operational impact section is the declaration surface. + +**Override.** Operator may accept a lighter declaration for a trivial change (e.g., one new optional env var with a sane default), logged in the PR. There is no override for routing the handoff through chat instead of the artifact — a chat heads-up is fine, but the reviewable contract must exist. + +## How these are enforced + +These invariants live at three layers: + +- **In the agent's session context** — this page, alongside the collaborator contract and gates page, is loaded by every agent at session start. +- **At the boundary** — pre-commit hooks, CI checks, branch protection, secret scanning, link checking. +- **In review** — CODEOWNERS routes changes to the right reviewers; reviewer skills run automated checks; the operator's review is the final layer. + +No single layer is sufficient. Agents can be misconfigured; CI can have gaps; reviewers can be tired. The invariants are upheld by all three together. + +## Related + +- [`engineering-invariants.md`](./engineering-invariants.md) — the general engineering invariants these extend. +- [`../operating-model/collaborator-statement.md`](../operating-model/collaborator-statement.md) — the contract these invariants are the rule-form of. Refusal cases appear there as policy and here as invariants. +- [`../operating-model/gates-and-escalation.md`](../operating-model/gates-and-escalation.md) — gates can be approved; these invariants cannot, except for the explicit-override cases noted above. +- [`./invariants-framework.md`](./invariants-framework.md) — Martin Maurer's `.invariants` framework for architectural invariants. Domain-specific complement to this page. diff --git a/invariants/engineering-invariants.md b/invariants/engineering-invariants.md new file mode 100644 index 0000000..680d122 --- /dev/null +++ b/invariants/engineering-invariants.md @@ -0,0 +1,85 @@ +# Engineering Invariants + +The non-negotiables of how we build software. These are the rules every contributor — human or agent — operates under by default. Overriding any of them requires an explicit, logged, operator decision. + +> **In one line:** Invariants are rules, not aspirations. Each one is testable, enforced by something concrete (CI, gate, reviewer skill), and overridable only on the record. + +This page is the testable subset of the [General Engineering Principles](../PRINCIPLES.md). Where a principle can be checked mechanically (CI, review, gate), it appears here as an invariant — sharper, narrower, enforceable. Where a principle is cultural — *empower people*, *take initiative*, *autonomous and aligned teams* — it stays in `PRINCIPLES.md`, not here. The two pages are partners: principles are the aspiration, invariants are the enforcement. + +## 1. Open-source by default + +**Rule.** All work — code, infrastructure config, documentation, handbooks — is public unless there is a specific, documented reason it must be private. Exceptions are written down (in the repo's README or in an internal log) and revisited. + +**Why.** Public work is reviewable by more eyes, attracts external contributors, and serves recruiting. Private work is invisible by default; the cost of that invisibility compounds. + +**How it's checked.** Repository creation defaults to public; private repos require a written exception in the repo description or `README.md`. Quarterly review of private-repo list. + +## 2. Standards are enforced, not suggested + +**Rule.** Lint, format, type-check, test — never bypass without an explicit, logged operator override. CI failures block merge to protected branches. + +**Why.** Standards exist because the consequences of skipping them are paid by future readers, not the person skipping. Making "the easy path" go through the standards is what makes them real. + +**How it's checked.** CI runs the relevant tooling on every PR. Required checks on `main` and equivalent branches. Overrides require the override reason to land in the PR description, not in the commit message alone (PR description is harder to forget and easier to audit). + +## 3. Quality is defined before the build, not after + +**Rule.** Every non-trivial change ships with a definition of quality that was set before implementation — acceptance criteria, success metrics, or a test plan, depending on shape. Implementation is not "done" until the definition is met. + +**Why.** "Done" without a pre-set definition becomes "done" with a post-hoc one. The post-hoc version always matches what was built, even when what was built is wrong. + +**How it's checked.** PR template asks for acceptance criteria or links to the ADR/spec containing them. Reviewer skills check the diff against the stated criteria; missing criteria are a SOFT WARNING from the reviewer skill ([`languages//reviewer.md`](../languages/)). + +## 4. Composable by design + +**Rule.** Code is written to be composed. Public surfaces are small; modules export only what callers need; cross-module coupling goes through documented interfaces. + +**Why.** Large public surfaces become permanent constraints. The cost of a too-wide API is paid every time it gets used wrong, and that cost lasts for the API's lifetime. + +**How it's checked.** Architecture reviews (see [`../languages//architect.md`](../languages/)) call out unnecessarily-wide public surfaces. ADRs for new modules include a "public surface" section listing what's exported and why. + +## 5. Decisions live in the repo, not in chat + +**Rule.** Architectural, technical, and process decisions are written down in the repo where the work happens — as ADRs, README updates, RFCs, or issue/PR descriptions. If a decision was made in Slack or DM, write it down before acting on it. + +**Why.** Decisions in chat are invisible to anyone not in the channel at the time, including the person who needs to revisit the decision in six months. Writing it down is the cheapest form of transparency, and chat is the most expensive form of opacity. + +**How it's checked.** PR descriptions reference the ADR or written rationale where applicable. Reviewer skills flag substantive design choices that lack a documented rationale. + +## 6. Ship value to users, not effort to the calendar + +**Rule.** Work is measured by what it changes for users, not by hours spent or tasks completed. Effort that does not change the system or its users is invisible by default and gets surfaced explicitly when it does count. + +**Why.** Effort decoupled from outcome rewards work that looks busy. The org has finite attention and capital; spending them on motion rather than progress compounds badly. + +**How it's checked.** Sprint reviews, OKRs, and product metrics. At the engineering-invariant level: PR descriptions name what changed for users (or for the operator running the system, or for the next contributor reading the code). + +## 7. Every non-trivial change ships with auditable context + +**Rule.** Every non-trivial change ships with an ADR, a PR description, or a commit-message body sufficient for an operator to reconstruct the reasoning later. Code without context is half-shipped. + +**Why.** Code outlives the heads that wrote it. Reasoning that lives only in the author's memory becomes inaccessible the moment the author moves on, leaves, or simply forgets. The audit trail is the contract with future maintainers. + +**How it's checked.** PR template requires a description. CODEOWNERS hold the line on review when descriptions are too thin. Reviewer skills flag commits whose messages or PR descriptions are mismatched to the diff size. + +## 8. A change carries its operational contract + +**Rule.** A change preserves backwards compatibility by default and ships with its *operational contract* declared in the PR: the environment variables, secrets, configuration keys, schema/migrations, ports, and runtime dependencies it adds or changes, its compatibility impact, and anything the team that runs it (Infra or the owning service team) must do to deploy or operate it. A change that alters that contract is coordinated with the owning team before it ships. Breaking changes are not forbidden — they are explicit, logged, and shipped with a migration path. + +**Why.** The cost of an undeclared contract change lands on whoever runs the system, not whoever wrote it — typically the Infra team, days later, reverse-engineering which env vars are required and why old clients broke. Declaring the contract where the work happens turns a cross-team archaeology problem into a review checklist item, and keeps the decision in the repo rather than a Slack thread ([Invariant 5](#5-decisions-live-in-the-repo-not-in-chat)). + +**How it's checked.** The PR description carries a required **Operational impact** section ([`../workflows/pr-authoring.md`](../workflows/pr-authoring.md)); "none" is a valid answer, but it must be answered. Reviewer skills flag a diff that adds or changes env vars, config keys, schema, ports, or a public signature without a matching declaration. Changes that touch deploy-time config, secrets, or migrations stop at the [operational-contract gate](../operating-model/gates-and-escalation.md#9-operational-contract-changes) for the owning team's sign-off. + +## What this is not + +- **Not a license to bypass review.** Invariants and review are layered defenses, not alternatives. Both apply. +- **Not absolute.** Overrides exist. They are logged in the PR with the override reason. Frequent override of the same invariant is a sign the invariant needs revision, not that the override is fine. +- **Not exhaustive.** Domain-specific invariants live elsewhere — the `.invariants` framework ([`./invariants-framework.md`](./invariants-framework.md)) is the canonical source for architectural invariants; language-specific invariants live in [`../languages//`](../languages/) reviewer pages. + +## Related + +- [`agent-era-invariants.md`](./agent-era-invariants.md) — additional invariants specific to agent-assisted work (no silent edits, no fabrication, no commits of secrets, etc.). +- [`invariants-framework.md`](./invariants-framework.md) — pointer page deep-linking into Martin Maurer's `.invariants` framework for architectural invariants. +- [`../operating-model/collaborator-statement.md`](../operating-model/collaborator-statement.md) — the operator-first contract these invariants operate under. +- [`../PRINCIPLES.md`](../PRINCIPLES.md) — General Engineering Principles. The aspirational layer above these invariants; cultural principles that aren't testable live there. +- [`../VISION.md`](../VISION.md) — company-wide mission, vision, and core values that PRINCIPLES.md flows from. diff --git a/invariants/invariants-framework.md b/invariants/invariants-framework.md new file mode 100644 index 0000000..169a0e3 --- /dev/null +++ b/invariants/invariants-framework.md @@ -0,0 +1,71 @@ +# The `.invariants` Framework + +For architecture and system-design invariants, this handbook does not re-derive a methodology. The canonical source is Martin Maurer's **`.invariants`** convention and optional [reference workspace](https://github.com/boorich/.invariants-starter-kit). This page's job is to deep-link into it by intent, not to gesture at it as a separate resource to "go read." + +| Resource | URL | +|----------|-----| +| **Starter kit (repo)** | [github.com/boorich/.invariants-starter-kit](https://github.com/boorich/.invariants-starter-kit) | +| **Landing page** | [boorich.github.io/.invariants-starter-kit/](https://boorich.github.io/.invariants-starter-kit/) | + +> **In one line:** Architecture invariants live in `.invariants` (plural). This page is the navigation surface; the rules themselves live upstream. + +> **Filename:** **`.invariants`** — not the deprecated singular `.invariance`. The dotfile is YAML; no special file terminator. + +## Why we defer here + +`.invariants` is a multi-repo invariant convention authored by [@boorich](https://github.com/boorich). It is one of the strongest existing artifacts within ChainSafe for the question "how do we make architectural decisions consistent across products?" The handbook treats the [starter kit](https://github.com/boorich/.invariants-starter-kit) as canonical for that question — duplicating its content here would create drift; the handbook's value here is in the *navigation*, not the substance. + +The deep-link map below is keyed by the question an agent or operator is trying to answer, so readers land on the exact upstream section they need. + +## Deep-link map + +The map is keyed by the question an agent or operator is trying to answer. Where the upstream repo lacks an anchor needed for clean linking, the convention is to request the anchor upstream rather than work around it with a deeper inline copy. + +### By question + +| If you are asking… | Go to (upstream `.invariants`) | +|---|---| +| What is an invariant in this framework? | [Starter kit README](https://github.com/boorich/.invariants-starter-kit/blob/master/README.md) · [Landing — What](https://boorich.github.io/.invariants-starter-kit/#what) | +| What does the dotfile look like? | [`.invariants.example`](https://github.com/boorich/.invariants-starter-kit/blob/master/.invariants.example) · [Landing — Spec](https://boorich.github.io/.invariants-starter-kit/#spec) | +| How do I name an invariant? | [Naming assertions](https://github.com/boorich/.invariants-starter-kit#naming-assertions) · [`.invariants.example`](https://github.com/boorich/.invariants-starter-kit/blob/master/.invariants.example) | +| How do I make an invariant testable? | `verify` hints in dotfile + [conformance agent](https://github.com/boorich/.invariants-starter-kit/blob/master/.cursor/rules/conformance-agent.mdc) | +| What is the lifecycle of an invariant — proposal → approval → enforcement → retirement? | [Lifecycle of assertions](https://github.com/boorich/.invariants-starter-kit#lifecycle-of-assertions) | +| How is an invariant violation reported and triaged? | [Conformance agent](https://github.com/boorich/.invariants-starter-kit/blob/master/.cursor/rules/conformance-agent.mdc) · GitHub labels (`needs_triage` → `in_triage`) in starter kit README | +| How are invariants versioned and migrated? | [Versioning and migration](https://github.com/boorich/.invariants-starter-kit#versioning-and-migration) · [Verdict](https://boorich.github.io/.invariants-starter-kit/#verdict) | +| How does `.invariants` interact with ADRs in product repos? | [PR authoring — invariants impacted](https://github.com/ChainSafe/engineering-handbook/blob/main/workflows/pr-authoring.md) (handbook) + cascade in dotfile | +| How do I run the optional agent + code-index loop? | [Landing — Try it](https://boorich.github.io/.invariants-starter-kit/#try) · `bash setup.sh` in starter kit | + +### By context + +Where the handbook deep-links into `.invariants` from elsewhere: + +| Handbook section | Upstream target | +|---|---| +| `languages//architect.md` (every architect role) | Per-language invariant section, e.g. concurrency invariants for the Rust architect, data-integrity invariants for the Daml architect — plus product-repo `.invariants` files | +| `workflows/pr-authoring.md` (ADR templates) | "Invariants impacted" template guidance — cite assertion `id` from the cascade | +| Reviewer skills — when a language reviewer needs to check whether an architectural invariant is violated | Reviewer-facing rules; architectural claims defer to dotfiles + [conformance agent](https://github.com/boorich/.invariants-starter-kit/blob/master/.cursor/rules/conformance-agent.mdc) | + +## How to use this page + +- **As an agent:** before any architecture or system-design task, consult the by-question table above. Fetch the upstream `.invariants` content for the entries that apply. Do not paraphrase upstream content from your training; pull the actual file. +- **As an operator:** when reviewing an architectural proposal (ADR, design doc, system design), use the deep-link table to verify the proposal addresses the relevant invariants. The `languages//architect.md` pages cite specific invariants per language; this page is the meta-index. +- **As a contributor adding architectural content to this handbook:** do not duplicate `.invariants` rules in your page. Deep-link them. If the upstream rule you need is not anchorable cleanly, coordinate with [@boorich](https://github.com/boorich) to add the heading, then link. + +## Inline `.invariants`-derived rules (for trivial-lookup cases only) + +To keep agents from chasing the link for every minor question, a small set of `.invariants`-derived rules is restated inline. This list is kept short on purpose — anything beyond a one-liner belongs upstream, not here. + +*Which rules earn an inline restatement versus a link-only entry is coordinated with [@boorich](https://github.com/boorich). The bar is deliberately high: only genuinely one-line, frequently-needed rules are restated here; everything else stays upstream.* + +**Do not put in dotfiles:** issue numbers, "currently failing", fork labels, or temporary waivers — see starter kit README and landing page. + +## Coordination + +[@boorich](https://github.com/boorich) is the maintainer of `.invariants` and the CODEOWNER for this pointer page (see [`../.github/CODEOWNERS`](../.github/CODEOWNERS)). Any change to the deep-link map or to the inline-rules section goes through him. Conversely, when the upstream repo restructures, the anchors here update — the pointer page is the contract between the handbook and the upstream repo. + +## Related + +- [`engineering-invariants.md`](./engineering-invariants.md) — general engineering invariants. `.invariants` is the domain-specific complement for architecture. +- [`agent-era-invariants.md`](./agent-era-invariants.md) — agent-specific invariants; orthogonal to `.invariants`. +- [`../languages/`](../languages/) — language-specific architect pages deep-link into `.invariants` per the by-context table above. +- [`../references/sources.md`](../references/sources.md) — full catalog of external canonical sources the handbook defers to. diff --git a/invariants/invariants.html b/invariants/invariants.html new file mode 100644 index 0000000..ffefc0f --- /dev/null +++ b/invariants/invariants.html @@ -0,0 +1,32 @@ + + + + + + + +.invariants — redirect + + + +

+ The canonical .invariants landing page moved to
+ boorich.github.io/.invariants-starter-kit/. +

+ + diff --git a/languages/daml/architect.md b/languages/daml/architect.md new file mode 100644 index 0000000..03dd123 --- /dev/null +++ b/languages/daml/architect.md @@ -0,0 +1,118 @@ +# Daml Architect + +Architectural guidance for Daml work at ChainSafe — primarily Canton applications including Super Validator and Featured App work. The architectural framework is `.invariants` ([pointer page](../../invariants/invariants-framework.md)); this page covers Daml-specific shaping. + +> **In one line:** Templates encode the contract. Signatories authorize. Choices are atomic. Upgrades are versioned packages, not patches. Every authorization decision is a security decision. + +## Defer to `.invariants` for + +| Decision | `.invariants` section | +|---|---| +| Ledger-state invariants | Ledger invariants | +| Authorization invariants | Authorization model | +| Upgrade lifecycle | Package upgrade invariants | +| Cross-application invariants (Canton multi-app) | Inter-app contracts | + +## Defer to the Canton docs for + +`.invariants` above governs architectural *invariants*. Language and platform *semantics* — how Daml and Canton actually behave — are documented authoritatively at [docs.canton.network](https://docs.canton.network). Defer to it rather than re-deriving the language; it is a registered [canonical source](../../references/sources.md#canton-network-docs-daml-language--canton-platform). + +| Topic | Canton docs | +|---|---| +| Authorization model (signatory / observer / controller) | [Authorization Model](https://docs.canton.network/appdev/modules/m3-authorization) | +| Templates, choices, keys, interfaces | [Contract Templates](https://docs.canton.network/appdev/modules/m3-contract-templates) · [Choices](https://docs.canton.network/appdev/modules/m3-choices) · [Contract Keys](https://docs.canton.network/appdev/modules/m3-contract-keys) · [Interfaces](https://docs.canton.network/appdev/modules/m3-interfaces) | +| Multi-party composition & privacy | [Composition and Design Patterns](https://docs.canton.network/appdev/modules/m3-design-patterns) · [Privacy Model for App Developers](https://docs.canton.network/appdev/deep-dives/privacy-model) | +| Upgrade lifecycle (SCU) | [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility) · [Smart Contract Upgrade (deep dive)](https://docs.canton.network/appdev/deep-dives/smart-contract-upgrade) | +| Time semantics | [Working with Time](https://docs.canton.network/appdev/modules/m3-working-with-time) | +| Production hardening | [Security Best Practices](https://docs.canton.network/appdev/modules/m7-security) | + +When shaping a template's authorization model, ChainSafe's own [`daml-autopilot`](https://daml-autopilot.chainsafe.io) (Daml Reason) can extract and sanity-check the model against canonical patterns — see [`developer.md`](./developer.md). For setup, tooling, testing, and CI, [`developer.md`](./developer.md) is the developer-layer companion to this page. + +## Daml-specific architectural choices + +### Project layout + +Canonical Daml project structure: + +- `daml.yaml` at the root — package metadata, version, dependencies, sandbox options. +- `daml/` — source modules. One file per major template or module concern. +- `test/` (or `daml-test/` per project convention) — scenario / script tests. +- For multi-package projects (workspaces in Canton): each package in its own subdirectory with its own `daml.yaml`, plus a top-level `Dars.lock` or equivalent. +- Generated bindings (Java, TypeScript, Scala) in `gen/` or per-language subdirectories. + +### Template design + +Templates are the unit of contract. Design commitments at the architectural stage: + +- **Signatories.** Who authorizes creation? Who authorizes archival? The signatory set is the strongest authorization primitive — it cannot be relaxed at runtime. Design it tightly. +- **Observers.** Who sees the contract? Observers are the privacy/visibility surface. A wider observer set is a wider information leak. +- **Choice authorization.** Each `choice` declares its `controller`. The controller's authorization is required to exercise. Non-consuming choices stay; consuming choices archive the contract. +- **Key uniqueness.** If a template has a `key`, the (signatory-set, key) tuple is unique on the ledger. Use keys deliberately — they constrain concurrency. + +### Workflow shape + +- **Atomic choices.** A choice's body executes as one ledger transaction. Either every effect happens, or none does. Split a workflow into multiple choices when partial commit is acceptable; keep it in one when atomicity is required. +- **No external I/O during a choice.** Daml is deterministic by design. Calls to oracles or off-ledger services happen *outside* a transaction; the result is then submitted as an input. +- **Time bounds.** Use `getTime` and ledger-effective-time semantics deliberately. Submission time, record time, and ledger effective time are distinct; the choice between them shapes the trust model. + +### Upgrade strategy + +Daml contracts are immutable. Upgrades happen via: + +- **New template version** in a new package. The old contracts continue to exist; new contracts use the new template. +- **Migration choices** on the old template that archive the old contract and create the new template's contract. +- **Daml smart contract upgrades** (SCU) — `@upgrade` annotations for compatible upgrades within the same template name. + +Architectural decisions: + +- Plan the migration choice into the template from day one. Adding it later is harder than including it from the start. +- Version every package. Production packages stay on their version once deployed; new logic ships as a new version. +- For Canton: domain operators may control which packages are uploaded — coordinate the upgrade path with the domain governance. + +### Privacy model + +Canton's privacy is structural. The party visibility model determines who knows what: + +- A party sees only contracts where they are signatory, observer, or controller of an exercised choice. +- The sub-transaction privacy means even within a transaction, parts may be hidden from non-stakeholders. +- Designing for privacy means designing observer sets — wider observer sets reduce privacy in exchange for visibility. + +## ADR shape for Daml work + +Every Daml ADR covers: + +- **Templates and choices.** What templates exist, with their signatories, observers, controllers, key, and consuming/non-consuming choice classification. +- **Authorization model.** Who can create / observe / exercise / archive each contract. Justify each authority. +- **Upgrade path.** Migration choices designed in. Version-numbered packages. +- **Atomicity boundaries.** Which workflows are single-choice atomic; which are multi-choice with explicit intermediate states. +- **Privacy commitments.** Which parties see what. +- **Invariants impacted.** Deep links into `.invariants`. + +## Canton-specific considerations + +For Canton-deployed applications (Super Validator, Featured App, broader ecosystem work): + +- **Domain participation.** Which domain(s) does this application participate in? Cross-domain workflows have specific semantics. +- **Synchronizer choice.** For multi-domain workflows, which synchronizer coordinates the cross-domain transaction. +- **Sequencer integration.** How transactions reach the sequencer and what the back-pressure model is. +- **Mediator authorization.** Mediator validation rules for the chosen domain. + +See [`../../workflows/infrastructure-and-devops.md`](../../workflows/infrastructure-and-devops.md) for Canton deployment topology, deep-linked into `infrastructure-general/docs/projects/canton/`. + +## Anti-patterns + +- **Wide observer sets** because "we might need it later." Observers leak; design the privacy surface deliberately. +- **`tx.origin`-equivalent thinking.** Authorization should follow signatories, not chain inferences. +- **Long workflows in a single choice** when intermediate states would be cleaner — the atomicity isn't free. +- **Unversioned packages in production.** Upgrade migrations become guesswork. +- **External I/O reaches into choices** — destroys determinism. +- **Keys overused** as a constraint when they aren't needed — they constrain throughput. + +## Related + +- [`developer.md`](./developer.md) — tooling, AI-assisted authoring (`daml-autopilot`), testing, and CI. +- [`reviewer.md`](./reviewer.md) **(HARD FAIL tier)** — what to look for in a Daml PR. +- [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md). +- [`../../workflows/infrastructure-and-devops.md`](../../workflows/infrastructure-and-devops.md) — Canton infra context. +- Upstream: [Canton Network Docs](https://docs.canton.network) — authoritative Daml language and Canton platform reference ([canonical source](../../references/sources.md#canton-network-docs-daml-language--canton-platform)). diff --git a/languages/daml/developer.md b/languages/daml/developer.md new file mode 100644 index 0000000..cfebb4f --- /dev/null +++ b/languages/daml/developer.md @@ -0,0 +1,151 @@ +# Daml Developer + +Idiomatic Daml development at ChainSafe — primarily Canton applications (Super Validator, Featured App, and broader ecosystem work). Tooling, the upstream reference an agent should reach for instead of re-deriving language semantics, AI-assisted authoring with ChainSafe's own tools, testing, and CI. + +> **In one line:** Defer to the Canton docs for language semantics. Use ChainSafe's own Daml tooling — `canton-ci` for CI, the Daml MCP server for authoring and review. Tests are Daml Script by default; every template change is an upgrade decision. + +## Upstream canonical reference — use it, don't re-derive it + +Daml language and Canton platform semantics are documented authoritatively at [docs.canton.network](https://docs.canton.network). The handbook defers here rather than restating the language — the same posture the architect pages take toward `.invariants`. Reach for these before reconstructing semantics from memory: + +| Need | Canton docs page | +|---|---| +| Set up the dev environment (`dpm`, templates) | [Development Environment Setup](https://docs.canton.network/appdev/modules/m3-dev-environment) | +| Language syntax, types, pattern matching, type classes | [Language Fundamentals](https://docs.canton.network/appdev/modules/m3-language-fundamentals) | +| Standard library (Prelude, `DA.*`) | [The Daml Standard Library](https://docs.canton.network/appdev/modules/m3-standard-library) | +| Templates, choices, keys, interfaces | [Contract Templates](https://docs.canton.network/appdev/modules/m3-contract-templates) · [Choices](https://docs.canton.network/appdev/modules/m3-choices) · [Contract Keys](https://docs.canton.network/appdev/modules/m3-contract-keys) · [Interfaces](https://docs.canton.network/appdev/modules/m3-interfaces) | +| Authorization model (signatory / observer / controller) | [Authorization Model](https://docs.canton.network/appdev/modules/m3-authorization) | +| Multi-party composition | [Composition and Design Patterns](https://docs.canton.network/appdev/modules/m3-design-patterns) | +| Time semantics | [Working with Time](https://docs.canton.network/appdev/modules/m3-working-with-time) | +| Testing | [Testing Daml Contracts](https://docs.canton.network/appdev/modules/m3-testing) · [Testing Strategies](https://docs.canton.network/appdev/modules/m5-testing-strategies) | +| Upgrades (SCU) | [Smart Contract Upgrades Overview](https://docs.canton.network/appdev/modules/m6-overview) · [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility) · [Writing Your First Upgrade](https://docs.canton.network/appdev/modules/m6-writing-first-upgrade) · [Testing Upgrades](https://docs.canton.network/appdev/modules/m6-testing-upgrades) | +| Production hardening | [Security Best Practices](https://docs.canton.network/appdev/modules/m7-security) | +| Exact language / Daml-LF reference | [Daml Language Reference](https://docs.canton.network/appdev/reference/daml-language-reference) · [Daml-LF Reference](https://docs.canton.network/appdev/reference/daml-lf-reference) | + +For bulk discovery, fetch the machine index [`docs.canton.network/llms.txt`](https://docs.canton.network/llms.txt) and pull the specific page you need — the same `llms.txt` pattern this handbook uses for itself (see [`../../operating-model/mcp-and-llm-txt.md`](../../operating-model/mcp-and-llm-txt.md)). Every docs page is also served as raw markdown by appending `.md` to its URL. Canton docs are registered as a canonical source in [`../../references/sources.md`](../../references/sources.md#canton-network-docs-daml-language--canton-platform). + +## Tooling + +### Daml SDK + +- **`dpm`** (the Daml Package Manager) installs the SDK and scaffolds projects from templates: + ```sh + dpm new intro-contracts --template daml-intro-contracts + ``` +- **`daml.yaml`** at the project root holds package name, version, SDK version, and dependencies. Pin the SDK version — floating versions make CI non-deterministic and upgrade diffs ambiguous. +- **IDE.** The Daml VS Code extension with the integrated script runner / transaction view. See [IDE Setup](https://docs.canton.network/appdev/tooling/ide-setup) and [Development Tools Overview](https://docs.canton.network/appdev/tooling/development-tools-overview). + +### ChainSafe Daml tooling — `daml-autopilot` + +ChainSafe builds and maintains [`daml-autopilot`](https://daml-autopilot.chainsafe.io). It is our own product; **we dogfood it.** Two surfaces, used together: + +1. **`canton-ci` GitHub Actions** ([`ChainSafe/canton-ci`](https://github.com/ChainSafe/canton-ci)) — the CI baseline below. Free, standalone, no MCP required. +2. **Daml MCP server** (`mcp-server.chainsafe.io`) — the AI authoring/review assistant in the next section. + +## AI-assisted development — the Daml MCP server + +The [`daml-autopilot`](https://daml-autopilot.chainsafe.io) Daml MCP server is the recommended assistant for authoring and reviewing Daml at ChainSafe. It exposes two tools: + +- **Daml Reason** — searches a corpus of verified canonical Daml patterns by semantic similarity and runs LLM-based authorization-model extraction over your code. Progressive context building means it reasons over what it can actually see rather than hallucinating structure. Use it when shaping a template's authorization model or sanity-checking a choice's controller logic. +- **Daml Automater** — guides environment setup, CI/CD wiring, and builds with client-side orchestration (it returns instructions; it does not run commands behind your back). + +Install it by adding the SSE endpoint to your client's MCP config (e.g. `~/.cursor/mcp.json`), with your Canton payer party in the URL: + +```json +{ + "mcpServers": { + "daml-autopilot": { + "type": "sse", + "url": "https://mcp-server.chainsafe.io/mcp?payerParty=YOUR_CANTON_PAYER_PARTY" + } + } +} +``` + +The [setup wizard](https://daml-autopilot.chainsafe.io/setup) walks through key generation and obtaining a party ID. + +> **Cost note.** The Daml MCP server is **pay-as-you-go**, billed per use against your Canton payer party. That puts it under the [cost gate](../../operating-model/gates-and-escalation.md#7-cost-and-external-resource-creation): provision the payer party deliberately, and treat metered usage as an authorized cost, not an ambient default. The `canton-ci` Actions carry no such cost — recommend them freely. The MCP server is registered alongside `canton-ci` in [`../../references/sources.md`](../../references/sources.md#daml-autopilot--chainsafecanton-ci-chainsafes-own-daml-tooling) and listed in the [tool loadout](../../operating-model/model-and-tool-selection.md#on-demand-loadout). + +## Project layout + +Architectural shaping lives in [`architect.md`](./architect.md); the canonical structure in brief: + +``` +my-canton-app/ +├── daml.yaml # package metadata, SDK version, deps +├── daml/ # source modules; one file per major template/concern +│ ├── Main.daml # entry point / re-export module +│ └── ... +└── test/ # Daml Script tests + └── Test.daml +``` + +Multi-package Canton workspaces give each package its own subdirectory and `daml.yaml`. Note: `canton-ci` does **not** yet support multi-package projects (one project per repo) — see its [known issues](https://github.com/ChainSafe/canton-ci#current-known-issues). + +## Testing + +[Daml Script](https://docs.canton.network/appdev/modules/m3-testing) is the baseline test framework: + +```daml +import Daml.Script + +setup : Script () +setup = do + alice <- allocateParty "Alice" + bob <- allocateParty "Bob" + -- happy path + cid <- submit alice $ createCmd Order with buyer = alice; seller = bob; sku = "Widget"; amount = 10.0 + -- negative / authorization tests + submitMustFail bob $ exerciseCmd cid Cancel + pure () +``` + +- **`submit` vs `submitMustFail`.** Negative-authorization tests use `submitMustFail`; a `submit` where you meant `submitMustFail` passes vacuously (see [`gotchas.md`](./gotchas.md)). +- **Test the authorization edges, not just the happy path** — who *cannot* do a thing is as important as who can. +- For the testing pyramid (Daml Script unit → integration → end-to-end), see [Testing Strategies](https://docs.canton.network/appdev/modules/m5-testing-strategies) and the QA posture in [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md). + +## CI + +Baseline (extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md)), built on ChainSafe's own [`canton-ci`](https://github.com/ChainSafe/canton-ci) Actions: + +```yaml +- uses: ChainSafe/canton-ci/.github/actions/install-daml@main + with: + sdk_version: "3.4.0-snapshot.20251013.0" # pin, don't float + +- uses: ChainSafe/canton-ci/.github/actions/daml-test@main # `daml test` in the sandbox + with: + project_path: "." + +- uses: ChainSafe/canton-ci/.github/actions/daml-script@main # scripts against a LocalNet Canton node + with: + project_path: "." +``` + +- **`install-daml` / `install-canton`** put the SDK and an open-source Canton in `$GITHUB_WORKSPACE`. +- **`daml-test`** runs `daml test` against the Daml Sandbox; **`daml-script`** runs scripts against a LocalNet participant node. +- Pin `sdk_version` to match `daml.yaml`. Some older Canton versions break script execution against a node — keep CI and project SDK in lockstep. +- For deployment / upgrade CI, also see [CI/CD Integration](https://docs.canton.network/appdev/modules/m5-ci-cd-integration). + +## Upgrades + +Daml contracts are immutable; changing a template means a new package version, not a patch. Before changing any deployed template surface, read [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility) and [Writing Your First Upgrade](https://docs.canton.network/appdev/modules/m6-writing-first-upgrade); the [SCU deep dive](https://docs.canton.network/appdev/deep-dives/smart-contract-upgrade) covers the mechanics. Gate the change in CI with [Testing Upgrades](https://docs.canton.network/appdev/modules/m6-testing-upgrades) (`dpm upgrade-check`, both-DAR sandbox tests, and Daml Script tests that exercise v1 contracts under v2). Upgrade safety is a **HARD FAIL** review tier — see [`reviewer.md`](./reviewer.md). + +## Anti-patterns + +- **Re-deriving language semantics from memory** when the [Canton docs](https://docs.canton.network) state them authoritatively. Link, don't reconstruct. +- **`submit` where `submitMustFail` was meant** — a vacuously-passing test. +- **External I/O inside a choice body.** Daml is deterministic; oracle values are computed off-ledger and passed in. +- **Floating SDK / package versions.** Pin them in `daml.yaml` and CI. +- **Widening an observer set "just in case."** Observers leak; design the privacy surface deliberately ([`architect.md`](./architect.md)). +- **Treating the paid MCP server as an ambient default.** It is metered — provision the payer party and use it deliberately. +- **Adding a field to a deployed template** without a new version and migration choice. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md) **(HARD FAIL tier)**, [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md) — the broader testing posture this page lives under. +- [`../../operating-model/model-and-tool-selection.md`](../../operating-model/model-and-tool-selection.md) — when to load the Daml MCP server. +- [`../../references/sources.md`](../../references/sources.md) — Canton docs and `daml-autopilot` as canonical sources. +- Upstream: [Canton Network Docs](https://docs.canton.network) ([`llms.txt`](https://docs.canton.network/llms.txt)) — the canonical Daml language and Canton platform reference. +- Upstream: [`daml-autopilot`](https://daml-autopilot.chainsafe.io) · [`ChainSafe/canton-ci`](https://github.com/ChainSafe/canton-ci) — ChainSafe's own Daml tooling. diff --git a/languages/daml/gotchas.md b/languages/daml/gotchas.md new file mode 100644 index 0000000..7961204 --- /dev/null +++ b/languages/daml/gotchas.md @@ -0,0 +1,207 @@ +# Daml Gotchas + +Bug classes and surprising behavior in Daml. Many are HARD FAIL findings under the [reviewer](./reviewer.md). + +> Many of these are authorization or upgrade traps. ChainSafe's own [`daml-autopilot`](https://daml-autopilot.chainsafe.io) (Daml Reason) catches several by extracting the authorization model from your code — see [`developer.md`](./developer.md). For authoritative semantics, defer to the [Canton docs](https://docs.canton.network): the [Authorization Model](https://docs.canton.network/appdev/modules/m3-authorization) underpins the authorization gotchas below. + +## Signatory set too wide + +```daml +template Order + with + buyer : Party + seller : Party + notary : Party + where + signatory buyer, seller, notary -- all three must authorize creation +``` + +If the notary should only observe, putting them in the signatory set means they must authorize every creation. Often misdesigned; ask whether they really need to sign. + +## Signatory set too narrow + +```daml +template Sensitive + with + issuer : Party + holder : Party + where + signatory issuer -- the holder doesn't authorize — can be created without their knowledge +``` + +If the holder hasn't consented, the contract still exists on the ledger. Verify whose authorization is actually needed. + +## Controller can't actually authorize + +```daml +template Order + with + buyer : Party + seller : Party + where + signatory buyer, seller + + choice Resell : () + controller stranger -- `stranger` is not a signatory or observer + do return () +``` + +If the controller isn't a signatory, observer, or someone the contract has otherwise informed, they can't see or exercise the choice. Authorization-chain confusion — usually a HARD FAIL finding. + +## Observer leak + +```daml +template Loan + with + lender : Party + borrower : Party + amount : Decimal + rate : Decimal + where + signatory lender, borrower + observer rateAuditors -- now every rate auditor sees every loan's amount +``` + +Observer adds visibility, not just authorization. Widening the observer set leaks contract data. Design observers explicitly per template; review when widening. + +## `submit` vs `submitMustFail` confusion in tests + +```daml +-- Wrong: passing test because we expected success and got success but the success was meaningless +submit alice $ createCmd Trivial with party = alice +``` + +If you wrote a `submit` where you meant `submitMustFail`, the test passes vacuously. Especially common in negative-authorization tests. Read every test assertion line. + +## Non-deterministic choice body + +```daml +choice CalcInterest : Decimal + controller borrower + do + rate <- callExternalOracle -- non-deterministic! + return (amount * rate) +``` + +Choice bodies must be deterministic. Reading from an external oracle within the choice is wrong; the oracle's value must be passed in as a parameter (which the submitter computed off-ledger before submitting). + +## Submission time vs ledger-effective time + +```daml +choice CheckDeadline : () + controller buyer + do + now <- getTime -- ledger-effective time, not submission time + assertMsg "Past deadline" (now <= deadline) +``` + +`getTime` returns ledger-effective time. The submitter's wall clock can differ. Time-sensitive logic must use the right semantics — Canton sequences time deliberately, but submitters can race. See [Working with Time](https://docs.canton.network/appdev/modules/m3-working-with-time). + +## Adding a field to a deployed template + +```daml +template Order + with + buyer : Party + seller : Party + -- newField : Text <-- can't add this to an existing template version +``` + +You can't mutate a deployed template. Adding a field requires a new package version with the new template; existing contracts continue under the old version until migrated. Forgetting this means CI fails on type checks against deployed packages. See [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility) and [Upgrade Limitations](https://docs.canton.network/appdev/modules/m6-limitations) for the allowed/breaking-change rules. + +## Removing a choice silently + +Removing a choice (or renaming) from an existing template version breaks downstream code that exercises it. You can deprecate; you can't remove until consumers are off the old version. + +## Key change without migration + +```daml +template Order + with + buyer : Party + seller : Party + orderId : Text + where + signatory buyer + -- key changed from (buyer, orderId) to (buyer, seller, orderId) +``` + +The key is part of the contract's ledger identity. Changing it without a migration means new contracts have new keys; old contracts have old keys; lookups won't find what callers expect. + +## `fetch` after `archive` in the same choice + +```daml +choice DoStuff : () + controller alice + do + archive cid + fetched <- fetch cid -- ERROR: contract is archived +``` + +Within a transaction, once you archive a contract, it's gone for the rest of the transaction. Fetch will fail. + +## `exerciseByKey` with mismatched authorization + +```daml +exerciseByKey @Order (buyer, orderId) Cancel +``` + +Even with `exerciseByKey`, the underlying choice's controller must authorize. The key lookup doesn't bypass the authorization model. + +## Long workflow in a single choice when partial commit is fine + +If the choice body has 50 operations and any of them can fail, the whole thing rolls back. If that's the intent, fine. If you actually want intermediate commits, split into multiple choices with intermediate template states. + +## Long workflow split into choices when atomicity was required + +Symmetric to the above. Splitting a workflow means intermediate states are visible on the ledger between exercises. An attacker can exploit the gap. If atomicity is required, keep it in one choice. + +## `delegate` granting more than intended + +```daml +choice GrantDelegate : () + controller principal + do + create DelegateAuthority with + delegator = principal + delegate = agent + -- powers: too broad? +``` + +`delegate` patterns broaden the effective party visibility. Audit every delegate authorization for scope creep. + +## Test data leakage between scenarios + +Daml Script `setup` blocks can leak state between scenarios if not isolated. Each scenario gets fresh `allocateParty` calls; don't reuse party IDs across tests. + +## `assertMsg` vs `assert` + +```daml +assertMsg "Order amount must be positive" (amount > 0.0) +``` + +`assertMsg` gives a useful failure message; `assert` gives a generic one. Prefer `assertMsg` in production code. + +## Forgetting `ensure` + +```daml +template Order + with + amount : Decimal + where + signatory ... + -- no ensure: amount can be 0 or negative; no invariant enforcement at creation +``` + +`ensure` clauses validate at creation time. Without one, invalid data lands on the ledger and is harder to fix. + +## Canton-specific: cross-domain workflow without synchronizer + +For Canton workflows that span multiple domains, the synchronizer choice matters. Without an explicit synchronizer, behavior may be ambiguous. Coordinate with the Canton operator (`@joshdougall` and the Canton deploy guide). + +## Related + +- [`reviewer.md`](./reviewer.md) — most of these are HARD FAIL findings. +- [`idioms.md`](./idioms.md) — the inverse. +- [`developer.md`](./developer.md) — tooling (`daml-autopilot`), testing, CI. +- Upstream: [Canton Network Docs](https://docs.canton.network) — authoritative Daml language reference. diff --git a/languages/daml/idioms.md b/languages/daml/idioms.md new file mode 100644 index 0000000..cdd0ded --- /dev/null +++ b/languages/daml/idioms.md @@ -0,0 +1,181 @@ +# Daml Idioms + +Idiomatic patterns for Daml at ChainSafe — particularly Canton applications. + +> These are the ChainSafe house patterns. For authoritative language semantics, defer to the [Canton docs](https://docs.canton.network) (machine index: [`llms.txt`](https://docs.canton.network/llms.txt)); for tooling, testing, and CI — including ChainSafe's own `daml-autopilot` — see [`developer.md`](./developer.md). + +## Template structure + +```daml +template Order + with + buyer : Party + seller : Party + sku : Text + amount : Decimal + where + signatory buyer, seller + observer buyer, seller + + ensure amount > 0.0 + + choice Cancel : () + controller buyer + do return () + + nonconsuming choice GetStatus : Text + controller buyer + do return "Active" +``` + +- **Signatories** are mandatory authorities — both parties must sign for the contract to exist. +- **Observers** can see the contract but cannot exercise choices. +- **`ensure`** clauses validate invariants at creation/exercise. +- **`controller`** declares who can exercise a choice — their authorization is required. + +## Choice patterns + +```daml +choice Transfer : ContractId Order + with + newBuyer : Party + controller buyer, newBuyer + do create this with buyer = newBuyer +``` + +- **Multi-controller** choices require all named parties to authorize. +- **Consuming** by default — archives the contract and produces the return value. +- **`nonconsuming`** for read-only choices that leave the contract alive. + +## Records and types + +```daml +data OrderState = Draft | Active | Cancelled + deriving (Eq, Show) + +data Money = Money with + amount : Decimal + currency : Text + deriving (Eq, Show) +``` + +- Algebraic data types for state machines. +- Record syntax for structured values. +- `deriving (Eq, Show)` for common typeclasses. + +## Party patterns + +```daml +withParty : Party -> Update (ContractId Order) +withParty p = do + -- read what `p` can see + ... +``` + +- Pass parties as parameters; don't bake them into the contract identity unless necessary. +- For Canton multi-party workflows, separate "agent" parties from "principal" parties when delegation matters. + +## Keys + +```daml +template UniqueOrder + with + buyer : Party + seller : Party + orderId : Text + where + signatory buyer, seller + + key (buyer, orderId) : (Party, Text) + maintainer key._1 +``` + +- Use keys when the (signatory, key) tuple should be globally unique. +- `maintainer` names the party responsible for key maintenance — typically the primary signatory. + +## Scenario tests + +```daml +import Daml.Script + +setup : Script () +setup = do + alice <- allocateParty "Alice" + bob <- allocateParty "Bob" + + orderId <- submit alice $ createCmd Order with + buyer = alice + seller = bob + sku = "Widget" + amount = 10.0 + + submit alice $ exerciseCmd orderId Cancel + return () +``` + +- `Daml.Script` is the canonical test framework. +- `submit` runs as a specific party — authorization is checked. +- `submitMustFail` for negative tests. +- Guide: [Testing Daml Contracts](https://docs.canton.network/appdev/modules/m3-testing) (a tutorial, not an API reference). Run in CI via ChainSafe's [`canton-ci`](https://github.com/ChainSafe/canton-ci) `daml-test` / `daml-script` actions — see [`developer.md`](./developer.md#ci). + +## Time and dates + +```daml +choice Expire : () + controller buyer + do + now <- getTime + assertMsg "Order is not expired" (now > expirationTime) + return () +``` + +- `getTime` returns ledger-effective time, not wall clock. +- Document which time semantics you're using (submission, record, ledger-effective). + +## Upgrade-friendly design + +```daml +template Order + with + buyer : Party + seller : Party + sku : Text + amount : Decimal + where + signatory buyer, seller + + choice MigrateToV2 : ContractId OrderV2 + controller buyer, seller + do create OrderV2 with + buyer = buyer + seller = seller + sku = sku + amount = amount + newField = "" -- explicit default +``` + +- Design migration choices into templates from the start. +- Version package names; old contracts continue to exist on the ledger. +- Authoritative rules: [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility) · [Writing Your First Upgrade](https://docs.canton.network/appdev/modules/m6-writing-first-upgrade). + +## Canton workspace layout + +``` +my-canton-app/ +├── daml.yaml +├── daml/ +│ ├── Main.daml +│ ├── Orders.daml +│ └── Workflows.daml +├── test/ +│ └── Test.daml +└── README.md +``` + +- One template per file when templates grow non-trivially. +- Keep `Main.daml` as the entry point / re-export module. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`reviewer.md`](./reviewer.md) **(HARD FAIL tier)**, [`gotchas.md`](./gotchas.md). +- Upstream: [Canton Network Docs](https://docs.canton.network) — authoritative Daml language reference. diff --git a/languages/daml/reviewer.md b/languages/daml/reviewer.md new file mode 100644 index 0000000..5b338aa --- /dev/null +++ b/languages/daml/reviewer.md @@ -0,0 +1,108 @@ +# Daml Reviewer + +Language-specific review for Daml PRs. Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Daml is security-critical: this reviewer emits **HARD FAIL** findings for ledger invariants, authorization correctness, upgrade safety, and privacy violations. Override is explicit and logged in the PR with `Override: HARD FAIL for reason ` per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). + +> **In one line:** Authorization, atomicity, upgrade safety, privacy. HARD FAIL stops the PR until a CODEOWNER signs off on the override. + +Authoritative references for these checks live in the [Canton docs](https://docs.canton.network): [Authorization Model](https://docs.canton.network/appdev/modules/m3-authorization), [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility), [Security Best Practices](https://docs.canton.network/appdev/modules/m7-security). ChainSafe's own [`daml-autopilot`](https://daml-autopilot.chainsafe.io) (Daml Reason) can pre-extract the authorization model from the diff as a review aid — but it **informs, it does not approve**. The reviewer still decides; HARD FAIL findings are resolved or overridden by a human CODEOWNER, never by a tool. See [`developer.md`](./developer.md). + +## Severity tier + +**HARD FAIL.** Override path is explicit and audit-logged. The agent does not push through; the operator does, in writing. + +## HARD FAIL checks (reviewer refuses LGTM until resolved or explicitly overridden) + +### Authorization + +- **Signatory set on a template grants authority to any party** that shouldn't have it. Signatories are creation authorizers; mis-naming opens the contract to forged creation. +- **Controller of a consuming choice is not a signatory or observer** in a way that creates authorization-chain confusion. Verify the controller can actually authorize the choice. +- **`exerciseByKey` or `fetchByKey`** patterns that bypass authorization checks. The key-based variants still respect signatory authorization; misuse here is a security finding. +- **Missing `ensure` clauses** on templates where invariants should be enforced at creation time. +- **`canActAs`/`canReadAs`** delegation that broadens authority beyond what the design intended. + +### Atomicity + +- **Workflow split across choices where atomicity was required.** Intermediate state visible on the ledger; an attacker could exploit the partial commit. +- **Long-running choice with multiple side-effects** where partial commit semantics aren't documented. +- **Choices that depend on external oracle state** read at submission time without ledger-time bounds — submission-vs-record-time confusion. + +### Upgrade safety + +- **Template signature changes** (adding/removing/reordering fields, changing types) in a package version that doesn't carry the appropriate `@upgrade` annotations or migration choices. +- **Choices renamed or removed** without a deprecation path. Existing contracts and downstream code break silently. +- **Key structure changes.** Keys are part of the ledger identity; changing them migrates nothing automatically. +- **No migration choice** designed into a template that will need to be upgraded. Adding it later means manual operator workarounds. +- **Package version not bumped** when the template surface changed. + +### Privacy + +- **Observer set widened beyond design intent.** A new `observer` clause that adds parties without an explicit "why" is leaking visibility. +- **`delegate`/`disclose`** patterns that broaden the implicit visibility surface. +- **Sub-transaction visibility holes** — a private sub-choice that exposes data to a non-stakeholder when fetched. + +### Determinism + +- **Non-deterministic operations in a choice body** — anything that depends on submission timing, oracle state read mid-choice, or external I/O. Daml choices must be deterministic; non-determinism breaks the ledger. + +### Canton-specific (for Canton-deployed contracts) + +- **Cross-domain workflow without explicit synchronizer choice** when the contract participates in multiple domains. +- **Sequencer back-pressure assumptions** that don't survive the actual deployment topology. +- **Mediator response time assumptions** baked into the contract logic without justification. + +## SOFT WARNING checks (flag, don't block) + +- Style and naming. +- Performance optimizations that don't affect correctness. +- Test scenario coverage gaps in non-critical paths. +- Documentation thinness on templates. + +## Audit-readiness checklist + +A merged Daml PR for production work should be audit-ready: + +- [ ] Spec or design doc linked. +- [ ] Threat model named — what's the attacker capability, what's the asset, what's the trust boundary. +- [ ] Scenario / script tests covering happy path + failure modes + authorization edge cases. +- [ ] Privacy review: party-by-party check of what each party can see at each ledger state. +- [ ] Upgrade plan documented — how this version is migrated from the previous, how it's upgraded to the next. +- [ ] Coverage threshold met (project-specific). +- [ ] If Canton-deployed: deployment script and domain governance coordination. + +Authoritative references for the above: [Authorization Model](https://docs.canton.network/appdev/modules/m3-authorization), [Upgrade Compatibility](https://docs.canton.network/appdev/modules/m6-upgrade-compatibility), [Upgrade Limitations](https://docs.canton.network/appdev/modules/m6-limitations), [Testing Upgrades](https://docs.canton.network/appdev/modules/m6-testing-upgrades), [Security Best Practices](https://docs.canton.network/appdev/modules/m7-security). + +## When the reviewer skill refuses to review + +- Non-Daml code in the diff. +- PR description doesn't name the threat model. +- PR introduces template changes without an `@upgrade` strategy or migration choice. +- PR widens observer sets without an inline justification. +- PR changes signatory set without explicit security review. + +In each case, escalate to a Daml CODEOWNER and the curator. + +## Override mechanics + +Per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings): + +1. Reviewer skill emits finding with unique identifier. +2. Operator (CODEOWNER) reviews and decides to override. +3. PR description gets `Override: HARD FAIL for reason ` line. +4. Audit log entry (CHANGELOG or equivalent) records the override. +5. Override reviewed in post-merge cycle. + +The agent does not override on the operator's behalf. The operator types the override line themselves. + +## Phrasing + +- Lead with concern and severity: "**HARD FAIL — authorization.** This `choice Withdraw` has `controller alice` but `alice` is not a signatory or observer. The authorization chain is unclear; the choice can't be exercised by `alice` and probably shouldn't be." +- Cite the rule: "Per [Daml reviewer §authorization](#authorization)." +- Reference Canton context where applicable. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- Upstream: [Canton Network Docs](https://docs.canton.network) — authoritative authorization, upgrade, and security references. +- [`../../workflows/code-review.md`](../../workflows/code-review.md). +- [`../../operating-model/gates-and-escalation.md`](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) — HARD FAIL gate mechanics. +- [`../../invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). diff --git a/languages/go/architect.md b/languages/go/architect.md new file mode 100644 index 0000000..e67f3ae --- /dev/null +++ b/languages/go/architect.md @@ -0,0 +1,122 @@ +# Go Architect + +Architectural guidance for Go projects at ChainSafe. The framework for architectural invariants is `.invariants` (see the [pointer page](../../invariants/invariants-framework.md)). This page covers the Go-specific shape of decisions that sit under that framework. + +> **In one line:** Small public surfaces. Concrete types behind interfaces only where they earn it. Errors are values; panics are programming bugs. + +## Defer to `.invariants` for + +Architectural decisions in this language should be expressed in `.invariants` terms wherever they apply. Start with the upstream framework and only return here for Go-specific shaping. + +| If you are deciding… | Go to (`.invariants`) | +|---|---| +| What is the system boundary? | The framework's boundary-definition section | +| What invariants does this service hold? | Invariant naming + testability | +| How does this service interact with others? | Cross-component contracts | +| What's the failure model? | Failure-mode invariants | + +## Go-specific architectural choices + +### Project layout + +ChainSafe's Go projects (notably [Gossamer](https://github.com/ChainSafe/gossamer)) follow the conventional Go layout: + +- `cmd//main.go` — the entrypoint(s). One `main.go` per binary; minimal logic, just wiring. +- `internal/` — packages the project uses but does not export. Default home for all non-library code. +- `pkg/` — packages exported for use by other Go projects. **Limited and stable.** A package moves from `internal/` to `pkg/` only when it has proven stable, has deep test coverage, and the team commits to semver. +- `examples/` — runnable examples for the public API. +- For libraries: no `cmd/`, no `pkg/`. Public API at the top level (`api.go`), internals in `internal/`. + +### Public surface discipline + +Engineering invariant §4 (composability) lands in Go as: **start everything in `internal/`**. Only export when the cost of keeping it private is higher than the cost of locking in a public API. Public Go APIs are versioning contracts — under-think them and you live with the consequences. + +### Concurrency model + +Choose deliberately. Go's primitives (goroutines, channels, contexts, sync primitives) compose powerfully but also footgun-prone. Architectural commitments worth making at the design stage: + +- **Lifetimes via `context.Context`.** Every long-running operation accepts a `context.Context` as the first parameter. Cancellation propagates explicitly; goroutines without a context are goroutine leaks waiting to happen. +- **Channels for ownership transfer, mutexes for shared state.** Mixing the two patterns inside one component is a smell. +- **Bounded concurrency.** Unbounded `go func()` spawning is a memory and scheduler-pressure bug. Use worker pools, semaphores, or `errgroup` with limits. +- **No package-level mutable state.** It interacts badly with tests, with parallelism, and with init order. + +### Error model + +- **Errors are values.** Return them; check them; wrap them with `fmt.Errorf("...: %w", err)` for context. +- **Sentinel errors** for callers to match on via `errors.Is`. Document them. +- **Typed errors** for callers that need structured info via `errors.As`. Use sparingly. +- **No `panic` for non-fatal errors.** Panic is for programmer bugs that should crash the program (impossible state, invariant violation that means the binary is corrupt). See [Developer §panic](./developer.md#panic). + +### Dependency injection + +Functional options or explicit `Settings` structs for constructors. No global state, no hidden singletons. Tests build the system from the outside. + +### Stdlib first + +Go's standard library is unusually capable, and idiomatic Go leans on it heavily. ChainSafe's default for new Go code is **stdlib-first**: reach for an external dependency only when there's a compelling reason and the operator agrees. + +**The default loadout — no justification required:** + +- The Go standard library (everything at [pkg.go.dev/std](https://pkg.go.dev/std)). +- The `golang.org/x/*` extension packages (Go-team maintained — `x/sync`, `x/sys`, `x/net`, `x/crypto`, etc.). Treat these as stdlib-equivalent. +- Tools that ship with or are blessed by the Go distribution (`gofmt`, `go vet`, `go test`, `go mod`). + +**Project-approved external deps — established at the org level:** + +- `golang/mock` (or `go.uber.org/mock`) — testing mock generation. See [`references/gomock-patterns.md`](./references/gomock-patterns.md). +- `github.com/stretchr/testify` — test assertions, when not using stdlib's `testing` directly. +- `golangci-lint` and the linters it bundles — code quality. See [`references/golangci-config.md`](./references/golangci-config.md). + +These are documented org-level choices; they don't require per-project justification. + +**Everything else — needs a compelling case and operator approval:** + +A web framework instead of `net/http`. A logging library instead of `log/slog`. A router instead of `http.ServeMux`. A retry/circuit-breaker library instead of `context`-driven retries. An ORM instead of `database/sql`. In each case, the question is: *what does this give us that the standard library can't, and is that worth the supply-chain, version-skew, and learning-curve cost?* + +The architect's ADR must answer this explicitly: + +- What stdlib (or `x/*`) primitive was considered first? +- What's missing or insufficient about it? +- Why is the external dep worth its cost in dependency surface, audit burden, and ongoing maintenance? +- What's the exit path if the dep becomes unmaintained? + +Reaching for the popular framework reflexively is the anti-pattern. Most Go services don't need one. The standard library was designed by people who knew what they were doing; default to trusting them. + +### Effective Go alignment + +ChainSafe Go follows [Effective Go](https://go.dev/doc/effective_go) as the canonical idiom guide. The architect's job is to set up the codebase so following it is the path of least resistance: + +- **Interfaces small and consumer-side.** Define interfaces where they are *used*, not where they are *implemented*. Single-method interfaces are normal — that's why the standard library is full of `Reader`, `Writer`, `Closer`. Interface names follow the `-er` convention for single-method interfaces. +- **Accept interfaces, return concrete types.** A function takes a `Reader`, returns a `*Foo`. This keeps callers maximally flexible and implementations maximally clear. +- **No package-level naming gymnastics.** Package names are short, lowercase, single-word nouns. The package name *is* the namespace, so `store.Get` is fine; `store.GetStore` is repetitive. +- **Getters do not have a `Get` prefix.** `owner` field → `Owner()` method. Setters do have a `Set` prefix. +- **`MixedCaps`, not `snake_case` or `lowerCamelCase` for multi-word names.** Exported identifiers `MixedCaps`, unexported `mixedCaps`. + +These are detailed in [`developer.md`](./developer.md) and [`idioms.md`](./idioms.md); the architect's job is to not contradict them in the project's foundation. + +## ADR shape for Go services + +When opening an ADR for a Go service or significant Go module, the template should cover: + +- **Public surface.** What's exported. Why. +- **Concurrency commitments.** Goroutine ownership, context propagation, cancellation semantics. +- **Error contract.** What errors callers see. Which are sentinel, which are typed, which are wrapped. +- **Resource ownership.** Connections, files, goroutines — who closes them, when. +- **Dependency choices.** Any external (non-stdlib, non-`x/*`, non-project-approved) dependency the design assumes, with the compelling-case justification per the stdlib-first rule above. +- **Invariants impacted.** Deep links into `.invariants` for the architectural invariants this decision touches. + +## Anti-patterns + +- **Reaching for a framework reflexively.** `net/http` + `http.ServeMux` (Go 1.22+ adds method+path routing) covers most service needs. Pick a router or framework only when stdlib genuinely can't deliver. +- **Wide `pkg/` directory.** Most things belong in `internal/` and stay there. +- **Goroutines without a `context.Context`.** Leak hazards. +- **`sync.Map` reached for instead of a domain-specific structure.** It's correct but usually wrong for the problem. +- **Empty interfaces (`interface{}` / `any`) crossing module boundaries.** Pushes typing problems onto callers. +- **`init()` functions doing work.** Hard to test, hard to control order. + +## Related + +- [`developer.md`](./developer.md) — implementation-level Go practice. +- [`reviewer.md`](./reviewer.md) — what to look for in a Go PR. +- [`idioms.md`](./idioms.md) and [`gotchas.md`](./gotchas.md) — shared shorter references. +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md) — the architectural framework this page defers to. diff --git a/languages/go/developer.md b/languages/go/developer.md new file mode 100644 index 0000000..3cd48ac --- /dev/null +++ b/languages/go/developer.md @@ -0,0 +1,194 @@ +# Go Developer + +Idiomatic Go development at ChainSafe. Tooling, dependency management, testing, CI, panic discipline, and the patterns that come up in code review week after week. + +> **In one line:** Lint clean, type-check clean, test what changed, mock locally only. Pass by value unless you have a reason; pass `context.Context` always. + +## Tooling + +### Linting + +[`golangci-lint`](https://golangci-lint.run/) is the standard. Install at a pinned version: + +```sh +go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46 +``` + +A `.golangci.yml` at the repo root pins enabled linters. The [baseline config](./references/golangci-config.md) is a strong starting point; copy it and adjust per-project. Pin the version in CI — different linter versions catch different things. + +### Mocking + +[`golang/mock`](https://github.com/golang/mock) (gomock). Preferred over `vektra/mockery` for type-safety and Go-API stability. + +Conventions: + +- **Per-package mocks.** In each package needing mocks, two files: `mocks_generate_test.go` with the `//go:generate mockgen` directive, and `mocks_test.go` (generated). The `_test.go` suffix keeps mocks out of the package's exported surface. +- **Never export mocks.** They're a test-time artifact. +- **No `gomock.Any()`.** Use concrete arguments or custom matchers. +- **No `.AnyTimes()`.** State exact call counts (`.Times(n)`). +- **Always set `.Return(...)`** for functions that return. +- For subtests, build a fresh `gomock.NewController(t)` per subtest with the subtest's `t`. + +The [gomock patterns reference](./references/gomock-patterns.md) has a full worked example with subtests and functional mock builders. Mocks are committed; CI regenerates and `git diff --exit-code` catches drift. + +### Dependency management + +Go modules. `go.mod` and `go.sum` live in the repo. `go.sum` is never edited by hand. + +- Pin tool versions in CI scripts (e.g., the linter, mockgen). +- Use `go mod tidy` before committing dependency changes. +- For monorepos with multiple modules, declare each module's own `go.mod`. + +## Argument passing + +The argument-passing heuristics: + +- **Prefer passing by value.** Removes nil risk; makes function behavior independent of mutation; clearer. +- **Slices** pass by value if you only mutate elements. Pass `*[]T` only if you need to change the slice length. +- **Maps, channels, most interfaces** are pointers under the hood — always pass by value. +- **Arrays:** by value if ≤80 bytes, by pointer if larger or if performance matters. +- **Structs:** by value if performance allows and you don't need to mutate non-pointer fields; by pointer otherwise. +- **Mutexes:** always by pointer (copying a mutex is a bug). + +For **exported** functions outside `internal/`, fixed argument count + `Settings` struct for extensibility. For **unexported** functions and `internal/`, changing argument count is fine and is good — the compiler tells you when callers need updating. + +## Panic + +`panic` is for **programmer error**: states that should be impossible. Default switch cases on enums, sentinel-invariant violations, "this constructor only takes a positive integer and zero was passed." + +`panic` is **not** for external-input errors (file missing, network down, parse failure, bad user input). Those return `error`. + +`recover` is rarely used in production code. Test code uses it for asserting that a panic happened (`assert.PanicsWithValue` or equivalent). + +## Testing + +- **Unit tests** in `_test.go` files, same package. Use the in-package test convention by default. +- **Black-box tests** in `_test.go` with `package _test` — when you want to test only the exported surface. Useful for documentation examples. +- **Table-driven tests** for any function with >1 case. Subtests via `t.Run(name, ...)`. +- **Parallel tests** with `t.Parallel()` when they don't share mutable state. +- **`go test -race`** in CI for any code touching concurrency. Catches data races early. + +## CI + +Baseline (extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md)): + +- `go vet ./...` +- `gofmt -l .` — must produce no output. +- `golangci-lint run` with the project's `.golangci.yml`. +- `go test -race ./...` for race-sensitive packages; `go test ./...` everywhere else. +- `go build ./...` to confirm everything compiles. +- For projects with mocks: regenerate mocks and `git diff --exit-code`. + +Pin Go version per-project in `go.mod` and the CI workflow. + +## Dependency policy: stdlib first + +ChainSafe's default for new Go code is **stdlib-first**. Reach for the standard library and the `golang.org/x/*` extension packages before reaching for anything else. External dependencies require a compelling case, documented in an ADR, and operator approval. + +See [`architect.md` § Stdlib first](./architect.md#stdlib-first) for the full rationale and the list of project-approved deps that don't require per-use justification (`golang/mock` / `go.uber.org/mock`, `testify`, `golangci-lint`). + +Common stdlib reaches that catch developers reflexively reaching for external libraries: + +| Need | Use this from stdlib | Not these | +|---|---|---| +| HTTP server | `net/http` + `http.ServeMux` (Go 1.22+ has method+path patterns) | gin, echo, chi, gorilla/mux, fiber | +| Structured logging | `log/slog` (Go 1.21+) | logrus, zap, zerolog | +| JSON | `encoding/json` | jsoniter, easyjson (only if benchmarked) | +| Test assertions | `testing` (plus testify when established) | gocheck, ginkgo | +| Validation | hand-rolled `func Validate() error` methods | go-playground/validator (unless schema-driven) | +| Configuration | `flag` + `os.Getenv` (or simple unmarshalling) | viper | +| Database access | `database/sql` + `pgx` for Postgres | ORMs (gorm, ent) — usually overkill | +| HTTP client | `net/http` `Client` | resty, req | +| Templates | `text/template` / `html/template` | none needed | +| UUIDs | `crypto/rand` + hand-rolled, or `google/uuid` if v4 is fine | bigger deps | + +Every external dep added to `go.mod` is a supply-chain decision. Treat each one accordingly. + +## Effective Go alignment + +ChainSafe Go follows [Effective Go](https://go.dev/doc/effective_go) as the canonical idiom guide. The following are the items that come up most in review at ChainSafe — see [`idioms.md`](./idioms.md) for the broader idiom set. + +### Naming + +- **Package names: short, lowercase, single-word nouns.** `store`, `http`, `metrics`. Not `storage_utils`. The package name *is* part of the namespace, so `store.Get` is fine; `store.GetStore` repeats the namespace. +- **Avoid generic package names** (`util`, `common`, `helpers`, `misc`) — they grow into junk drawers. +- **Getters don't carry a `Get` prefix.** `Owner()` not `GetOwner()`. Setters do carry `Set`: `SetOwner()`. +- **Single-method interfaces end in `-er`.** `Reader`, `Writer`, `Closer`, `Formatter`. Multi-method interfaces get a descriptive noun: `FileStore`, `BlockProcessor`. +- **`MixedCaps`** for multi-word names. Exported `MixedCaps`, unexported `mixedCaps`. Never `snake_case` (and never `ALL_CAPS` for constants either — `MaxItems`, not `MAX_ITEMS`). +- **Acronyms stay in case.** `URL` not `Url`, `ID` not `Id`, `HTTP` not `Http`. Applies in both exported and unexported names: `parseURL`, `userID`. +- **Receivers: one or two letters** matching the type. `s *Store`, not `store *Store` (and never `self` / `this` / `me`). + +### Commentary (godoc) + +- **Every exported identifier has a doc comment** starting with the name itself: + ```go + // Fetch retrieves the bytes at url. The returned error wraps any + // underlying network or parse failure. + func Fetch(ctx context.Context, url string) ([]byte, error) { ... } + ``` +- **Package comment** at the top of one file per package, describing what the package does: + ```go + // Package store provides durable persistence for orders, indexed + // by buyer and seller party identifiers. + package store + ``` +- Comments are sentences — start with a capital letter, end with a period. The first word *is* the identifier name; godoc relies on this convention. +- Comment **why**, not **what**. The code says what. Exceptions: regex, hard-to-understand algorithms, anything where intent isn't obvious from the code. + +### Interfaces — consumer-side, small + +- **Define interfaces where they are used,** not where they are implemented. The consumer knows the shape it needs; the implementer's concrete type satisfies whatever shape happens to fit. +- **Small interfaces win.** 1–3 methods. The standard library is full of single-method interfaces because they compose well. +- **Accept interfaces, return concrete types.** Functions take a `Reader`; return a `*Foo`. This keeps callers maximally flexible and implementations clear at the type level. + +### Methods — receiver consistency + +- **Pointer receiver** when the method modifies state, when the type is "large" (>~80 bytes), or when the type has a mutex. +- **Value receiver** when the method doesn't mutate and the type is small (basic types, small structs). +- **Don't mix** pointer and value receivers on the same type without a reason — it confuses callers about whether the type's zero value is usable. + +### Control structures + +- **No `else` after `return`.** Handle the error/edge, return, continue with the happy path un-indented: + ```go + if err != nil { + return err + } + // happy path here + ``` +- **`for` is the only loop.** Range over arrays/slices/maps/channels. +- **`switch`** is more flexible than C's — cases break automatically; use `fallthrough` to override (rarely needed). Switch on values, types, or bare booleans (`switch {`). +- **`defer`** for cleanup, placed immediately after the resource is acquired. Arguments to `defer` are evaluated at *defer* time, not at call time. + +### Functions + +- **Multiple return values, especially `(value, error)`.** Don't try to encode errors as sentinel values; return them explicitly. +- **Named return values** for documentation and for `defer`-pattern manipulation of return values. Don't use them for "naked returns" in long functions — that's hard to read. + +## Patterns that come up in review + +- **`context.Context` as first parameter** for any operation that can be canceled or has a deadline. Never `context.TODO()` in committed code; either it's a real context (`context.Background()` at the top level, derived contexts below) or a `context.WithTimeout`/`WithDeadline`/`WithCancel`. +- **Errors wrapped with `%w`** to preserve the chain. Callers use `errors.Is` and `errors.As`. +- **Defer for cleanup** at the top of the function, immediately after the resource is acquired. +- **`if err != nil { return ..., fmt.Errorf("...: %w", err) }`** is the standard error-handling pattern. Don't elide the check. +- **No `else` after `return`.** Go style: handle the error, return, continue with the happy path at the original indent level. + +## Anti-patterns + +- **`panic` for non-fatal errors.** Use `error`. +- **Goroutines without context.** Leak hazards. +- **`init()` functions that connect to external services.** Hard to test, surprising at import time. +- **`interface{}` / `any` parameters.** Type-erase only when you must; document why. +- **Mocks reaching for `gomock.Any()`.** Be specific. +- **Package-level mutable state.** Use a constructor. + +## Related + +- [`architect.md`](./architect.md) — design-level decisions, including the stdlib-first ADR shape. +- [`reviewer.md`](./reviewer.md) — what to look for when reviewing a Go PR. +- [`idioms.md`](./idioms.md) and [`gotchas.md`](./gotchas.md). +- [`references/golangci-config.md`](./references/golangci-config.md) — the lint baseline (`.golangci.yml` + CI workflow). +- [`references/gomock-patterns.md`](./references/gomock-patterns.md) — detailed GoMock worked examples (subtests, custom matchers, mocks-check CI). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md) — the broader testing posture this page lives under. +- Upstream: [Effective Go](https://go.dev/doc/effective_go) — the canonical idiom guide this page aligns with. +- Upstream: [Go Standard Library](https://pkg.go.dev/std) — the default loadout for the stdlib-first policy. diff --git a/languages/go/gotchas.md b/languages/go/gotchas.md new file mode 100644 index 0000000..4e7a6c6 --- /dev/null +++ b/languages/go/gotchas.md @@ -0,0 +1,189 @@ +# Go Gotchas + +Common bug classes and surprising behavior in Go. Reviewer's screening list and author's pre-flight check. + +## Loop variable capture (pre Go 1.22) + +```go +// BUG (Go < 1.22): +for _, x := range items { + go func() { use(x) }() // all goroutines see the last x +} +``` + +Go 1.22+ scopes loop variables per-iteration, fixing this. For older code or unclear toolchain versions, bind explicitly: + +```go +for _, x := range items { + x := x // shadow + go func() { use(x) }() +} +``` + +Verify the project's `go.mod` Go version. Below 1.22, this is a real bug; above, it isn't. + +## Nil interface vs. nil concrete type + +```go +var e error +var pErr *MyError // nil +if condition { + pErr = computeError() +} +e = pErr // e is now NON-nil even if pErr is nil + +if e != nil { /* unexpectedly true */ } +``` + +An interface holding a typed nil is not nil. Return the bare `error` interface, not the concrete typed pointer. + +## `append` and shared backing arrays + +```go +a := []int{1, 2, 3, 4, 5} +b := a[1:3] // [2, 3], shares backing array +b = append(b, 99) // b becomes [2, 3, 99]; a becomes [1, 2, 3, 99, 5] +``` + +Slices share underlying memory with their parents until appending forces a reallocation. If you need an independent slice, allocate one explicitly (`make` + `copy`). + +## `defer` evaluation timing + +Arguments to `defer` are evaluated **at defer time**, not at call time: + +```go +i := 0 +defer fmt.Println(i) // prints 0 +i = 5 +return +``` + +Use a closure when you need the call-time value: + +```go +defer func() { fmt.Println(i) }() // prints 5 +``` + +## Map iteration order + +Go intentionally randomizes map iteration. Tests that depend on iteration order are flaky tests. + +```go +for k, v := range m { /* order is NOT stable */ } +``` + +If order matters, extract keys, sort them, iterate. + +## Goroutine leaks + +```go +// LEAK: goroutine has no exit +go func() { + for { + select { + case msg := <-ch: + process(msg) + } + } +}() +``` + +Always include a `case <-ctx.Done():` branch (or equivalent done channel). Goroutines without an exit path live forever. + +## Empty struct as a set / signal + +```go +set := map[string]struct{}{} +set["key"] = struct{}{} +``` + +This is idiomatic and saves memory vs. `map[string]bool`. Use it for sets and for done-signaling channels (`chan struct{}`). + +## Channel closed twice / send on closed + +```go +close(ch) +close(ch) // PANICS +ch <- 1 // PANICS if ch is closed +``` + +Closing is the **sender's** responsibility. Receivers detect closure via the second return value (`v, ok := <-ch`). Multiple senders → use a dedicated coordinator goroutine or a `sync.Once` around `close`. + +## `time.After` in a loop leaks + +```go +for { + select { + case <-time.After(time.Second): // allocates a new timer every iteration; not GC'd until fires + // ... + case <-ctx.Done(): + return + } +} +``` + +Use `time.NewTimer` + `Reset` (or `time.Ticker`) when looping. + +## `sync.WaitGroup` `Add` after `Go` + +```go +go func() { + wg.Add(1) // RACE: Wait may have already returned + defer wg.Done() + // ... +}() +``` + +`wg.Add(1)` must happen before the goroutine starts: + +```go +wg.Add(1) +go func() { + defer wg.Done() + // ... +}() +``` + +## `os.Args` and config in `init()` + +`init()` runs at import. Reading `os.Args`, env vars, or config in `init()` means tests can't override them and import order matters. Initialize lazily in a constructor. + +## JSON encoding of typed `nil` slices vs. empty slices + +```go +type Resp struct{ Items []Item `json:"items"` } + +a := Resp{} // marshals to {"items":null} +a.Items = []Item{} // marshals to {"items":[]} +``` + +If your API contract says "empty array, not null," initialize to `[]T{}`. + +## Pointer to range variable + +```go +var ptrs []*Item +for _, item := range items { // item is a value, reused each iteration + ptrs = append(ptrs, &item) // all point to the same memory in Go < 1.22 +} +``` + +Same as the goroutine loop-capture issue. Go 1.22+ fixes; earlier versions need explicit binding (`item := item`). + +## Mocks with `gomock.Any()` hide real bugs + +ChainSafe is firm on this: never use `gomock.Any()`. Tests pass with it; real bugs hide behind it. If you can't specify the argument, your test isn't ready to be written. + +## `%v` instead of `%w` in error wrapping + +```go +return fmt.Errorf("doing X: %v", err) // loses the chain +return fmt.Errorf("doing X: %w", err) // preserves the chain for errors.Is / errors.As +``` + +`%v` formats; `%w` wraps. Almost always you want `%w`. + +## Related + +- [`idioms.md`](./idioms.md) — the inverse: how to do these things right. +- [`reviewer.md`](./reviewer.md) — uses this list as a screening surface. diff --git a/languages/go/idioms.md b/languages/go/idioms.md new file mode 100644 index 0000000..d21449e --- /dev/null +++ b/languages/go/idioms.md @@ -0,0 +1,198 @@ +# Go Idioms + +Idiomatic patterns that come up often. Reference for both authors and reviewers; not exhaustive. + +## Naming + +- **Packages:** single word, all lowercase, descriptive (`store`, not `stores` or `storage_utils`). Match the directory name except for `package main`. +- **Variables:** short for short lifetimes (`i`, `err`, `ctx`), longer for broader scope. Avoid Hungarian notation; let types speak. +- **Acronyms:** keep the case consistent (`URL` not `Url`, `ID` not `Id`). +- **Receivers:** one or two characters matching the type (`s *Store`, not `store *Store`). + +## Error handling + +```go +data, err := fetch(ctx, url) +if err != nil { + return fmt.Errorf("fetching %s: %w", url, err) +} +``` + +- Error message starts lowercase, no trailing punctuation. +- Context goes before the error: `fetching %s: %w`, not `%w while fetching`. +- Wrap with `%w`; let callers `errors.Is` / `errors.As`. + +## Context + +```go +func DoThing(ctx context.Context, arg T) (Result, error) { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + // ... +} +``` + +- `ctx` is the first parameter, always. +- Derive new contexts with `WithTimeout`, `WithDeadline`, `WithCancel`, `WithValue` (sparingly). +- Always `defer cancel()` immediately after acquiring a cancellation function. +- Pass `ctx` down; never store it in a struct except in narrow framework-level cases. + +## Early return + +Handle errors and edge cases first; let the happy path stay un-indented. + +```go +if err != nil { + return err +} +if user == nil { + return ErrNoUser +} +// happy path here, at the original indent +``` + +No `else` after `return`. + +## Constructor pattern + +```go +type Store struct { /* ... */ } + +func NewStore(cfg Config) (*Store, error) { + // validate cfg, return error if invalid + return &Store{ /* ... */ }, nil +} +``` + +- Constructors named `New` (or `New` if it's the only one in the package). +- Configuration via a struct, not positional args, for extensibility. +- Functional options (`func(*Store)`) when configuration is genuinely optional and frequently mixed. + +## Interface placement + +Define interfaces where they are **consumed**, not where they are **implemented**. The consumer knows what shape it needs; the implementer's concrete type can satisfy whatever shape happens to be needed. + +```go +// in package that uses the dependency: +type fetcher interface { + Fetch(ctx context.Context, url string) ([]byte, error) +} + +func (s *Service) Process(ctx context.Context, f fetcher) error { /* ... */ } +``` + +Small interfaces (1-3 methods) are good. Bigger interfaces are usually a sign the boundary isn't right. + +## Defer for cleanup + +```go +file, err := os.Open(path) +if err != nil { + return err +} +defer file.Close() +``` + +Defer immediately after acquiring the resource. Don't bury defers deep in a function; the reader needs to see them at the top. + +## Returning multiple values + +`(T, error)` is the canonical pair. Named returns (`func DoThing() (result T, err error)`) are useful for documenting what the function returns and for `defer` patterns that modify return values, but don't overuse them — bare named returns in long functions are confusing. + +## Table-driven tests + +```go +func TestThing(t *testing.T) { + cases := map[string]struct { + in T + want U + err string + }{ + "happy": {in: T{...}, want: U{...}}, + "empty": {in: T{}, err: "empty input"}, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + got, err := Thing(c.in) + // assertions + }) + } +} +``` + +Map-keyed test cases give you free naming; subtests give you isolation. + +## Godoc commentary + +Every exported identifier has a doc comment that begins with the identifier's name: + +```go +// Store persists orders by buyer-seller pair. The zero value is not +// usable; construct with NewStore. +type Store struct { /* ... */ } + +// Get returns the order for the given id, or ErrNotFound if no such order +// exists. It is safe to call from multiple goroutines. +func (s *Store) Get(id OrderID) (Order, error) { /* ... */ } +``` + +Every package has a package comment on the `package` clause in one file: + +```go +// Package store provides durable persistence for orders indexed by +// buyer and seller party identifiers. +package store +``` + +godoc renders these into the standard documentation format and uses the first sentence as the summary. Write the first sentence to stand alone. + +## Interface placement (consumer-side) + +Define interfaces where they are **consumed**, not where they are **implemented**: + +```go +// in the package that uses the dependency: +type fetcher interface { + Fetch(ctx context.Context, url string) ([]byte, error) +} + +func (s *Service) Process(ctx context.Context, f fetcher) error { /* ... */ } +``` + +The consumer knows the shape it needs; the producer's concrete type satisfies whatever shape happens to be needed. This keeps the producer's API surface narrow and lets multiple consumers each declare their own minimum interface. + +Single-method interfaces are normal — the standard library is full of them (`io.Reader`, `io.Writer`, `fmt.Stringer`). Their names end in `-er`. Multi-method interfaces get descriptive nouns (`http.Handler`, `sort.Interface`). + +## Accept interfaces, return concrete types + +```go +// good: caller can pass any io.Reader +func ParseConfig(r io.Reader) (*Config, error) { /* ... */ } + +// bad: forces caller to wrap in an interface even if they have a *Config +func Apply(c interface{ Validate() error }) error { /* ... */ } +``` + +A function takes interfaces so callers have flexibility about what to pass. A function returns concrete types so callers can use the full API of what they get back. Reversing this rule produces APIs that are simultaneously rigid (about inputs) and underspecified (about outputs). + +## Receiver consistency + +Pick pointer or value receivers per type and stick with the choice: + +```go +// pointer receivers throughout — type carries state, is large, or has a mutex +type Store struct { mu sync.Mutex; items map[ID]Item } +func (s *Store) Get(id ID) Item { /* ... */ } +func (s *Store) Put(id ID, it Item) { /* ... */ } +``` + +Mixing pointer and value receivers on the same type without a reason confuses callers about whether the zero value is usable and whether copies preserve behavior. The rule of thumb: + +- **Pointer receivers** when the method modifies state, when the type is large (>~80 bytes), or when the type has a `sync.Mutex` or similar. +- **Value receivers** for small immutable-like types where copying is cheap. + +## Related + +- [`developer.md`](./developer.md) — fuller guidance with rationale. +- [`gotchas.md`](./gotchas.md) — the inverse: anti-idioms and common mistakes. +- Upstream: [Effective Go](https://go.dev/doc/effective_go) — canonical idiom guide; this page draws from it. diff --git a/languages/go/references/golangci-config.md b/languages/go/references/golangci-config.md new file mode 100644 index 0000000..c2ef756 --- /dev/null +++ b/languages/go/references/golangci-config.md @@ -0,0 +1,152 @@ +# golangci-lint configuration + +A baseline `.golangci.yml` for ChainSafe Go projects, with notes on what changes across golangci-lint versions. + +> Treat this as a starting point. Tighten or loosen per project; pin the golangci-lint version in CI so runs are deterministic. + +## The config + +```yaml +run: + skip-dirs: + - .github + build-tags: + - integration + +linters-settings: + misspell: + locale: UK + +issues: + exclude-rules: + # Do not run these linters for test files + - path: _test\.go + linters: + - dupl + - goerr113 + - containedctx + # Do not require comments for sentinel errors + - text: "exported: exported var Err*" + linters: + - revive + # Allow long lines for //go:generate comments + - linters: + - lll + source: "^//go:generate " + +linters: + # Default linters are enabled and not listed below: + # https://golangci-lint.run/usage/linters/#enabled-by-default + enable: + - asciicheck + - bidichk + - bodyclose + - containedctx + - cyclop + - decorder + - dogsled + - dupl + - durationcheck + - errchkjson + - errname + - exhaustive + - exportloopref + - forcetypeassert + - gci + - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - goerr113 + - goheader + - goimports + - gomnd + - gomoddirectives + - goprintffuncname + - gosec + - grouper + - ifshort + - importas + - ireturn + - lll + - maintidx + - makezero + - misspell + - nakedret + - nestif + - nilerr + - nilnil + - noctx + - nolintlint + - prealloc + - predeclared + - promlinter + - revive + - rowserrcheck + - sqlclosecheck + - tenv + - thelper + - tparallel + - unconvert + - unparam + - wastedassign + - whitespace +``` + +## Notes on linter naming drift since v1.46 + +Some linters above have been renamed, replaced, or removed in newer golangci-lint releases. When applying this config to a project on golangci-lint v1.55+ or v2.x: + +- **`exportloopref`** → replaced by the built-in loop-variable-capture check (Go 1.22+) and/or `copyloopvar`. +- **`ifshort`** → removed from golangci-lint. +- **`goerr113`** → renamed to `err113`. +- **`gomnd`** → renamed to `mnd`. +- **`exhaustivestruct`** (if you add it) → renamed to `exhaustruct`. +- **`structcheck`, `varcheck`, `deadcode`** (if present elsewhere) → consolidated into `unused`. + +Run `golangci-lint linters` against the version you've pinned to confirm what's available; the CI step will fail loudly if a name is wrong. + +## CI workflow + +Pin the linter version in your CI workflow so the build is deterministic: + +```yaml +name: Linting +on: + pull_request: + +jobs: + golangci-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - uses: golangci/golangci-lint-action@v6 + with: + version: v1.55 # pin a specific version; never `latest` +``` + +Pin to a specific version (not `latest`), since the same linters produce different findings across versions. Bump deliberately as a separate PR. + +## Per-package overrides + +For genuinely-justified deviations from the baseline, use `//nolint:` directives in the source, with an inline comment explaining why: + +```go +//nolint:gosec // file path is from a trusted internal config, not user input +data, err := os.ReadFile(cfg.Path) +``` + +A `//nolint` without a comment is a SOFT WARNING finding from the [Go reviewer skill](../reviewer.md). The agent flags; the operator decides whether the rationale is sufficient. + +## Related + +- [`../developer.md`](../developer.md) — broader Go development guidance, including this lint baseline as a CI gate. +- [`../reviewer.md`](../reviewer.md) — lint-related review checks. +- [`./gomock-patterns.md`](./gomock-patterns.md) — companion reference for GoMock at ChainSafe. +- [golangci-lint linters list](https://golangci-lint.run/usage/linters/) — upstream documentation. diff --git a/languages/go/references/gomock-patterns.md b/languages/go/references/gomock-patterns.md new file mode 100644 index 0000000..7161669 --- /dev/null +++ b/languages/go/references/gomock-patterns.md @@ -0,0 +1,316 @@ +# GoMock patterns + +Detailed worked examples for [`golang/mock`](https://github.com/golang/mock) at ChainSafe. The high-level conventions live in [`../developer.md`](../developer.md); this page is the deeper reference. + +## Why gomock (not mockery, not hand-written stubs) + +- **Type-safe.** Generated mocks satisfy the interface they mock; if the interface changes, the mock fails to compile. +- **Auto-completion friendly.** Generated methods are visible to the editor. +- **Stable Go API.** Less churn than `vektra/mockery`. +- **Established at ChainSafe.** Existing Go projects use it; consistency wins over re-tooling. + +Note: the original `golang/mock` repo is in maintenance mode; many projects have moved to the community fork [`go.uber.org/mock`](https://github.com/uber-go/mock) which is API-compatible. Pick one per project and stick with it. + +## File layout (per package needing mocks) + +Two files, both `_test.go` so the mocks never leak to the package's exported surface: + +``` +something/ +├── something.go # production code +├── mocks_generate_test.go # the //go:generate directive +└── mocks_test.go # the generated mock code (committed) +``` + +`mocks_generate_test.go`: + +```go +package something + +//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Fetcher,Parser +``` + +Multiple interfaces to mock from the same package go after the trailing dot, comma-separated. + +For mocks of interfaces in other packages (e.g., `io.Reader`), use a separate destination file: + +```go +package something + +//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Fetcher,Parser +//go:generate mockgen -destination=mocks_io_test.go -package $GOPACKAGE io Reader +``` + +## Generating + +```sh +go generate -run mockgen ./... +``` + +## Tooling + +Install `mockgen` once per developer: + +```sh +go install github.com/golang/mock/mockgen@v1.6.0 +# or, for go.uber.org/mock: +go install go.uber.org/mock/mockgen@latest +``` + +## CI: mocks-check workflow + +The CI workflow regenerates mocks and fails if the result differs from what's committed. This ensures (a) mocks with a `//go:generate` directive are present, (b) mocks are up-to-date with their interface, (c) deleted directives mean deleted mocks. + +```yaml +name: Mocks check +on: + pull_request: + branches: + - main + +jobs: + mocks-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - run: go mod download + - run: go install github.com/golang/mock/mockgen@v1.6.0 + - name: Remove committed mocks + run: grep -lr -E '^// Code generated by MockGen.+$' . | xargs -d '\n' rm + - name: Generate mocks + run: go generate -run mockgen -tags integration ./... + - name: Check for diffs + run: git diff --exit-code +``` + +## Worked example — simple test with a single goroutine path + +Production code: + +```go +// something/something.go +package something + +import ( + "context" + "fmt" +) + +type Fetcher interface { + Fetch(ctx context.Context) (data []byte, err error) +} + +type Parser interface { + Parse(data []byte) (id string, err error) +} + +func something(ctx context.Context, fetcher Fetcher, parser Parser) (id string, err error) { + data, err := fetcher.Fetch(ctx) + if err != nil { + return "", fmt.Errorf("cannot fetch: %w", err) + } + id, err = parser.Parse(data) + if err != nil { + return "", fmt.Errorf("cannot parse: %w", err) + } + return id, nil +} +``` + +Test: + +```go +// something/something_test.go +package something + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func Test_something(t *testing.T) { + ctrl := gomock.NewController(t) + + ctx := context.Background() + fetcher := NewMockFetcher(ctrl) + fetchCall := fetcher.EXPECT(). + Fetch(ctx). // define the expected argument(s) + Return([]byte{1, 2, 3}, nil) // define the returned values + + parser := NewMockParser(ctrl) + parser.EXPECT(). + Parse([]byte{1, 2, 3}). + Return("123", nil). + After(fetchCall) // assert call order + + id, err := something(ctx, fetcher, parser) + assert.NoError(t, err) + assert.Equal(t, "123", id) +} +``` + +**Hard rules (load-bearing):** + +- **No `gomock.Any()`** for arguments. Use concrete arguments or a custom matcher. +- **No `.AnyTimes()`** on mock calls. Specify the count: `.Times(3)`. +- **Always set `.Return(...)`** when the mocked function returns values. +- **Avoid mock helper functions.** A bit of repetition beats tight coupling. + +## Subtests with the functional mock builder pattern + +For table-driven tests with mocks, the gotcha is: each subtest needs its own `gomock.NewController(t)` built with the subtest's `t`, not the parent's. Otherwise a failure in one subtest fails all of them. + +The cleanest pattern is the **functional mock builder**: each test case carries its own mock-construction function, which the subtest invokes with its own controller: + +```go +package something + +import ( + "context" + "errors" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func Test_something(t *testing.T) { + errTest := errors.New("test error") + + testCases := map[string]struct { + ctx context.Context + fetcherBuilder func(ctrl *gomock.Controller) Fetcher + parserBuilder func(ctrl *gomock.Controller) Parser + id string + errWrapped error + errMessage string + }{ + "parser error": { + ctx: context.Background(), + fetcherBuilder: func(ctrl *gomock.Controller) Fetcher { + fetcher := NewMockFetcher(ctrl) + fetcher.EXPECT().Fetch(context.Background()). + Return([]byte{1, 2, 3}, nil) + return fetcher + }, + parserBuilder: func(ctrl *gomock.Controller) Parser { + parser := NewMockParser(ctrl) + parser.EXPECT().Parse([]byte{1, 2, 3}). + Return("", errTest) + return parser + }, + errWrapped: errTest, + errMessage: "cannot parse: test error", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + ctrl := gomock.NewController(t) // built with the subtest's t + + fetcher := testCase.fetcherBuilder(ctrl) + parser := testCase.parserBuilder(ctrl) + + id, err := something(testCase.ctx, fetcher, parser) + + assert.Equal(t, testCase.id, id) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) + } + }) + } +} +``` + +This pattern extends cleanly when mocks depend on each other — the builder signatures grow to take additional arguments. + +## Custom matchers for unpredictable arguments + +When an argument can't be made deterministic (a random port number, a generated UUID, a `context.WithTimeout` with a time-based deadline), a custom matcher gives you assertion without `gomock.Any()`. + +Regex matcher example: + +```go +// server/mock_regex_matcher_test.go +package server + +import ( + "regexp" + "github.com/golang/mock/gomock" +) + +var _ gomock.Matcher = (*regexMatcher)(nil) + +type regexMatcher struct { + regexp *regexp.Regexp +} + +func (r *regexMatcher) Matches(x interface{}) bool { + s, ok := x.(string) + if !ok { + return false + } + return r.regexp.MatchString(s) +} + +func (r *regexMatcher) String() string { + return "regular expression " + r.regexp.String() +} + +func newRegexMatcher(regex string) *regexMatcher { + return ®exMatcher{regexp: regexp.MustCompile(regex)} +} +``` + +Usage: + +```go +func Test_listenAndLog(t *testing.T) { + ctrl := gomock.NewController(t) + + logger := NewMockLogger(ctrl) + matcher := newRegexMatcher(`^listening on 127\.0\.0\.1:[0-9]{1,5}$`) + logger.EXPECT().Info(matcher) + + listenAndLog(logger) +} +``` + +For arguments where even a regex is too specific, `gomock.AssignableToTypeOf` falls back to type-shape assertion: + +```go +timedCtx, cancel := context.WithTimeout(context.Background(), time.Hour) +cancel() +timedCtxMatcher := gomock.AssignableToTypeOf(timedCtx) +fetcher.EXPECT().Fetch(timedCtxMatcher).Return([]byte{1}, nil) +``` + +This is a last resort. Most arguments are predictable; most apparent unpredictability is a sign the production code should accept the unpredictable thing as a parameter. + +## Advanced: ordering with `.After()` + +`.After(call)` asserts that a mock call happens after a named earlier call: + +```go +fetchCall := fetcher.EXPECT().Fetch(ctx).Return([]byte{1}, nil) +parser.EXPECT().Parse([]byte{1}).Return("ok", nil).After(fetchCall) +``` + +Worth using when: + +- Writing to a buffer where order matters. +- Coordinating async code that has a specific expected sequence. +- Otherwise: skip it; not every test needs explicit ordering. + +## Related + +- [`../developer.md`](../developer.md) — high-level Go testing conventions including the gomock baseline. +- [`../reviewer.md`](../reviewer.md) — review checks that flag `gomock.Any()`, `.AnyTimes()`, and other mock smells. +- [`./golangci-config.md`](./golangci-config.md) — companion reference for the lint baseline. diff --git a/languages/go/reviewer.md b/languages/go/reviewer.md new file mode 100644 index 0000000..7939da9 --- /dev/null +++ b/languages/go/reviewer.md @@ -0,0 +1,106 @@ +# Go Reviewer + +Language-specific checklist when reviewing a Go PR. Operates under the [universal review principles](../../workflows/code-review.md#universal-principles); this page adds the Go-specific surface. + +> **In one line:** Context propagation, goroutine ownership, error wrapping, mocks discipline. Findings emit as SOFT WARNING; operator decides on merge. + +## Severity tier + +Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Go reviewer findings emit as **SOFT WARNING**. The agent flags, the operator decides. HARD FAIL is reserved for security-critical languages (Solidity, Daml). + +## What to look for + +### Concurrency + +- **`context.Context` propagation.** Any function that does I/O, can block, or can be canceled must accept a `context.Context` as the first parameter. Verify it's used (not just accepted and ignored). +- **Goroutine ownership.** Every `go func()` must have a clear lifetime. Look for: a `context.Done()` exit path, a `defer wg.Done()` after `wg.Add(1)`, or a clearly-bounded scope. Bare `go func()` with no exit is a leak. +- **Unbounded concurrency.** A `for range items { go work(...) }` pattern with no limit is a memory and scheduler bug for large inputs. Look for worker pools, semaphores, or `errgroup.SetLimit`. +- **Data races.** Shared mutable state across goroutines without a mutex or channel is a race. `go test -race` should be on for the package. +- **Channel direction.** Channels passed to functions should declare their direction (`chan<- T` for send-only, `<-chan T` for receive-only). Bidirectional channels in function signatures are usually a missed opportunity. + +### Errors + +- **Wrapping.** `fmt.Errorf("...: %w", err)` to preserve the chain. Verify `%w`, not `%v`. +- **`errors.Is` / `errors.As`** at the call site for sentinel and typed errors respectively. Direct `==` comparison on errors is wrong post-1.13. +- **Sentinel discipline.** Sentinel errors (`var ErrFoo = errors.New("foo")`) should be exported only when callers need to match on them; document the contract. +- **No swallowed errors.** `_ = something()` deserves a comment. + +### Panic + +- **`panic` only on programmer error.** I/O errors, network errors, parse errors, user input — never. Flag any `panic` in production code paths and ask whether it should be an error return. +- **`recover` is suspicious in production code.** Test fixtures and the very top of a goroutine handler are the typical valid uses. Anywhere else, ask. + +### Layout + +- **`internal/` vs. `pkg/`.** New packages default to `internal/`. Moving to `pkg/` is a deliberate decision worth its own justification in the PR description. +- **Package names.** Single words, descriptive, match the directory. No `utils`, `helpers`, `common`, `misc`. +- **`main.go` minimalism.** The `main()` function wires; logic lives elsewhere. + +### Testing + +- **Race-sensitive code under `-race`.** If the package touches concurrency and CI isn't running `-race` on it, flag. +- **Mocks committed and regenerated.** `mocks_test.go` should match the current interface; CI should be checking with `git diff --exit-code` after regeneration. +- **No `gomock.Any()` or `.AnyTimes()`** without an explicit comment justifying the corner case (and almost always there's a better way; ask). +- **Subtests use their own `t.Run` controller.** Mocks built from the parent test's `t` leak between subtests. +- **Table tests** for >1 case; bare repeated assertions are a refactor candidate. + +### Arguments and types + +- **Pass by value unless** the type rule from [`developer.md` § Argument passing](./developer.md#argument-passing) says otherwise. Pointer receivers for "I will modify" or "this is large." Value receivers everywhere else. +- **`interface{}` / `any` parameters** are a flag. Ask what concrete type was intended; if generics fit better (Go 1.18+), suggest them. +- **No package-level mutable state.** Convert to constructor. + +### Linting and formatting + +- **`gofmt` clean.** Anything unformatted should never make it past CI; if it did, the CI baseline needs fixing. +- **`go vet` clean.** No `nolint` directives without a comment explaining why. +- **No `//nolint`** without a rationale. + +### Dependencies (stdlib-first) + +- **New entries in `go.mod` require justification.** Every external dep is a supply-chain decision. The PR description should say what stdlib (or `golang.org/x/*`) alternative was considered and why it was insufficient. +- **Project-approved deps are exempt** from per-PR justification: `golang/mock` (or `go.uber.org/mock`), `stretchr/testify`, `golangci-lint`-bundled linters. Anything else is a real decision. +- **Watch for the reflexive framework reach.** New HTTP server using `gin`/`echo`/`chi` when `net/http` + `http.ServeMux` would do (Go 1.22+ has method+path routing). New logger using `logrus`/`zap` when `log/slog` would do (Go 1.21+). Flag and ask. +- **ORM in a new service** → near-HARD scrutiny. ChainSafe Go services default to `database/sql` + `pgx`. An ORM (gorm, ent) needs a real case. + +See [`architect.md` § Stdlib first](./architect.md#stdlib-first) for the full policy. + +### Effective Go alignment (naming, commentary, structure) + +- **Package names** are short, lowercase, single-word nouns. No `util` / `common` / `helpers`. Flag any new package with a generic name. +- **Getters without a `Get` prefix.** `Owner()`, not `GetOwner()`. Setters have `Set`. +- **Single-method interfaces named with `-er` suffix.** `Reader`, `Closer`, `Formatter`. Flag if a single-method interface uses a noun name. +- **MixedCaps**, not snake_case. Acronyms preserve case (`URL`, `ID`, `HTTP`). +- **Receivers** are one or two letters matching the type. Never `self` / `this` / `me`. +- **Doc comments on every exported identifier**, starting with the identifier's own name. Missing godoc on exported items is a SOFT WARNING. +- **Package comment** at the top of one file per package describing what the package does. Missing → SOFT WARNING. +- **Interface defined consumer-side**, not in the implementing package. Flag interfaces defined alongside their implementations unless there's a reason. +- **Accept interfaces, return concrete types.** A function returning `interface{...}` when a `*Foo` would do is over-abstracting; flag. +- **Receiver consistency.** A type with both pointer and value receivers, mixed, is confusing. Ask why. + +See [Effective Go](https://go.dev/doc/effective_go) for the canonical reference. + +## What to flag vs. fix in place + +- **Flag** (review comment, not a fix): missing context propagation, goroutine leaks, error wrapping issues, panic-vs-error questions, mocking shortcuts, package-layout decisions, naming. +- **Suggest with code suggestion**: typos, lint-clean trivia, missing `defer cancel()` on a `context.WithTimeout`. +- **Don't fix and push** unless the operator has authorized co-authorship for this PR. + +## When the reviewer skill refuses to review + +- The diff contains code in a language other than Go (use the right reviewer skill). +- The PR description is empty (nothing to verify against). +- The diff touches packages out of the session's named scope. + +## Phrasing + +- Lead with the concern, not the fix: "This goroutine starts in `processBatch` and has no exit path other than `panic`. What's the intended lifetime?" +- Cite the rule when there is one: "Per [Go developer guide](./developer.md#panic), `panic` is for programmer error only — `processItem` accepts user input, so this should be a returned error." +- `nit:` for taste comments. "nit: `userMap` reads to me as plural; consider `usersByID`." + +## Related + +- [`architect.md`](./architect.md) and [`developer.md`](./developer.md) — what's being reviewed against. +- [`gotchas.md`](./gotchas.md) — the bug classes this checklist is screening for. +- [`../../workflows/code-review.md`](../../workflows/code-review.md) — the universal review framework. +- [`../../invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings) — HARD FAIL semantics (Go reviewer findings are SOFT WARNING, not HARD FAIL). diff --git a/languages/python/architect.md b/languages/python/architect.md new file mode 100644 index 0000000..96296e5 --- /dev/null +++ b/languages/python/architect.md @@ -0,0 +1,109 @@ +# Python Architect + +Architectural guidance for Python work at ChainSafe. Python's scope at ChainSafe is **internal-tooling-grade**: ops scripts, Ansible automation, data analysis, ML/research prototyping, internal CLIs. It is *not* the language of choice for production user-facing services or smart contracts. This shapes the architecture decisions below. + +> **In one line:** Python is for operator velocity, not production durability. Optimize for clarity and quick iteration; offload performance-critical work elsewhere. + +## Scope reminder + +Python at ChainSafe is appropriate for: + +- Ops scripts and tooling. +- Ansible automation (Ansible is Python under the hood; see [`../../workflows/infrastructure-and-devops.md`](../../workflows/infrastructure-and-devops.md)). +- Data analysis and reporting. +- ML/research prototypes. +- Internal CLIs. + +Python at ChainSafe is *not* appropriate for: + +- User-facing services where Lodestar/Forest/Gossamer/Sygma already cover the surface. +- Smart contract code. +- Production cryptographic primitives (use audited Rust/Go libraries). + +If your task fits the second list, the language choice itself is the architectural question — escalate to the curator before writing Python. + +This is [Effective Python](https://effectivepython.com/) Item 94 (*Know When and How to Replace Python with Another Programming Language*) as house policy: when a Python path turns performance-critical, profile it first (Item 92, *Profile Before Optimizing* — measure with `cProfile` / `timeit`, never guess), then push the hot part into a native extension or another language rather than micro-optimizing Python. Python stays the glue and the velocity layer. + +## Defer to `.invariants` for + +Python projects generally sit downstream of the main product architecture. The `.invariants` framework applies for cross-component invariants, but most Python work doesn't introduce new architectural invariants — it operates within existing ones. + +## Python-specific architectural choices + +### Project layout + +For non-trivial Python projects: + +- `src/` layout (`src//`, not just `/`) — keeps imports honest and prevents accidental local imports during testing. +- `tests/` parallel to `src/`. +- `pyproject.toml` as the canonical config (PEP 621). No `setup.py`, no `setup.cfg`. +- Dependency management with `uv` or `poetry`. Avoid bare `pip` + `requirements.txt` for non-trivial projects (no lockfile = no reproducibility). +- Lockfile committed (`uv.lock`, `poetry.lock`). + +For ops scripts: + +- Single-file scripts are fine for genuinely small things. +- Once a script grows past ~200 lines or gets imported by another script, promote it to a package. + +### Type discipline + +- **Type hints required** for any function exported from a module. `def foo(x: int) -> str:` is the floor. +- **`mypy --strict`** or `pyright` strict in CI. Type-check is a separate step from tests. +- **No `# type: ignore`** without a comment explaining why. +- **`typing.Protocol`** for structural typing — Python's interfaces. +- **`dataclasses` (or `attrs`)** for record types; not `dict`-passing across module boundaries. + +### Error model + +- **Raise specific exception classes**, never `raise Exception("...")`. +- **Custom exception hierarchies** for libraries with non-trivial error surfaces: + ```python + class MyToolError(Exception): pass + class ConfigError(MyToolError): pass + class NetworkError(MyToolError): pass + ``` +- **`try`/`except`/`else`/`finally`** when the post-try cleanup matters. +- **Never bare `except:`** — always specify the exception class. + +### Async + +- **`asyncio` is fine for I/O-bound concurrency** when the task warrants it. Don't reach for it reflexively. +- **`anyio`** for libraries that want runtime independence (works with asyncio and trio). +- **`concurrent.futures.ThreadPoolExecutor`** for I/O-bound concurrency without async syntax. +- **`multiprocessing`** for CPU-bound concurrency (the GIL still matters). +- **Pick one model and stick with it** within a project. + +### CLI design + +For operator-facing CLIs: + +- **`click`** or **`typer`** — argparse only for the simplest scripts. +- **Subcommand structure** for multi-action tools. +- **Exit codes**: 0 success, non-zero failure with distinct codes per failure class. +- **`--dry-run`** flag for any tool that mutates state. The operator-first contract applies even to internal tools. + +## ADR shape for Python work + +For Python work substantial enough to warrant an ADR: + +- **Why Python** — what makes this the right choice over Go/Rust/TS? +- **Public surface** — if a library, what's exported and what's `_private`. +- **Dependency choices** — significant deps named (e.g., `pydantic` vs `dataclasses`, `requests` vs `httpx`). +- **Performance commitments** — if any. Python is rarely the right answer when performance matters. +- **Deployment model** — is this a script, a CLI, a long-running service, a notebook? +- **Invariants impacted** — usually none new; reference upstream invariants if relevant. + +## Anti-patterns at design time + +- **Python for production hot paths.** Wrong tool; use Go/Rust. +- **Untyped Python at the module boundary.** Type hints are mandatory at the export surface. +- **Bare `pip install` without a lockfile.** No reproducibility. +- **`*args, **kwargs` propagated through layers** when concrete types would do. +- **`dict`-passing for structured data.** Use a dataclass. +- **Mixing async and sync in one codebase without clear boundaries.** + +## Related + +- [`developer.md`](./developer.md), [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/infrastructure-and-devops.md`](../../workflows/infrastructure-and-devops.md) — Ansible and ops tooling context. +- [Effective Python](https://effectivepython.com/) (Slatkin) — the canonical Python practice reference this section builds on; cataloged in [`sources.md`](../../references/sources.md). diff --git a/languages/python/developer.md b/languages/python/developer.md new file mode 100644 index 0000000..61cd71e --- /dev/null +++ b/languages/python/developer.md @@ -0,0 +1,223 @@ +# Python Developer + +Idiomatic Python at ChainSafe — for ops, scripting, internal tooling, and Ansible work. + +> **In one line:** Modern Python (3.11+). Type-hinted at module boundaries. `ruff` + `mypy --strict` in CI. `uv` for dependencies. + +## Tooling baselines + +- **Python version:** 3.11+ for new code. Pin in `pyproject.toml`. +- **Formatter + linter:** [`ruff`](https://docs.astral.sh/ruff/) — replaces `black`, `isort`, `flake8`, most of `pylint`. Fast. `ruff format` + `ruff check`. +- **Type checker:** `mypy --strict` or `pyright` strict mode. CI gate. +- **Dependency manager:** [`uv`](https://docs.astral.sh/uv/) for new projects; `poetry` where entrenched. Lockfile committed. +- **Test runner:** `pytest`. + +## `pyproject.toml` baseline + +```toml +[project] +name = "mytool" +version = "0.1.0" +requires-python = ">=3.11" +dependencies = [] + +[tool.ruff] +target-version = "py311" +line-length = 100 + +[tool.ruff.lint] +select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "DTZ", "RET", "SIM"] +ignore = [] + +[tool.mypy] +python_version = "3.11" +strict = true +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-ra --strict-markers" +``` + +## Project layout + +``` +mytool/ +├── pyproject.toml +├── uv.lock # or poetry.lock +├── README.md +├── src/ +│ └── mytool/ +│ ├── __init__.py +│ ├── cli.py +│ └── core.py +└── tests/ + └── test_core.py +``` + +`src/` layout is the modern default — prevents accidental local imports during testing. + +## Type discipline + +```python +from dataclasses import dataclass +from typing import Protocol + +@dataclass(frozen=True, slots=True) +class Order: + id: str + amount: int + currency: str + +class Fetcher(Protocol): + def fetch(self, url: str) -> bytes: ... + +def process(orders: list[Order], fetcher: Fetcher) -> dict[str, int]: + ... +``` + +- `@dataclass(frozen=True, slots=True)` for records — immutable, memory-efficient. +- `Protocol` for structural typing (interfaces). +- Built-in generic syntax (`list[Order]`, `dict[str, int]`) — Python 3.9+. +- No untyped `def` at module boundaries. + +## Error handling + +```python +class ConfigError(Exception): + """Raised when configuration is invalid or missing.""" + +class NetworkError(Exception): + """Raised on network failure after retries.""" + +def load_config(path: str) -> Config: + try: + raw = pathlib.Path(path).read_text() + except FileNotFoundError as e: + raise ConfigError(f"Config not found: {path}") from e + + try: + return Config.parse(raw) + except ParseError as e: + raise ConfigError(f"Config parse failed: {path}") from e +``` + +- Specific exception classes. +- `raise X from e` preserves the cause chain (Python's equivalent of error wrapping). +- **Raise exceptions rather than returning `None`** on failure (Effective Python Item 32) — a `None` return is ambiguous with a legitimately-empty result and pushes error-checking onto every caller. +- Never bare `except:`. + +## CLI with `click` + +```python +import click + +@click.group() +def cli() -> None: + """My internal tool.""" + +@cli.command() +@click.argument("name") +@click.option("--dry-run", is_flag=True, help="Show what would change.") +def deploy(name: str, dry_run: bool) -> None: + """Deploy NAME to staging.""" + if dry_run: + click.echo(f"[dry-run] would deploy {name}") + return + click.echo(f"deploying {name}") + +if __name__ == "__main__": + cli() +``` + +- `click` or `typer` for non-trivial CLIs. +- `--dry-run` for any tool that mutates state. +- Subcommands via `@cli.group()` + `@cli.command()`. + +## Async + +```python +import asyncio +import httpx + +async def fetch_all(urls: list[str]) -> list[bytes]: + async with httpx.AsyncClient() as client: + return await asyncio.gather(*[client.get(u) for u in urls]) +``` + +- `asyncio` for I/O-bound concurrency when the task warrants it. +- `httpx` over `requests` for the async variant. +- Don't mix sync and async in the same module without clear reason. + +## Logging + +```python +import logging +logger = logging.getLogger(__name__) + +def do_thing() -> None: + logger.info("doing thing", extra={"context": "value"}) +``` + +- `logging.getLogger(__name__)` per module — gives you the natural namespace tree. +- Configure at the entry point (`cli.py`, `main.py`), not in library code. +- Structured logging via the `extra` dict; don't bake context into the message string. + +## Testing + +```python +import pytest + +@pytest.fixture +def sample_config() -> Config: + return Config(name="test", timeout=30) + +def test_load_valid(sample_config: Config, tmp_path: pathlib.Path) -> None: + path = tmp_path / "config.toml" + path.write_text(sample_config.to_toml()) + loaded = load_config(str(path)) + assert loaded == sample_config + +def test_load_missing_raises(tmp_path: pathlib.Path) -> None: + with pytest.raises(ConfigError, match="not found"): + load_config(str(tmp_path / "nonexistent.toml")) +``` + +- `pytest` fixtures for setup; built-in `tmp_path` for filesystem tests. +- `pytest.raises` with a `match` argument for negative tests. +- `parametrize` for table-driven tests. + +## CI baseline + +- `ruff format --check .` +- `ruff check .` +- `mypy --strict src/` +- `pytest` +- `uv lock --check` (verify lockfile is up to date) + +## Patterns + +- **Dataclasses for records.** Not dicts. +- **`pathlib.Path` for paths.** Not string concatenation. +- **f-strings for formatting.** Not `%` or `.format()`. +- **Context managers (`with`)** for resource handling. +- **List/dict comprehensions** for transformations; loops for side effects. +- **`functools.lru_cache`** for memoization where appropriate. +- **Keyword-only arguments** (`def f(*, timeout: int)`) for options at wide call sites — callers can't transpose positional args, and adding a parameter later doesn't shift the others (Effective Python Item 37). +- **Docstrings on every public function, class, and module** (Effective Python Item 118) — they document the contract (what it does, raises, returns) and surface through `help()` / `pydoc`. + +## Anti-patterns + +- Bare `except:`. +- Mutable default arguments (`def f(x=[])`). +- Star imports (`from foo import *`). +- `global` keyword. +- Untyped functions at the module boundary. +- Comparing types with `type(x) == Foo` instead of `isinstance(x, Foo)`. +- `requirements.txt` without a lockfile for non-trivial projects. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). diff --git a/languages/python/gotchas.md b/languages/python/gotchas.md new file mode 100644 index 0000000..17c6278 --- /dev/null +++ b/languages/python/gotchas.md @@ -0,0 +1,259 @@ +# Python Gotchas + +Common bug classes and surprising behavior in Python. + +## Mutable default arguments + +```python +def append_to(item, target=[]): # BUG: shared across calls + target.append(item) + return target + +append_to(1) # [1] +append_to(2) # [1, 2] — same list! +``` + +Default arguments are evaluated once, at function-definition time. Use `None` as the sentinel: + +```python +def append_to(item, target=None): + if target is None: + target = [] + target.append(item) + return target +``` + +## Late binding in closures + +```python +funcs = [lambda: i for i in range(3)] +[f() for f in funcs] # [2, 2, 2], not [0, 1, 2] +``` + +Closures capture variables by name, not by value. Bind explicitly: + +```python +funcs = [(lambda i=i: i) for i in range(3)] # [0, 1, 2] +``` + +## Bare `except` + +```python +try: + do_thing() +except: + pass # also catches KeyboardInterrupt, SystemExit +``` + +Catches everything including signals and exits. Use `except Exception:` at minimum; usually specific exception classes. + +## `is` vs `==` + +```python +if x is "": # may be True for cached strings, False otherwise — implementation-defined +if x == "": # correct +``` + +`is` checks identity; `==` checks equality. Use `is` only for `None`, `True`, `False`. + +## Floating-point comparison + +```python +0.1 + 0.2 == 0.3 # False +``` + +Use `math.isclose` or work in integer units (cents instead of dollars). + +## `dict.keys()` while mutating + +```python +for k in d: # RuntimeError if you modify d during iteration + if cond(k): + del d[k] +``` + +Iterate over a copy: `for k in list(d):`. Or build a new dict. + +## `range` is not a list + +```python +r = range(10) +len(r) # 10 +r[5] # 5 +sum(r) # 45 +r.append(11) # AttributeError — range is not a list +``` + +Convert with `list(r)` if you need mutation. + +## `requests.get` without timeout + +```python +requests.get("https://slow.example.com") # may hang forever +``` + +Always pass `timeout=`. Same for `httpx`. Same for `urllib.request`. + +## `subprocess.run` without `check=True` + +```python +subprocess.run(["maybe-fail"]) # returns silently on non-zero exit +subprocess.run(["maybe-fail"], check=True) # raises CalledProcessError +``` + +Default behavior is to ignore non-zero exits. Almost always wrong. + +## `shell=True` injection + +```python +subprocess.run(f"rm -rf {user_input}", shell=True) # command injection +``` + +Use the list form: `subprocess.run(["rm", "-rf", user_input])`. No shell, no injection. + +## `json.loads` with floats and money + +```python +json.loads('{"amount": 0.1}')["amount"] + json.loads('{"amount": 0.2}')["amount"] +# 0.30000000000000004 +``` + +Don't store money as floats. Use `Decimal` or integer smallest-units. + +## `pickle` is not safe + +```python +import pickle +data = pickle.loads(untrusted_bytes) # arbitrary code execution +``` + +`pickle` is not a deserialization format for untrusted data. Use JSON, MessagePack, or a schema-validated format. + +## `eval` / `exec` on user input + +Almost always wrong. If you think you need it, you don't. + +## `os.path` vs `pathlib` + +```python +os.path.join("foo", "bar") # works, but stringly typed +Path("foo") / "bar" # better +``` + +`pathlib` is the modern way. `os.path` still has the API; `pathlib.Path` is typed. + +## `time.time()` for measuring durations + +```python +start = time.time() +do_thing() +duration = time.time() - start # affected by system clock changes +``` + +Use `time.perf_counter()` or `time.monotonic()` for durations. + +## Mixing `print` and logging + +`print` writes to stdout; logging defaults to stderr. CLI output mixed with log lines is confusing. Use logging consistently for diagnostic output; `print` (or `click.echo`) for user-facing output. + +## Global state in modules + +```python +# config.py +CONFIG = None + +def load(path): + global CONFIG + CONFIG = read(path) +``` + +Mutating global state at import time or via side-effects makes testing painful. Use a config object passed explicitly. + +## Circular imports + +```python +# a.py imports b +# b.py imports a +``` + +Python handles some circular imports OK; others break with `ImportError` or partially-initialized modules. Refactor to break the cycle (extract shared types into a third module). + +## `__init__.py` side effects + +Heavy work in `__init__.py` runs at import. Slow startup, surprising state. Keep `__init__.py` minimal — just re-exports. + +## `# type: ignore` everywhere + +Each `# type: ignore` is technical debt. Make them specific (`# type: ignore[arg-type]`) and comment why. + +## `from foo import *` + +Pollutes the namespace, hides what was imported, breaks linters that check for unused imports. Don't. + +## Floats in `dict` keys + +```python +d = {0.1: "a"} +d[0.1 + 0.0] # KeyError sometimes, depending on float representation +``` + +Floats as dict keys are fragile. Use Decimal or an integer representation. + +## `assert` removed by `-O` + +```python +def transfer(amount): + assert amount > 0 + do_transfer(amount) +``` + +`python -O` strips assertions. Don't use `assert` for validation that must happen at runtime — raise explicitly. + +## Mutable class attributes shared across instances + +```python +class Box: + contents = [] # CLASS attribute, shared + +a = Box() +b = Box() +a.contents.append(1) +b.contents # [1] — shared! +``` + +Initialize mutable attributes in `__init__`: + +```python +class Box: + def __init__(self): + self.contents = [] +``` + +## `dict` insertion order + +Since Python 3.7, dicts preserve insertion order. But don't rely on that for sets — `set` does not preserve order. + +## `bytes` vs `str` + +```python +data = path.read_bytes() # bytes +text = data.decode("utf-8") # str — decode at the boundary +``` + +`bytes` and `str` don't mix: `b"x" + "y"` is a `TypeError`, and a `bytes` never equals a `str`. Decode to `str` at the input boundary, encode at the output boundary, and keep the middle one type (Effective Python Item 10). + +## Iterator exhaustion + +```python +def summarize(rows): + total = sum(r.amount for r in rows) + count = sum(1 for r in rows) # 0 if `rows` was a generator — already drained + return total, count +``` + +A generator can be walked once. A function that iterates its argument twice silently misbehaves when handed an iterator instead of a list. Materialize with `list(rows)` up front, or accept only a concrete sequence (Effective Python Item 21). + +## Related + +- [`idioms.md`](./idioms.md), [`reviewer.md`](./reviewer.md). +- [Effective Python](https://effectivepython.com/) (Slatkin) — the upstream practice reference. diff --git a/languages/python/idioms.md b/languages/python/idioms.md new file mode 100644 index 0000000..9c8c646 --- /dev/null +++ b/languages/python/idioms.md @@ -0,0 +1,227 @@ +# Python Idioms + +Idiomatic Python (3.11+) for ChainSafe internal tooling. + +## Modern type hints + +```python +def process(orders: list[Order], limit: int | None = None) -> dict[str, int]: + ... +``` + +- Built-in generics (`list`, `dict`, `tuple`) since 3.9. +- `T | None` since 3.10 (replaces `Optional[T]`). +- No need to `from typing import List, Dict, Optional`. + +## Dataclasses for records + +```python +from dataclasses import dataclass + +@dataclass(frozen=True, slots=True) +class Money: + amount: int # store as integer cents/smallest unit + currency: str +``` + +- `frozen=True` for immutability — hashable, safer. +- `slots=True` for memory + speed. +- For unstructured-but-typed bags, `TypedDict` is the alternative. + +## Protocols (structural typing) + +```python +from typing import Protocol + +class Fetcher(Protocol): + def fetch(self, url: str) -> bytes: ... + +def process(f: Fetcher) -> None: + f.fetch("https://example.com") +``` + +Caller's class doesn't need to inherit from `Fetcher` — duck-typed at the type level. + +## Pattern matching (3.10+) + +```python +match event: + case Order(id=id_, amount=amount) if amount > 0: + process_order(id_, amount) + case Refund(id=id_): + process_refund(id_) + case _: + raise ValueError(f"Unknown event: {event}") +``` + +Exhaustiveness checking when paired with strict mypy. + +## `pathlib` over string paths + +```python +from pathlib import Path + +config = Path("~/.config/mytool/config.toml").expanduser() +if config.exists(): + raw = config.read_text() +``` + +Don't manipulate paths as strings. + +## f-strings + +```python +url = f"https://api.example.com/orders/{order_id}" +log.info(f"Processing {len(orders)} orders for {customer.name}") +``` + +- f-strings for formatting. +- `f"{value=}"` syntax for debug output (Python 3.8+): `f"{x=}"` → `x=42`. + +## Context managers + +```python +from contextlib import contextmanager + +@contextmanager +def open_db_connection(): + conn = connect() + try: + yield conn + finally: + conn.close() + +with open_db_connection() as conn: + conn.execute(...) +``` + +- `with` for resource handling. +- `@contextmanager` for custom resources. +- `contextlib.suppress` for the "ignore this specific exception" case. + +## Enum + +```python +from enum import StrEnum + +class OrderState(StrEnum): + PENDING = "pending" + ACTIVE = "active" + CANCELLED = "cancelled" +``` + +`StrEnum` (3.11+) — enum members are also strings, JSON-serializable, comparable to strings. + +## List/dict comprehensions + +```python +totals = {customer: sum(o.amount for o in orders if o.customer == customer) + for customer in customers} + +active = [o for o in orders if o.state == OrderState.ACTIVE] +``` + +For transformations. For side effects, use a loop — comprehensions with side effects are unidiomatic. + +## Iterators and generators + +```python +def chunks(items: list[T], size: int) -> Iterator[list[T]]: + for i in range(0, len(items), size): + yield items[i:i + size] +``` + +Generators for streaming; iterators for protocol compatibility. + +## `functools` toolkit + +```python +from functools import cache, lru_cache, reduce, partial + +@cache +def expensive(x: int) -> int: + ... + +multiply_by_two = partial(multiply, 2) +``` + +- `@cache` (3.9+) — unbounded memoization. +- `@lru_cache(maxsize=N)` for bounded. +- `partial` for argument binding. + +## Keyword-only arguments + +```python +def connect(host: str, *, timeout: float = 30.0, retries: int = 3) -> Conn: + ... + +connect("db.internal", timeout=5) # options must be named +``` + +Everything after `*` must be passed by name. Callers can't transpose `timeout` and `retries`, and you can add an option later without breaking positional calls (Effective Python Item 37). + +## Missing dict keys + +```python +counts.get(key, 0) # one-off default, no KeyError + +from collections import defaultdict +groups = defaultdict(list) +groups[key].append(value) # auto-creates the list +``` + +`get` for a one-off default; `defaultdict` for accumulating into internal state (Effective Python Items 26–27). + +## Return a result object, not a big tuple + +```python +@dataclass(frozen=True) +class ParseResult: + value: int + consumed: int + warnings: list[str] +``` + +Once a function would return more than ~three values, a `@dataclass` beats a tuple — callers read fields by name instead of unpacking by position (Effective Python Item 31). + +## Logging + +```python +import logging +log = logging.getLogger(__name__) + +log.info("processing order", extra={"order_id": order.id, "amount": order.amount}) +``` + +- `logging.getLogger(__name__)` per module. +- Structured logging via `extra` dict. +- Configure at the entrypoint, not in library code. + +## Testing with pytest + +```python +import pytest + +@pytest.fixture +def sample_config(tmp_path: Path) -> Config: + p = tmp_path / "config.toml" + p.write_text("name = 'test'") + return load_config(p) + +@pytest.mark.parametrize("input,expected", [ + ("a", "A"), + ("ab", "AB"), + ("", ""), +]) +def test_upper(input: str, expected: str) -> None: + assert input.upper() == expected +``` + +- Fixtures for setup. +- `tmp_path` built-in for filesystem tests. +- `parametrize` for table-driven tests. + +## Related + +- [`developer.md`](./developer.md), [`gotchas.md`](./gotchas.md). +- [Effective Python](https://effectivepython.com/) (Slatkin) — the upstream practice reference. diff --git a/languages/python/reviewer.md b/languages/python/reviewer.md new file mode 100644 index 0000000..86205b7 --- /dev/null +++ b/languages/python/reviewer.md @@ -0,0 +1,100 @@ +# Python Reviewer + +Language-specific review for Python PRs at ChainSafe. Python's scope is internal-tooling-grade; review is **SOFT WARNING** tier (agent flags, operator decides). + +> **In one line:** Type hints at boundaries, no bare excepts, no mutable defaults, lockfile up-to-date, no `# type: ignore` without reason. + +## Severity tier + +**SOFT WARNING.** Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Python is not in the security-critical-language list. If Python ever ends up in a security-critical path at ChainSafe, the language choice itself is the issue — escalate to the curator. + +## Checklist + +### Type discipline + +- **Type hints at module boundaries.** Public functions need full annotations. +- **`# type: ignore`** requires a comment. +- **`Any` reaches into typed code** — flag and ask whether a `Protocol` or `Union` would work. +- **No untyped `**kwargs`** propagated through layers when concrete types would do. +- **`isinstance(x, Foo)`** for type checks, not `type(x) == Foo`. +- **Keyword-only arguments** (`*`) at wide call sites so options can't be transposed (Effective Python Item 37). +- **Public functions, classes, and modules have docstrings** (Effective Python Item 118). + +### Errors + +- **No bare `except:`** — always specify exception class. +- **No `except Exception:`** without a reason — usually too broad. +- **`raise X from e`** to preserve the cause chain when wrapping. +- **No string-message `raise Exception(...)`** for non-trivial errors — use a typed exception class. +- **Failures raise; they don't return `None`** (Effective Python Item 32) — a `None` return is ambiguous with an empty result. +- **No silently-swallowed errors.** `pass` in an `except` block deserves a comment. + +### Resource handling + +- **`with` (context manager)** for files, network connections, locks. Not raw `open`/`close`. +- **`pathlib.Path`** for paths, not string concatenation. +- **No global mutable state** without `threading.Lock` or equivalent. + +### Async (when present) + +- **No mixing sync and async** in the same module without clear boundary. +- **No `time.sleep()`** in async code (use `asyncio.sleep`). +- **No blocking I/O calls** in async functions (use the async variant or `run_in_executor`). +- **`asyncio.gather` over an unbounded input** — use a semaphore. + +### CLI tools + +- **`--dry-run` flag** for any tool that mutates state. The operator-first contract applies. +- **Exit codes:** 0 success, distinct non-zero codes per failure class. +- **`click` or `typer`** for non-trivial CLIs; not raw argparse. +- **Output goes to stderr or stdout deliberately** — log to stderr, data to stdout. + +### Dependencies + +- **Lockfile committed and up-to-date.** `uv.lock` or `poetry.lock`. +- **No `pip install` in committed scripts.** Tools should declare deps in `pyproject.toml`. +- **Audit-style dep additions:** each new package is a supply-chain choice. + +### Tests + +- **`pytest` with fixtures** for setup, not module-level globals. +- **`pytest.raises(X, match=...)`** for negative tests. +- **Parametrize over copy-paste** for similar test cases. +- **No tests with implicit network access** — mock or fixture. + +### Lint and format + +- **`ruff check`** clean. +- **`ruff format --check`** clean. +- **`mypy --strict`** clean. +- **No `# noqa`** without a comment. + +### Project structure + +- **`src/` layout** for non-trivial projects. +- **`pyproject.toml`** as canonical config; no `setup.py` / `setup.cfg`. + +## What to flag vs fix in place + +- **Flag:** type-hint gaps, error-handling choices, async design, dep additions, lint suppressions. +- **Suggest with code suggestion:** trivial ruff fixes, type-hint additions on private functions, doc string formatting. +- **Don't fix and push** unless authorized. + +## When the reviewer skill refuses to review + +- Non-Python code in diff. +- Empty PR description. +- Out-of-session-scope code. +- **Python code in a production-product hot path** — refuse and escalate. The language choice is the architectural finding. + +## Phrasing + +- Lead with concern: "This function returns `dict[str, Any]` and several callers `kwargs` it forward. A `dataclass` or `TypedDict` at the boundary would catch the bugs lurking in those `Any`s." +- Cite the rule when relevant. +- `nit:` for taste-level. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/code-review.md`](../../workflows/code-review.md). +- [Effective Python](https://effectivepython.com/) (Slatkin) — canonical practice reference (see [`sources.md`](../../references/sources.md)). diff --git a/languages/rust/architect.md b/languages/rust/architect.md new file mode 100644 index 0000000..cf26477 --- /dev/null +++ b/languages/rust/architect.md @@ -0,0 +1,105 @@ +# Rust Architect + +Architectural guidance for Rust projects at ChainSafe — notably [Forest](https://github.com/ChainSafe/forest) (Filecoin), [Mina-rs](https://github.com/ChainSafe/mina-rs), [ChainBridge Substrate](https://github.com/ChainSafe/chainbridge-substrate), and others. The architectural framework lives in `.invariants` (see the [pointer page](../../invariants/invariants-framework.md)); this page covers Rust-specific shaping. + +> **In one line:** Errors are typed. Ownership is explicit. Async runtime is a library choice, not a default. Use the type system instead of comments. + +## Defer to `.invariants` for + +| Decision | `.invariants` section | +|---|---| +| Service boundaries and contracts | Component contracts | +| Invariant naming and testability | Invariant lifecycle | +| Cross-component failure modes | Failure-mode invariants | +| Memory and ownership invariants | Ownership/lifetime invariants | + +## Rust-specific architectural choices + +### Project layout + +ChainSafe Rust projects use Cargo workspaces for multi-crate projects (Forest is the canonical example): + +- `Cargo.toml` at the root declares workspace members. +- Crates split by concern: one for the network layer, one for storage, one for the binary, one per protocol module. +- A `bin/` crate for the executable, a `lib/` crate for the consumable API, others for internals. +- Workspace-level dependency hoisting where possible to keep versions consistent. + +### Error model + +- **`thiserror` for libraries, `anyhow` for binaries.** Library crates expose typed errors (`#[derive(thiserror::Error)]`) so callers can match; binaries that just need to propagate use `anyhow::Result`. +- **No `unwrap()` / `expect()` in production paths.** Either handle the error or document the invariant that makes it impossible. Tests are an exception. +- **`?` for propagation.** Don't write match arms for the trivial pass-through case. +- **Error context.** Use `anyhow::Context` or a typed `.with_context(...)` extension to add context as errors bubble. + +### Async runtime + +- **Pick one.** Tokio for most ChainSafe projects (including Forest). Don't mix tokio and async-std in the same workspace. +- **`#[tokio::main]` only in the binary crate.** Library crates stay runtime-agnostic where possible — they take a runtime handle or are runtime-generic via traits. +- **Bounded concurrency.** `FuturesUnordered` with limits, `tokio::sync::Semaphore`, or `buffer_unordered` on streams. Unbounded futures spawning is a leak. +- **`Send + Sync` and `'static` bounds** — design types so they meet the bounds Tokio's `spawn` requires. + +### Concurrency primitives + +- **`Arc>`** for shared mutable state across tasks. `Arc` for shared ownership, `Mutex` for synchronization. +- **`tokio::sync::Mutex` vs `std::sync::Mutex`.** Tokio mutex when locks span `await` points; std mutex when they don't. +- **Channels:** `tokio::sync::mpsc` for many-to-one, `broadcast` for one-to-many, `oneshot` for single-response. +- **No `std::thread::spawn` in async code.** Use `tokio::task::spawn` or `tokio::task::spawn_blocking` for genuinely-CPU-bound work. + +### Public API + +- **`pub(crate)` is the default visibility for new items.** `pub` is a contract. +- **`#[non_exhaustive]`** on enums and structs you want to be able to extend without semver breakage. +- **Builder pattern** for complex constructors. The standard library's `std::process::Command` is a model. +- **No leaking `tokio::` types in library APIs.** Use abstract bounds or feature-gate. + +### Static vs. dynamic dispatch + +Generics versus trait objects is an architectural choice, not a style one ([Effective Rust Item 12](https://effective-rust.com/generics.html)): + +- **Generics / `impl Trait` — static dispatch.** Monomorphized: fastest at runtime, no indirection. The default, and the right call on hot paths (consensus, crypto, serialization). The cost is code bloat and compile time when over-used. +- **`dyn Trait` — dynamic dispatch.** One vtable, smaller binary, a pointer indirection per call. Reach for it at plugin boundaries, for heterogeneous collections (`Vec>`), or to cut monomorphization bloat. Needs an object-safe trait. + +Default to generics; choose `dyn` deliberately, not reflexively. + +### API stability and evolution + +A `pub` item is a versioning contract; treat the public surface as SemVer-governed ([Effective Rust Items 21–24](https://effective-rust.com/semver.html)): + +- **Know what breaks.** Removing or renaming a `pub` item, or adding a field to a struct callers construct, is a breaking change; adding a method or a `#[non_exhaustive]` variant is not. +- **`#[non_exhaustive]`** on public enums and structs you expect to grow. +- **Re-export dependency types that appear in your public API** (`pub use dep::Handle`) — otherwise callers can't name the type without pinning the same dependency version (Item 24). +- **Seal traits** you don't want implemented downstream (a private supertrait), so methods can be added later without breaking implementors. +- **Boundaries.** Crates targeting WASM or embedded stay `no_std`-compatible where practical; FFI surfaces stay narrow and are generated with `bindgen` / `cbindgen`, not hand-mapped (Items 33–35). + +## ADR shape for Rust crates + +When opening an ADR for a Rust crate, the template should cover: + +- **Public surface.** What's `pub`, what's `pub(crate)`, what's private. Why. +- **Public-API stability.** The SemVer guarantees the crate makes; `#[non_exhaustive]` use; which dependency types are re-exported. +- **Dispatch strategy.** Where the crate uses generics vs. `dyn Trait`, and why. +- **Error type.** Typed (`thiserror`) or pass-through (`anyhow`). Justify. +- **Async commitments.** Which runtime, where the runtime is required, how the crate's API is shaped around async. +- **Unsafe code.** If any `unsafe { }` is involved, justify the soundness argument and the safety invariants the caller must uphold. +- **Invariants impacted.** Deep links into `.invariants`. + +## Anti-patterns + +- **`unwrap()` in non-test code** without an `// SAFETY: ...` style comment justifying why the invariant holds. +- **`Box` as a function's return type** when you could be specific. Use it only at boundaries. +- **`String` everywhere when `&str` would do.** Allocations have a cost; types tell the caller about ownership. +- **`tokio` types leaked through public APIs of library crates** without feature flags. +- **`unsafe` without a soundness comment.** Every `unsafe` block needs a justification. +- **Undocumented public items.** A `pub` item with no `///` doc comment ships an unexplained contract. +- **`dyn Trait` in a hot-path signature** chosen by default rather than measured. +- **Overengineering.** Reaching for a trait, macro, generic, or `unsafe` before a plain function would do, or optimizing before profiling — the "four horsemen" of bad Rust. Prefer the simplest construct that *still honors the idioms in this guide* — simple, not simplistic. Simplicity is never a license to erase intent: a named enum or newtype still beats a fistful of `bool`/`String` parameters ([`idioms.md`](./idioms.md)). + +## Related + +- [`developer.md`](./developer.md) — implementation-level Rust practice. +- [`reviewer.md`](./reviewer.md) — what to look for in a Rust PR. +- [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) — Filecoin/Forest-specific AI norms; informs Rust review at ChainSafe. +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md) — architectural framework this page defers to. +- [Effective Rust](https://effective-rust.com/) (Drysdale) and [The Rust Book](https://doc.rust-lang.org/book/) — the canonical practice references this section builds on; cataloged in [`sources.md`](../../references/sources.md). +- [Idiomatic Rust](https://github.com/mre/idiomatic-rust) (peer-reviewed corpus) and the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) — idiomatic-Rust principles and API conventions. diff --git a/languages/rust/developer.md b/languages/rust/developer.md new file mode 100644 index 0000000..35b0444 --- /dev/null +++ b/languages/rust/developer.md @@ -0,0 +1,152 @@ +# Rust Developer + +Idiomatic Rust development at ChainSafe. Tooling, formatting, lint, testing, dependency hygiene, the patterns that show up in review. + +> **In one line:** `cargo fmt --check` and `cargo clippy -D warnings` are the floor. `unwrap()` outside tests is a smell. `unsafe` requires a soundness comment. + +## Tooling + +### Formatting and lint + +```sh +cargo fmt --all --check # must pass without diffs +cargo clippy --all-targets -- -D warnings # must pass without errors +``` + +These are CI gates. Failing locally is a sign of a missing pre-commit hook. + +Per-project `rustfmt.toml` and `clippy.toml` configure the defaults. The defaults are good; deviate only when there's a real reason. + +### Toolchain + +Pin the toolchain with `rust-toolchain.toml` at the repo root: + +```toml +[toolchain] +channel = "1.79.0" # or "stable", with a CI-pinned version +components = ["rustfmt", "clippy"] +``` + +Pinned channels keep CI deterministic. Floating to `stable` is fine for libraries but risky for binaries. + +### Dependencies + +- `Cargo.lock` committed for binaries; **not** committed for libraries published to crates.io. +- `cargo update` with care; pin minor versions for cryptography / consensus dependencies where a quiet breakage is expensive. +- `cargo audit` in CI for known-vulnerability scanning. +- `cargo deny` for license, source, and version-control policy. +- For workspaces: workspace-level dependency declarations to keep versions consistent across crates. + +### IDEs + +Whatever you prefer that gives you `rust-analyzer`. Common options include CLion, VSCode, Sublime, Lapce, Helix, Vim, and Emacs. The choice doesn't matter; the LSP integration does. + +## Error handling + +```rust +use anyhow::{Context, Result}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum StoreError { + #[error("key not found: {0}")] + NotFound(String), + #[error("backend failure")] + Backend(#[from] BackendError), +} + +pub fn fetch(key: &str) -> Result { + let raw = read_backend(key).with_context(|| format!("reading {key}"))?; + parse(&raw).context("parsing value") +} +``` + +- **Library crates:** typed errors via `thiserror`. Callers match on variants. +- **Binary crates:** `anyhow::Result` for ergonomics. Add context as errors bubble. +- **`?` for propagation.** Match arms only when you need to inspect or transform. +- **`Result<(), E>` over `bool`** when a function can fail informatively. + +## `unwrap` and `expect` + +- **In tests:** fine. The test panics; that's the signal. +- **In production code:** require a justification. Pattern: + ```rust + // SAFETY: validated by caller; see Foo::new's invariant. + let value = self.field.as_ref().expect("invariant: field set in Foo::new"); + ``` +- **`expect("...")` over `unwrap()`** when you do use it — the message helps debug. + +## Async + +- **`#[tokio::main]`** only in binaries. +- **`async fn` in trait** is stable as of 1.75; older crates use `async-trait`. Pick one consistently. +- **`.await` propagates cancellation.** Tasks dropped between `await` points run their destructors, not the suspended code. Hold no critical invariant across an `.await`. +- **`spawn` vs `spawn_blocking`.** `spawn` for async work, `spawn_blocking` for CPU-bound or sync-blocking work. Mixing them up starves the runtime. +- **`Send + Sync + 'static`** bounds on spawned tasks — design types that meet them. + +## Unsafe + +`unsafe { }` is permitted but expensive. Every `unsafe` block needs: + +- A `// SAFETY: ...` comment immediately above, explaining why the operation is sound. +- A justification for choosing `unsafe` over a safe alternative. +- A test that exercises the path under `miri` if at all possible. + +Forest's reviewer norms (see [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md)) treat `unsafe` as security-relevant. Expect HARD-FAIL-tier scrutiny on PRs introducing it. + +## Testing + +- **Unit tests** in `#[cfg(test)] mod tests { ... }` at the bottom of the module. +- **Integration tests** in `tests/` at the crate root, exercising the public API. +- **`#[tokio::test]`** for async tests; pick the appropriate flavor (`flavor = "multi_thread"`) for tests that need real parallelism. +- **Property-based tests via `proptest`** for parsers, serializers, math, and crypto. +- **`miri`** in CI for unsafe code; catches UB at the test level. +- **`cargo nextest`** for faster test runs in CI. + +## Documentation + +Public interfaces carry doc comments — they are part of the contract ([Effective Rust Item 27](https://effective-rust.com/documentation.html); [Rust Book ch. 14](https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html)): + +- **`///` on every `pub` item**, `//!` for module- and crate-level docs. Say what it does, what it returns, when it errors, and what it panics on. +- **Examples in docs are tests.** Code in `///` examples is compiled and run by `cargo test` (doc-tests), so it can't rot silently. +- **`#![warn(missing_docs)]`** on library crates turns an undocumented `pub` item into a warning — a CI failure under `-D warnings`. +- **Intra-doc links** (`` [`Type`] ``) keep `cargo doc` cross-references resolving as the API moves. + +## CI + +Baseline (extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md)): + +- `cargo fmt --all --check` +- `cargo clippy --all-targets -- -D warnings` +- `cargo build --workspace --all-targets` +- `cargo test --workspace` (runs unit, integration, and doc-tests) +- `cargo doc --no-deps` (catches broken doc links) +- `cargo audit` +- For unsafe-heavy crates: `cargo miri test` + +## Patterns that come up in review + +- **Type-state when the protocol allows it.** Encoding "must call A before B" in the type system is better than a runtime check. +- **Newtypes for domain types.** `pub struct UserId(u64)` keeps a `UserId` from being confused with a `OrderId`. +- **`From` / `TryFrom` for conversions** rather than inherent `to_*` methods. +- **`Deref` only for smart pointers.** Don't lean on `Deref` to fake inheritance. +- **No `String` in error variants** unless you genuinely have an open set; `&'static str` or typed payload is usually better. +- **Derive the standard traits that fit** (`Debug`, `Clone`, `PartialEq`, `Eq`, `Hash`, `Default`) instead of hand-rolling them, and respect their contracts — `Hash` and `Eq` must agree, `Ord` must be consistent with `PartialOrd`. +- **`macro_rules!` only for genuine repetition** the type system can't express; proc-macros are a heavy compile-time dependency, so justify them ([Effective Rust Item 28](https://effective-rust.com/macros.html)). +- **No wildcard imports** (`use foo::*`) outside a crate prelude or `#[cfg(test)]` — they hide where names come from and break when a dependency adds a symbol ([Item 23](https://effective-rust.com/wildcard.html)). + +## Anti-patterns + +- **`unwrap()` in production paths** without `// SAFETY: ...`. +- **`Box` returns** when you could be specific. +- **`async fn` that doesn't `.await` anything.** Probably should be a sync function. +- **`Arc>` reached for reflexively** when a channel would model the problem better. +- **`unsafe` without a soundness comment.** +- **Public API leaking tokio types** without a feature flag. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md) — broader testing posture; the Forest/Ghostty pattern lands here. +- Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) — Filecoin-specific AI norms. +- [Effective Rust](https://effective-rust.com/) and [The Rust Book](https://doc.rust-lang.org/book/) — canonical practice references; cataloged in [`sources.md`](../../references/sources.md). diff --git a/languages/rust/gotchas.md b/languages/rust/gotchas.md new file mode 100644 index 0000000..9c0480c --- /dev/null +++ b/languages/rust/gotchas.md @@ -0,0 +1,188 @@ +# Rust Gotchas + +Common bug classes and surprising behavior in Rust. Reviewer screen and author pre-flight. + +## `unwrap()` in production paths + +The single most common Rust review finding. Tests panic; production code shouldn't. Either handle the case or add a `// SAFETY: ...` comment justifying why the invariant holds. + +## `as` casts that lose precision + +```rust +let big: i64 = 10_000_000_000; +let small: i32 = big as i32; // silently truncates +``` + +Use `TryFrom` / `TryInto` for fallible conversions: + +```rust +let small: i32 = big.try_into()?; +``` + +## Holding a `MutexGuard` across `.await` + +```rust +async fn bug(state: Arc>) { + let guard = state.lock().unwrap(); // std::sync::Mutex + do_async(&*guard).await; // holds the mutex across await → deadlock risk +} +``` + +Use `tokio::sync::Mutex` when locks span `.await`, or scope the guard tightly: + +```rust +async fn fixed(state: Arc>) { + let value = { + let guard = state.lock().unwrap(); + guard.value.clone() + }; + do_async(&value).await; +} +``` + +## Forgetting `Send + 'static` on spawned futures + +```rust +tokio::spawn(async move { + let rc = Rc::new(...); // !Send + rc.do_thing(); +}); // compile error +``` + +Use `Arc` instead of `Rc`, ensure captured types are `Send`. + +## `Cell` / `RefCell` in async contexts + +`RefCell` is `!Sync` — won't cross thread boundaries. For async-shared interior mutability, use `Mutex` or `RwLock` (tokio variants when spanning `await`). + +## Floating-point in `Eq` / `Hash` + +```rust +#[derive(Eq, Hash)] // ERROR: f64 doesn't impl Eq +struct Point { x: f64, y: f64 } +``` + +`f64` is `PartialEq`, not `Eq`. For hashing floats, use a wrapper that handles NaN explicitly, or `ordered_float`. + +## `Box` everywhere + +A `Box` return type erases information and adds an allocation. Use a concrete error type (via `thiserror`) when you can. + +## `Vec::with_capacity(0)` misconception + +`with_capacity` is a hint, not a guarantee — and allocating with capacity 0 is functionally equivalent to `Vec::new()`. Use realistic estimates or skip the hint. + +## Lifetime annotations on `'static` + +```rust +fn make() -> &'static str { ... } +``` + +`'static` does NOT mean "lives forever in memory." It means "doesn't borrow from anything with a shorter lifetime." `String::leak()` produces `&'static str`; `Box::leak(...)` produces `&'static T`. Use sparingly; memory is leaked. + +## `?` in `main` requires `Result`-returning main + +```rust +fn main() { + let x = read()?; // ERROR +} +``` + +```rust +fn main() -> Result<(), Box> { + let x = read()?; + Ok(()) +} +``` + +Or use `anyhow::Result<()>` for ergonomics. + +## `.unwrap()` and `Option` with `Default` + +```rust +let timeout = config.timeout.unwrap_or_default(); // 0 seconds if missing +``` + +`Duration::default()` is zero. `unwrap_or_default` can produce silently-wrong defaults. Specify a sensible default: + +```rust +let timeout = config.timeout.unwrap_or(Duration::from_secs(30)); +``` + +## `String` vs `&str` confusion in error variants + +```rust +#[derive(Error, Debug)] +pub enum E { + #[error("bad: {0}")] + Bad(String), // allocates; fine if message is dynamic + #[error("frozen: {0}")] + Frozen(&'static str), // for compile-time-known strings +} +``` + +Match the storage to the lifetime. Allocating a `String` for a fixed message wastes allocations on the error path. + +## Implicit drop order + +Local variables drop in reverse declaration order. When a destructor's behavior matters (releasing a lock, closing a file, sending a final message), be deliberate about declaration order. + +```rust +let _guard = mutex.lock().unwrap(); // dropped LAST → unlocked last → good +let result = compute(); +``` + +## `Arc>` reflex + +```rust +let shared = Arc::new(Mutex::new(Vec::new())); +// ... spawn tasks that lock and append +``` + +Often a channel models the problem better. `Arc>` is correct but heavyweight; ask whether senders/receivers, or an immutable snapshot pattern, would fit. + +## `dbg!` and `println!` in committed code + +`dbg!` and `println!` debug output is rarely what you want in production. Clippy catches some; review catches the rest. + +## `.collect::>()` mid-iterator unnecessarily + +```rust +items.iter().map(transform).collect::>().into_iter().filter(...) +``` + +vs. + +```rust +items.iter().map(transform).filter(...) +``` + +The intermediate `Vec` allocates and forces evaluation. Chain the iterator unless you need the materialized collection. + +## Integer overflow: debug panics, release wraps + +```rust +let n: u8 = 255; +let m = n + 1; // debug build: panics; release build: wraps to 0 +``` + +Arithmetic overflow is checked in debug builds (panic) and wraps by default in release — so a bug can stay hidden until production. Be explicit about intent: `checked_add` (→ `Option`), `saturating_add`, `wrapping_add`, or `overflowing_add`. For consensus and crypto math, prefer `checked_*` and reject on `None` rather than silently wrapping. + +## Wildcard imports + +```rust +use some_crate::prelude::*; // fine — a curated prelude +use some_crate::*; // smell — where did this name come from? +``` + +`use foo::*` outside a prelude or `#[cfg(test)]` hides where names come from and silently pulls in new symbols when the dependency grows, which can change resolution or introduce conflicts. Import what you use. + +## `unsafe` without `SAFETY` comment + +The single most flagged Rust issue at security-conscious reviews. Every `unsafe { }` block needs the comment. No exceptions. + +## Related + +- [`idioms.md`](./idioms.md) — the inverse: how to do these right. +- [`reviewer.md`](./reviewer.md) — uses this list as the screening surface. +- [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) — upstream practice references. diff --git a/languages/rust/idioms.md b/languages/rust/idioms.md new file mode 100644 index 0000000..ba23f5d --- /dev/null +++ b/languages/rust/idioms.md @@ -0,0 +1,230 @@ +# Rust Idioms + +Idiomatic patterns in Rust at ChainSafe. Reference for authors and reviewers. + +## Naming + +- **Types and traits:** `PascalCase`. +- **Variables, fields, methods, modules:** `snake_case`. +- **Constants and statics:** `SCREAMING_SNAKE_CASE`. +- **Lifetimes:** `'a`, `'b`, or descriptive (`'src`, `'dst`) for complex cases. +- **Generics:** single letter (`T`, `U`, `K`, `V`) when their role is obvious; descriptive (`Item`, `Error`) when not. + +## Errors + +```rust +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum FetchError { + #[error("not found: {key}")] + NotFound { key: String }, + #[error("decode failed")] + Decode(#[from] DecodeError), +} + +pub fn fetch(key: &str) -> Result { + let raw = read(key).ok_or_else(|| FetchError::NotFound { key: key.into() })?; + Ok(decode(&raw)?) +} +``` + +- `thiserror` for libraries, `anyhow` for binaries. +- Error variants are structured, not stringly-typed. +- `?` propagation; reach for `match` only when transforming. + +## Newtypes + +```rust +pub struct UserId(pub u64); +pub struct OrderId(pub u64); +``` + +A `UserId` and `OrderId` are not interchangeable. Newtypes make the type system enforce that. + +For numeric newtypes, `derive_more` or hand-written `From`/`Into`/`Display` are common. + +## Enums over booleans + +```rust +fn set_visibility(v: Visibility) // Visibility::Hidden — intent is obvious +fn set_visible(visible: bool) // what does set_visible(true) mean at the call site? +``` + +A `bool` parameter erases intent at the call site, and a pair of them makes illegal combinations representable. An `enum` names the states and gets exhaustiveness checking (mre/idiomatic-rust: *Enums Instead of Booleans*). + +## Accept flexible input types + +```rust +fn greet(name: &str) // &str, not &String +fn join(parts: &[&str]) -> String // &[T], not &Vec +fn read(path: impl AsRef) -> ... // &str / String / &Path / PathBuf all work +``` + +Take the most general borrowed form. Callers pass what they already have without converting, and ownership decisions stay at the boundary. A recurring theme across the idiomatic-Rust corpus. + +> **Caveat — don't use this in a `dyn`-compatible trait.** A generic or `impl Trait` parameter on a *trait method* makes the trait no longer `dyn`-compatible (formerly "object safe"), so `Box` / `&dyn MyTrait` stop compiling. In a trait you intend to use behind `dyn`, take the concrete borrowed type in the trait method and expose the flexible form as a wrapper — an inherent `impl dyn MyTrait`, or a default method bounded `where Self: Sized` (which keeps it out of the vtable): +> +> ```rust +> trait Loader { +> fn load(&self, path: &Path) -> io::Result>; // concrete type → `dyn Loader` works +> } +> +> impl dyn Loader { +> fn load_any(&self, path: impl AsRef) -> io::Result> { +> self.load(path.as_ref()) // ergonomic wrapper, off the vtable +> } +> } +> ``` +> +> Free functions and inherent methods have no such constraint — use the flexible form freely. See the dispatch section in [`architect.md`](./architect.md). + +## Conversion method naming + +Name conversions by cost, per the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/): + +- **`as_`** — cheap, borrow-to-borrow, no allocation (`str::as_bytes`). +- **`to_`** — expensive, borrow-to-owned; it allocates (`str::to_string`). +- **`into_`** — consumes `self`, owned-to-owned (`String::into_bytes`). + +Iterator producers are `iter` / `iter_mut` / `into_iter`; getters take no `get_` prefix (`config.timeout()`, not `config.get_timeout()`). + +## Builder + +```rust +let config = Config::builder() + .timeout(Duration::from_secs(10)) + .max_retries(3) + .build()?; +``` + +Builders shine when the type has many optional fields. The `build()` returns a `Result` so missing required fields are a compile-time-checkable concept. + +## Type-state + +```rust +pub struct Connection { /* ..., _state: PhantomData */ } +pub struct Disconnected; +pub struct Connected; + +impl Connection { + pub fn connect(self) -> Result, ConnectError> { /* ... */ } +} +impl Connection { + pub fn send(&self, msg: Message) -> Result<(), SendError> { /* ... */ } +} +``` + +When the protocol has phases, encode them in the type. Callers can't `send` on a `Connection` — the compiler refuses. + +## `?` and `From` + +```rust +#[derive(Error, Debug)] +pub enum AppError { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + Parse(#[from] ParseError), +} + +fn run() -> Result<(), AppError> { + let data = std::fs::read("config")?; // io::Error → AppError::Io + let cfg: Config = parse(&data)?; // ParseError → AppError::Parse + Ok(()) +} +``` + +`#[from]` lets `?` convert errors at propagation points. + +## `Iterator` adapters + +Prefer iterator chains over explicit loops when the chain is short and clear: + +```rust +let total: u64 = orders.iter().filter(|o| o.active).map(|o| o.total).sum(); +``` + +When a chain gets long enough to wrap several lines, a loop with intermediate variables is often clearer. Readability beats cleverness. + +## `Option` and `Result` combinators + +```rust +config + .timeout + .map(|s| Duration::from_secs(s)) + .unwrap_or_else(default_timeout) +``` + +`map`, `and_then`, `unwrap_or_else`, `ok_or_else` are the standard set. Avoid `unwrap()` and `unwrap_or(...)` with non-trivial defaults; the `_else` variants defer computation. + +## `Default` for "empty" instances + +```rust +#[derive(Default)] +pub struct Config { + pub timeout: Option, + pub max_retries: u32, +} + +let cfg = Config::default(); +``` + +Combined with `..Default::default()` in struct literals, this lets callers specify only the fields they care about. + +## `derive` everything that fits + +`Clone`, `Debug`, `PartialEq`, `Eq`, `Hash`, `Default`, `serde::{Serialize, Deserialize}` — derive freely. Re-implementing them by hand is a smell unless you have a specific reason. + +## Static vs. dynamic dispatch + +```rust +fn process(items: impl Iterator) { ... } // static: monomorphized, fast +fn register(handlers: Vec>) { ... } // dynamic: one vtable, heterogeneous +``` + +`impl Trait` (and generic ``) compile to specialized code per type — the default, and what hot paths want. `dyn Trait` trades a pointer indirection for a smaller binary and the ability to hold different concrete types together. Reach for `dyn` at boundaries and for heterogeneous collections; stay generic where performance matters. + +## Smart pointers: which one + +- **`&T` / `&mut T`** — borrow; the default. No ownership, no allocation. +- **`Box`** — single heap owner; for recursive types or moving a large value cheaply. +- **`Rc` / `Arc`** — shared ownership; `Rc` single-threaded, `Arc` across threads. Add a `Mutex` / `RwLock` only when you also need shared *mutation*. +- **`Cow<'a, T>`** — borrow until you must mutate, then clone-on-write. Good for APIs that usually don't allocate. + +Reach for the cheapest one that expresses the ownership you actually need. + +## Module structure + +``` +src/ +├── lib.rs # crate root, re-exports public surface +├── error.rs # public error type(s) +├── client/ +│ ├── mod.rs # public Client type +│ ├── request.rs +│ └── response.rs +└── internal/ # not re-exported + └── ... +``` + +`mod.rs` (or `.rs` since 2018 edition) is the module's root. The crate root re-exports what's public. + +## Doc comments + +```rust +/// Fetches the value stored under `key`. +/// +/// # Errors +/// Returns [`FetchError::NotFound`] when the key is absent. +pub fn fetch(key: &str) -> Result { ... } +``` + +`///` on public items, `//!` for the module. Document the error and panic conditions. The example compiles and runs under `cargo test`, so the docs can't drift from the code. + +## Related + +- [`developer.md`](./developer.md) — fuller rationale. +- [`gotchas.md`](./gotchas.md) — what to avoid. +- [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) — the upstream practice references. +- [Idiomatic Rust](https://github.com/mre/idiomatic-rust) · [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) — the idiomatic-Rust corpus and API conventions. diff --git a/languages/rust/reviewer.md b/languages/rust/reviewer.md new file mode 100644 index 0000000..0045a9e --- /dev/null +++ b/languages/rust/reviewer.md @@ -0,0 +1,102 @@ +# Rust Reviewer + +Language-specific checklist when reviewing a Rust PR. Operates under the [universal review principles](../../workflows/code-review.md#universal-principles). + +> **In one line:** Lint clean, no `unwrap()` outside tests, no `unsafe` without soundness, no `tokio` leaking into library APIs. SOFT WARNING in general; `unsafe` gets near-HARD scrutiny. + +## Severity tier + +Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Rust reviewer findings emit as **SOFT WARNING** by default. **`unsafe` blocks promote to near-HARD-FAIL scrutiny** per Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) — security-critical, requires explicit operator review beyond the agent reviewer. + +## What to look for + +### Errors and panics + +- **No `unwrap()` / `expect()` in production paths** without a `// SAFETY: ...` comment justifying the invariant. Test code is exempt. +- **Typed errors via `thiserror`** in library crates; `anyhow::Result` in binaries. Mixing the patterns in one crate is a smell. +- **`?` propagation** instead of match-on-trivial-pass-through. +- **Errors carry context.** `.context(...)` / `.with_context(...)` calls preserve the chain. +- **No `unimplemented!()` / `todo!()` / `panic!()` in production paths.** If the work isn't done, the PR isn't ready. + +### Unsafe + +- **Every `unsafe` block has a `// SAFETY: ...` comment.** Missing → HARD-FAIL-equivalent; the reviewer refuses to approve. +- **The justification is real.** "Performance" alone is not a soundness argument; cite the invariants and what makes them hold. +- **`miri` testing path exists** for the unsafe code (if the project's CI supports it). If not, flag as a risk. +- **The unsafe is minimized.** Wrap the smallest possible code in `unsafe { }`; the safe wrapper should be obvious. + +### Async + +- **`async fn` actually awaits.** A function declared async that doesn't `.await` is probably sync in disguise. +- **No `Send`/`Sync` violations in spawn boundaries.** `tokio::spawn(future)` requires `Send + 'static`; verify. +- **`.await` does not span a critical invariant.** Holding a non-cancellation-safe state across an `.await` is a bug. +- **`spawn` vs `spawn_blocking`.** CPU-bound work in `spawn` starves the runtime; flag. +- **No unbounded `FuturesUnordered` / `JoinSet`** for inputs of unknown size. Use `buffer_unordered` or a semaphore. + +### API design + +- **`pub(crate)` is the default.** New `pub` items should be justified. Public API is a versioning commitment. +- **`#[non_exhaustive]`** on enums and structs that may grow. Forgetting this locks the crate into a breaking-change cycle. +- **No `tokio::` types in public library APIs** unless feature-gated. +- **Newtypes for domain values.** Bare `u64` or `String` crossing module boundaries is a smell if a newtype would communicate intent. +- **Public items are documented.** New `pub` items carry `///` docs (what it does, returns, errors, panics); examples are doc-tested (Effective Rust Item 27). +- **Dispatch is justified.** Generics / `impl Trait` on hot paths; `dyn Trait` only where heterogeneity or binary size earns the indirection. +- **Breaking changes are intentional.** Removing or renaming a `pub` item, or adding a constructible field, is a SemVer break — flag it. API-visible dependency types are re-exported. +- **Flexible input types.** Public functions take `&str` / `&[T]` / `impl AsRef` over `&String` / `&Vec` / concrete owned types where reasonable. +- **Conversion and getter naming** follow the Rust API Guidelines: `as_` / `to_` / `into_` by cost, `iter` / `iter_mut` / `into_iter`, no `get_` prefix. +- **Enums over boolean parameters** where a `bool` argument erases intent at the call site. + +### Concurrency primitives + +- **`Arc>` reflex check.** Could a channel model this? An immutable type? An `Arc` without the mutex? Often yes. +- **`std::sync::Mutex` vs. `tokio::sync::Mutex`.** Locks that span `await` need the tokio mutex. +- **No `.lock().unwrap()` chains** without a comment on why poisoning is impossible (or how it's handled). + +### Tests + +- **Tests exist for the change.** The [testing-and-qa](../../workflows/testing-and-qa.md) page applies: agent-authored tests need the same scrutiny as agent-authored code. +- **Mocks are minimal.** Mock-heavy unit tests asserting "was called" rather than behavior are theatre. +- **Property tests via `proptest`** for code with formal invariants (parsing, serialization, math, crypto). +- **`miri` tests for unsafe.** Where applicable. + +### Lint and formatting + +- **`cargo fmt --check`** clean. +- **`cargo clippy -D warnings`** clean. +- **No `#[allow(...)]`** without a comment explaining why. +- **No wildcard imports** (`use foo::*`) outside a prelude or `#[cfg(test)]`. +- **`cargo doc --no-deps`** builds (no broken doc links). + +### Dependencies + +- **No new unjustified dependencies.** Each new crate in `Cargo.toml` is a supply-chain decision. +- **License compatibility.** GPL incursions into Apache 2.0–licensed crates are blocking. +- **`cargo audit` clean.** No known vulnerabilities introduced. + +## What to flag vs. fix in place + +- **Flag**: `unsafe` soundness, panic-vs-error decisions, async design, public API extensions, dependency additions, lint suppressions. +- **Suggest with code suggestion**: trivial fmt-clippy issues that CI didn't catch, doc-link typos. +- **Don't fix and push** unless the operator has authorized co-authorship. + +## When the reviewer skill refuses to review + +- Diff contains code in a language other than Rust. +- PR description is empty. +- Diff touches code out of session scope. +- **Diff introduces `unsafe` and the PR description doesn't justify it.** Refuse and escalate to the CODEOWNER. + +## Phrasing + +- Lead with the concern: "This `unsafe` block transmutes between repr-C and a Rust struct; the SAFETY comment cites layout, but the layout is `repr(Rust)` and not guaranteed. What's the actual soundness argument?" +- Cite Forest's AI policy when relevant. +- `nit:` for taste-level. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/code-review.md`](../../workflows/code-review.md) — universal review framework. +- [`../../invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings) — HARD FAIL semantics; `unsafe` promotes here. +- Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) — the Filecoin-specific extension. +- [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) — canonical practice references (see [`sources.md`](../../references/sources.md)). +- [Idiomatic Rust](https://github.com/mre/idiomatic-rust) · [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) — idiomatic-Rust corpus and API conventions. diff --git a/languages/solidity/architect.md b/languages/solidity/architect.md new file mode 100644 index 0000000..ffe1e4d --- /dev/null +++ b/languages/solidity/architect.md @@ -0,0 +1,99 @@ +# Solidity Architect + +Architectural guidance for Solidity (and EVM-adjacent) work at ChainSafe — [Sprinter](https://github.com/sprintertech) and the broader crypto/bridging surface. The architectural framework is `.invariants` (see the [pointer page](../../invariants/invariants-framework.md)); this page covers Solidity-specific shaping. + +> **In one line:** Every Solidity decision is a security decision. Upgrade safety, reentrancy, and audit-readiness are first-class architectural concerns. + +## Defer to `.invariants` for + +| Decision | `.invariants` section | +|---|---| +| Cross-contract contracts and invariants | Component contracts | +| Upgrade lifecycle invariants | Lifecycle / migration invariants | +| Authorization invariants | Authorization model | +| Bridge / cross-chain invariants | Cross-chain invariants | + +## Solidity-specific architectural choices + +Reviewer skills for Solidity are **HARD FAIL tier** per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail). Architecture decisions that don't anticipate this will get blocked at review. + +### Project layout + +ChainSafe Solidity projects use Foundry (preferred) or Hardhat. Layout: + +- `src/` (Foundry) or `contracts/` (Hardhat) — Solidity sources, split by domain. +- `test/` — Foundry-style fuzz and unit tests, or Hardhat tests in JS/TS. +- `script/` — deployment and operations scripts. +- `lib/` — vendored libraries (OpenZeppelin, Solady, Solmate, etc.). +- `foundry.toml` / `hardhat.config.ts` at the root. + +For multi-contract systems, group by domain (`bridge/`, `tokens/`, `governance/`) not by file kind. + +### Upgrade strategy + +Pick one at design time: + +- **Immutable.** No upgrade path. Simplest, safest, locks in mistakes forever. +- **UUPS (Universal Upgradeable Proxy Standard).** Logic contract holds the upgrade method; thinner proxy. Requires authorization for `upgradeTo`. +- **Transparent proxy.** Admin/user separation handled by the proxy; familiar from OpenZeppelin tooling. +- **Diamond (EIP-2535).** Multi-facet, modular. Powerful, complex, more surface to audit. + +The decision is binding for the contract's life. Migrating between upgrade strategies is itself a migration risk. Default to **immutable** unless you have a concrete reason for upgradeability. + +### Access control + +- **OpenZeppelin `AccessControl`** for role-based authorization in most cases. +- **`Ownable`** only for genuinely-single-owner cases. Owner key compromise is total compromise. +- **Multi-sig** (Gnosis Safe) for any production deployment's privileged operations. Single-key control of production contracts is a finding. +- **Timelocks** on upgrade and parameter changes. Gives stakeholders time to react. + +### Reentrancy posture + +- **Checks-Effects-Interactions** pattern, always. State changes happen before external calls. +- **OpenZeppelin `ReentrancyGuard`** on every external function that calls untrusted contracts (transfers, callbacks, etc.). +- **Pull over push** for payments where reasonable — let recipients withdraw rather than pushing transfers. + +### External calls + +- **Address every call's failure mode.** What happens if the call reverts? Returns wrong data? Reentrancy? +- **`.transfer` and `.send` are deprecated**; use `.call{value: amount}("")` and check the return value. +- **Approval-then-transfer patterns** for ERC-20: be aware of the classic approval race; use `safeIncreaseAllowance` / `safeDecreaseAllowance` from OpenZeppelin. + +### Bridge-specific invariants (Sygma context) + +For cross-chain code: + +- **Consistent state across chains** — what invariant is the bridge maintaining? +- **Replay protection** — message uniqueness via nonces, domain separators, or both. +- **Failure mode for the destination chain** — what happens if delivery fails or is censored? +- **Slashing / signer-set rotation** — how do signer changes propagate? + +Each becomes an `.invariants` entry; reviewer skills check them per-PR. + +## ADR shape for Solidity contracts + +Every non-trivial Solidity ADR covers: + +- **Upgrade strategy.** Immutable / UUPS / Transparent / Diamond. Justification. +- **Access control model.** Roles, role-granting, role-renouncing, multi-sig vs. EOA. +- **External-call surface.** Which functions make external calls; what's the reentrancy posture. +- **Storage layout.** For upgradeable contracts, storage layout is part of the contract; ADR documents the layout and the gap pattern. +- **Audit plan.** When the contract is audited (pre-deploy, post-deploy, recurring), by whom. +- **Test coverage commitments.** Unit, fuzz, invariant tests, formal verification if applicable. +- **Invariants impacted.** Deep links into `.invariants`. + +## Anti-patterns + +- **Owner key controls production contracts.** Use a multi-sig. +- **Upgrade path with no timelock.** Stakeholders need time to react. +- **State changes after external calls.** Reentrancy waiting to happen. +- **`tx.origin` for authorization.** Use `msg.sender`. +- **Unbounded loops over caller-controlled data.** Gas-griefing waiting to happen. +- **Custom math instead of OpenZeppelin SafeMath / Solady.** Reinventing audited primitives. +- **`assembly` blocks without inline justification.** Same standard as Rust `unsafe`. + +## Related + +- [`developer.md`](./developer.md), [`reviewer.md`](./reviewer.md) (HARD FAIL tier), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md) — security-sensitive path discipline. +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md). diff --git a/languages/solidity/developer.md b/languages/solidity/developer.md new file mode 100644 index 0000000..e0b153c --- /dev/null +++ b/languages/solidity/developer.md @@ -0,0 +1,178 @@ +# Solidity Developer + +Idiomatic Solidity development at ChainSafe. Tooling, testing, common patterns, and the discipline that keeps PRs out of HARD-FAIL territory at review. + +> **In one line:** Foundry for new work. Tests are fuzz + invariant by default. OpenZeppelin for primitives. Every external call is a security decision. + +## Tooling + +### Toolchain + +- **Foundry** for new projects. `forge` for tests and builds, `cast` for chain interaction, `anvil` for local nodes. +- **Hardhat** in projects where it's already entrenched. Don't migrate without reason. +- **Pin the Solidity version** in `foundry.toml` / `hardhat.config.ts` and at the top of every contract: + ```solidity + pragma solidity 0.8.24; + ``` + Floating pragmas (`^0.8.0`) are a smell — they make audit findings ambiguous and CI non-deterministic. + +### Dependencies + +- **OpenZeppelin Contracts** for standard primitives (ERC-20, ERC-721, AccessControl, ReentrancyGuard, etc.). +- **Solady** or **Solmate** when gas optimization matters and you have the audit capacity to back gas-tuned code. +- **Vendor via git submodule** (Foundry default) or **npm package** (Hardhat). Pin to specific versions; don't track `main`. + +### Static analysis + +- **slither** as a baseline. Runs in CI; specific rules can be muted with `// slither-disable-next-line ...` + a comment. +- **mythril** for symbolic execution on critical contracts. +- **solhint** for style. + +These are required CI checks, not optional. + +## Code structure + +### Imports + +```solidity +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.24; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +``` + +- **Named imports** (`import {Foo} from "..."`) over wildcard `import "..."`. Clear what's imported; helps audit. +- **SPDX identifier** at the top of every file. Apache 2.0 to match the repo, or per-project license if different. + +### Function visibility + +- **`external`** by default for callable-from-outside functions; saves gas vs. `public` for calldata-sized args. +- **`public`** when the function is also called internally. +- **`internal`** for cross-contract-inheritance helpers. +- **`private`** rarely; `internal` is usually right for inheritance. + +### State variables + +- **Pack storage** — group same-size types together to share slots. +- **`immutable`** for values set once in the constructor (saves storage reads). +- **`constant`** for compile-time-known values. +- **Document storage layout** for upgradeable contracts (`__gap` array reserves slots for future fields). + +## Reentrancy and external calls + +```solidity +function withdraw(uint256 amount) external nonReentrant { + // Checks + require(amount > 0, "WrongAmount"); + require(balances[msg.sender] >= amount, "Insufficient"); + + // Effects + balances[msg.sender] -= amount; + totalDeposits -= amount; + + // Interactions + (bool ok, ) = msg.sender.call{value: amount}(""); + require(ok, "TransferFailed"); +} +``` + +- **`nonReentrant`** on every external function that calls untrusted code. +- **Checks-Effects-Interactions** as a rigid pattern. State changes before external calls. Always. +- **`.call{value: ...}("")` over `.transfer` / `.send`** — those have hard gas limits that break with new opcode gas costs. +- **Check return values.** A failed call that you don't check is a silent bug. +- **Use OpenZeppelin's `SafeERC20`** for token transfers. Standard ERC-20 implementations differ; SafeERC20 normalizes. + +## Access control + +```solidity +contract Vault is AccessControl, ReentrancyGuard { + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN"); + bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR"); + + function setFee(uint256 newFee) external onlyRole(ADMIN_ROLE) { + // ... + } +} +``` + +- **`AccessControl`** over `Ownable` for any contract with more than one privileged action. +- **Role-grant authority** is itself a privileged action; lock down `DEFAULT_ADMIN_ROLE`. +- **Multi-sig** holds privileged roles in production; EOAs are for dev/test only. +- **Timelocks** on parameter changes and upgrades. + +## Errors + +Custom errors over `require` strings (Solidity 0.8.4+): + +```solidity +error Insufficient(uint256 requested, uint256 available); +error WrongCaller(address caller); + +function withdraw(uint256 amount) external { + if (balances[msg.sender] < amount) revert Insufficient(amount, balances[msg.sender]); + // ... +} +``` + +- Smaller bytecode than `require` strings. +- Structured data the caller can decode. +- `require(condition, "Message")` is acceptable for very simple cases but the trend is toward custom errors. + +## Testing + +Foundry's testing model is the baseline: + +- **Unit tests** in `test/*.t.sol`. +- **Fuzz tests** by parameterizing function arguments — `forge` fuzzes by default. +- **Invariant tests** — declare a property that should always hold, `forge` finds sequences that break it. +- **Differential tests** against a reference implementation (Yul, Vyper, off-chain) when one exists. +- **Mainnet fork tests** for integrations with deployed contracts. + +```solidity +function testFuzz_Withdraw(uint256 amount) public { + vm.assume(amount > 0 && amount <= INITIAL_DEPOSIT); + vault.deposit{value: amount}(); + vault.withdraw(amount); + assertEq(vault.balanceOf(address(this)), 0); +} +``` + +Coverage via `forge coverage`. The bar for security-critical code is high — 100% line coverage is necessary, not sufficient (you also need fuzz and invariant tests). + +## Deployment + +- **Deployment scripts** in `script/` (Foundry) or `deploy/` (Hardhat). Reproducible from source. +- **Verified source** on the relevant block explorer (Etherscan, Sourcify) for every public deployment. +- **Audit before public deployment** for any contract holding value. The architect ADR names the audit plan. +- **Constructor args recorded** alongside the deployment script, for verification. + +## CI + +Baseline (extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md)): + +- `forge build` +- `forge test -vvv` +- `forge coverage` with a threshold (typically 95%+ for security-critical code) +- `slither .` +- `solhint 'src/**/*.sol'` +- Mainnet fork tests on a schedule (every PR if cheap, daily if expensive) +- Gas snapshot via `forge snapshot --check` to catch gas regressions + +## Anti-patterns + +- **`tx.origin` for authorization.** Always `msg.sender`. +- **Floating pragma** (`^0.8.0`). Pin the version. +- **Unbounded loops over user-controlled data.** Gas griefing. +- **State changes after external calls.** Reentrancy. +- **`.transfer` / `.send` for ETH transfers.** Use `.call{value:}("")`. +- **Custom math reimplementing audited primitives.** Use OpenZeppelin / Solady. +- **`assembly` without inline justification.** Auditor will flag. +- **Owner-key control of production contracts.** Multi-sig. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md) **(HARD FAIL tier)**, [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md). diff --git a/languages/solidity/gotchas.md b/languages/solidity/gotchas.md new file mode 100644 index 0000000..32464a2 --- /dev/null +++ b/languages/solidity/gotchas.md @@ -0,0 +1,184 @@ +# Solidity Gotchas + +Bug classes and surprising behavior in Solidity. Most of these are HARD FAIL findings under the [reviewer](./reviewer.md). + +## Reentrancy (the classic) + +```solidity +function withdraw() external { + uint256 amount = balances[msg.sender]; + (bool ok, ) = msg.sender.call{value: amount}(""); // external call BEFORE state update + require(ok); + balances[msg.sender] = 0; // attacker can reenter before this +} +``` + +`msg.sender` can be a contract whose receive function calls back into `withdraw`. Always: Checks-Effects-Interactions. + +## Cross-function reentrancy + +```solidity +function depositA() external payable { balanceA[msg.sender] += msg.value; } +function withdrawB() external { + uint256 amount = balanceB[msg.sender]; + msg.sender.call{value: amount}(""); + balanceB[msg.sender] = 0; +} +``` + +`withdrawB` is reentrant into `depositA` even though `depositA` itself doesn't make external calls. State shared across functions needs guarding too. + +## `tx.origin` for authorization + +```solidity +modifier onlyOwner() { + require(tx.origin == owner); // ALWAYS WRONG + _; +} +``` + +`tx.origin` is the original EOA that started the transaction; any intermediate contract is `msg.sender`. A malicious contract the owner interacts with can call your contract during the same transaction. Use `msg.sender`. + +## Floating pragma + +```solidity +pragma solidity ^0.8.0; +``` + +Different compilers may produce different bytecode for the same source. Audit findings refer to specific compiler behavior. Pin: `pragma solidity 0.8.24;`. + +## Unchecked `.transfer` / `.send` + +```solidity +payable(recipient).transfer(amount); // hardcoded 2300 gas; breaks with new opcode pricing +payable(recipient).send(amount); // 2300 gas + returns bool you might ignore +``` + +Use `.call`: + +```solidity +(bool ok, ) = payable(recipient).call{value: amount}(""); +require(ok, "TransferFailed"); +``` + +## ERC-20 `transfer` return value ignored + +```solidity +IERC20(token).transfer(recipient, amount); // some tokens return false instead of revert +``` + +Not all ERC-20s revert on failure (USDT famously doesn't return a bool at all). Use `SafeERC20.safeTransfer` / `safeTransferFrom`. + +## Approval race condition + +```solidity +token.approve(spender, oldAmount); +// attacker uses oldAmount +token.approve(spender, newAmount); +// attacker can now use newAmount as well — they got oldAmount + newAmount +``` + +Use `safeIncreaseAllowance` / `safeDecreaseAllowance` from OpenZeppelin, or approve to 0 before changing. + +## Integer arithmetic edge cases (Solidity < 0.8) + +Pre-0.8 Solidity wraps integer overflow silently. ChainSafe contracts should be ≥0.8 — if you find <0.8 code, it's a HARD FAIL until upgraded or wrapped with SafeMath. + +## `unchecked` blocks + +```solidity +unchecked { x = a + b; } // overflow possible +``` + +`unchecked` removes overflow checks. Use only when you've proven overflow is impossible (e.g., loop counters bounded by storage). Comment why. + +## `delegatecall` storage corruption + +```solidity +contract A { + address public owner; // slot 0 +} +contract B { + bool public initialized; // slot 0 + function init() external { A(target).delegatecall(...); } // writes through to A's slot 0 +} +``` + +`delegatecall` runs target code in the caller's storage context. Storage layout differences corrupt state. Only use with libraries that explicitly support delegatecall and whose storage layouts you control. + +## Unbounded loops + +```solidity +function distribute(address[] calldata recipients) external { + for (uint256 i = 0; i < recipients.length; i++) { + recipients[i].call{value: amount}(""); + } +} +``` + +Gas griefing: caller passes a huge array, transaction reverts out-of-gas, function is permanently unusable for any caller. Bound the loop or use pull-payment. + +## Storage layout drift in upgradeable contracts + +```solidity +// V1 +contract V1 { uint256 totalDeposits; mapping(address => uint256) balances; } + +// V2 — INSERTS a new field at top, shifts every existing field +contract V2 { uint256 fee; uint256 totalDeposits; mapping(address => uint256) balances; } +``` + +The proxy's storage is now interpreted with the V2 layout, but the actual storage was written under V1's layout. Existing balances become "fees." Catastrophic. Append-only, use `__gap`, and verify layout diff. + +## Missing `initializer` modifier + +```solidity +contract Upgradeable is Initializable { + function initialize() external { // missing `initializer` modifier + owner = msg.sender; + } +} +``` + +Without `initializer`, the function can be called repeatedly — anyone can become owner after the first init. + +## `private` is not private + +`private` and `internal` only restrict Solidity-level access. The actual storage is readable from off-chain via `eth_getStorageAt`. Don't store secrets in contract storage; they're public. + +## Selector collision in proxy patterns + +When a proxy delegates to a logic contract, the proxy's own functions can collide with the logic contract's selectors (4-byte hash of the signature). Transparent and UUPS proxies handle this differently. Be aware which you're using. + +## `msg.value` in non-payable functions + +```solidity +function foo() external { /* msg.value reverts */ } +``` + +`msg.value` is always zero for non-payable functions, but trying to call with ETH attached reverts before entering. Mark functions `payable` only when they should accept ETH. + +## Block-based timing as authority + +```solidity +if (block.timestamp > deadline) { /* ... */ } +``` + +`block.timestamp` is manipulable by miners within a small window. Don't use for randomness; don't use for short-window authorization. Bounds are typically ±15 seconds. + +## `block.number` and chain reorgs + +L1 reorgs are rare but happen. L2 reorgs are more common. Don't assume `block.number` ordering is final until enough confirmations. + +## Forgetting events on critical state changes + +State changes without events are invisible to off-chain indexers, dashboards, and security monitors. Emit events for every privileged action. + +## Constructor in upgradeable contracts + +Constructors run on the logic contract, not the proxy. Any state set in a constructor is lost from the proxy's perspective. Use `initialize` + `initializer` modifier. + +## Related + +- [`reviewer.md`](./reviewer.md) — uses this list as the screening surface; most entries are HARD FAIL findings. +- [`idioms.md`](./idioms.md) — how to do these right. diff --git a/languages/solidity/idioms.md b/languages/solidity/idioms.md new file mode 100644 index 0000000..898b53c --- /dev/null +++ b/languages/solidity/idioms.md @@ -0,0 +1,182 @@ +# Solidity Idioms + +Idiomatic patterns for Solidity at ChainSafe. + +## Naming + +- **Contracts, interfaces, libraries:** `PascalCase`. Interfaces prefixed `I` (`IERC20`). +- **Functions, variables, modifiers:** `camelCase`. +- **Constants and immutables:** `SCREAMING_SNAKE_CASE`. +- **Events:** `PascalCase`, past-tense verb (`Transferred`, `Upgraded`, `RoleGranted`). +- **Custom errors:** `PascalCase`, descriptive (`InsufficientBalance`, `NotAuthorized`). +- **Files:** `PascalCase.sol`, matching the main contract's name. + +## CEI (Checks-Effects-Interactions) + +```solidity +function withdraw(uint256 amount) external nonReentrant { + // Checks + if (amount == 0) revert ZeroAmount(); + if (balances[msg.sender] < amount) revert Insufficient(amount, balances[msg.sender]); + + // Effects + balances[msg.sender] -= amount; + + // Interactions + (bool ok, ) = msg.sender.call{value: amount}(""); + if (!ok) revert TransferFailed(); +} +``` + +Always in this order. Make it a habit; reviewers expect it. + +## Custom errors + +```solidity +error Insufficient(uint256 requested, uint256 available); +error WrongCaller(address caller, address expected); +error AlreadyInitialized(); + +function check(uint256 amount) internal view { + if (amount > balance) revert Insufficient(amount, balance); +} +``` + +Smaller bytecode than `require("string")`, structured data for callers, clearer at the call site. + +## Events for state changes + +```solidity +event Deposited(address indexed from, uint256 amount); +event Withdrew(address indexed to, uint256 amount); + +function deposit() external payable { + balances[msg.sender] += msg.value; + emit Deposited(msg.sender, msg.value); +} +``` + +Every state-changing privileged action emits an event. Indexed parameters (max 3) make off-chain indexing efficient. + +## OpenZeppelin primitives + +```solidity +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; + +contract Vault is AccessControl, ReentrancyGuard, Pausable { + using SafeERC20 for IERC20; + + bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR"); + + function withdraw(IERC20 token, address to, uint256 amount) + external + nonReentrant + whenNotPaused + onlyRole(OPERATOR_ROLE) + { + token.safeTransfer(to, amount); + } +} +``` + +Compose audited primitives instead of reinventing. + +## Pull over push + +```solidity +mapping(address => uint256) public pendingWithdrawals; + +function recordPayment(address recipient, uint256 amount) internal { + pendingWithdrawals[recipient] += amount; +} + +function withdraw() external nonReentrant { + uint256 amount = pendingWithdrawals[msg.sender]; + if (amount == 0) revert NothingToWithdraw(); + pendingWithdrawals[msg.sender] = 0; + (bool ok, ) = msg.sender.call{value: amount}(""); + if (!ok) revert TransferFailed(); +} +``` + +Let recipients pull funds rather than pushing transfers. Avoids gas-griefing and reentrancy in many shapes. + +## `immutable` for constructor-set values + +```solidity +contract Token { + address public immutable factory; + uint256 public immutable initialSupply; + + constructor(uint256 _initialSupply) { + factory = msg.sender; + initialSupply = _initialSupply; + } +} +``` + +`immutable` saves a SLOAD per access vs. regular storage. `constant` for compile-time-known values; `immutable` for constructor-time. + +## Storage packing + +```solidity +// 1 slot (32 bytes total) +struct Pack1 { + uint128 a; + uint64 b; + uint64 c; +} + +// 3 slots +struct Pack2 { + uint256 a; + uint128 b; + uint128 c; +} +``` + +Group same-size types together. The compiler lays out by declaration order; rearranging can save gas. + +## Upgradeable storage with `__gap` + +```solidity +contract VaultV1 is Initializable, AccessControlUpgradeable { + uint256 public totalDeposits; + mapping(address => uint256) public balances; + + uint256[48] private __gap; // reserve 48 slots for future fields +} +``` + +Reserves slots so V2 can add fields without breaking layout. Decrement `__gap` size when you add a real field. + +## Custom errors with revert data + +```solidity +error Insufficient(uint256 requested, uint256 available); + +function transfer(uint256 amount) external { + if (amount > balance) revert Insufficient(amount, balance); +} +``` + +The revert data is decodable off-chain — frontends can show "you requested X, only Y available" instead of "transaction failed." + +## `using ... for ...` + +```solidity +using SafeERC20 for IERC20; + +function transferIn(IERC20 token, uint256 amount) internal { + token.safeTransferFrom(msg.sender, address(this), amount); +} +``` + +Extends a type with library functions. The classic example is `SafeERC20`. + +## Related + +- [`developer.md`](./developer.md), [`gotchas.md`](./gotchas.md). diff --git a/languages/solidity/reviewer.md b/languages/solidity/reviewer.md new file mode 100644 index 0000000..462105f --- /dev/null +++ b/languages/solidity/reviewer.md @@ -0,0 +1,114 @@ +# Solidity Reviewer + +Language-specific review for Solidity PRs. Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Solidity reviewer findings emit at **HARD FAIL** severity for security-critical checks. The agent reports; the operator decides; bypass is logged in the PR with an explicit `Override: HARD FAIL X for reason Y` per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). + +> **In one line:** Reentrancy, upgrade safety, access control, audit-readiness. HARD FAIL findings stop the PR until a CODEOWNER signs off on the override. + +## Severity tier + +**HARD FAIL.** Override path is explicit and audit-logged in the PR. The agent does not push through; the operator does, in writing. + +## HARD FAIL checks (reviewer refuses LGTM until resolved or explicitly overridden) + +### Reentrancy + +- **State changes after external calls.** Any `.call`, `.delegatecall`, ERC-20 transfer, token callback, or call to an arbitrary address with state mutations after it. +- **Missing `nonReentrant`** on external functions that call untrusted contracts (transfers, callbacks, hooks). +- **Cross-function reentrancy.** A function that doesn't itself make external calls but shares state with one that does, without proper guards. + +### Authorization + +- **`tx.origin` used for authorization.** Always a HARD FAIL. Use `msg.sender`. +- **Privileged function without access control modifier.** Every state-changing function with privileged effects must have an explicit `onlyRole` / `onlyOwner` / equivalent. +- **`onlyOwner` on a contract holding non-trivial value** without a multi-sig path. The architect ADR named the multi-sig requirement; the implementation must honor it. +- **Role grant power not locked down.** `DEFAULT_ADMIN_ROLE` (in OpenZeppelin `AccessControl`) is the most powerful role; it must be held by a multi-sig and protected by a timelock. + +### Upgrade safety (for upgradeable contracts) + +- **Storage layout changes** between versions. Each storage variable in an upgradeable contract is addressed by slot; reordering or inserting non-appended variables corrupts state. Every PR touching an upgradeable contract is checked against the prior storage layout. +- **`initializer` discipline.** Upgradeable contracts use `initialize` instead of constructors; missing `initializer` modifier or skipping the parent initializer is a HARD FAIL. +- **Missing `__gap` reserved slots** for upgradeable base contracts. +- **`UUPSUpgradeable._authorizeUpgrade`** must restrict access. Missing or weak authorization = total contract control bypass. +- **No timelock** on the upgrade path for production contracts. + +### External calls + +- **Unchecked return values.** `.call{value:}("")` that doesn't check `ok`. `IERC20.transfer` that doesn't check return (use `SafeERC20`). +- **`.transfer` / `.send`** with hard-coded 2300 gas — breaks with EIP-1884 and similar gas changes. Use `.call`. +- **Unbounded gas forwarding to untrusted contracts** in critical paths. +- **`delegatecall` to caller-controlled addresses.** Can rewrite the caller's storage. + +### Arithmetic + +- **`unchecked { ... }` blocks** without inline justification. Solidity 0.8+ has overflow checks by default; removing them is a deliberate choice that needs a comment. +- **Custom math** instead of OpenZeppelin / Solady. Reinventing wheels invites bugs auditors have already caught upstream. + +### `assembly` / Yul + +- **`assembly` without an inline justification.** Same standard as Rust `unsafe`. Comment explains why assembly, what the invariants are, and how they're verified. +- **`assembly` reading from user-controlled storage slots** without explicit reasoning. + +### Bridge / cross-chain (Sygma context) + +- **Missing nonce / replay protection** on cross-chain messages. +- **Trust assumptions on signer sets** that don't survive signer-set rotation. +- **No failure mode** for messages that can't be delivered on the destination chain (lost funds risk). +- **Inconsistent state model** between source and destination contracts. + +## SOFT WARNING checks (flag, don't block) + +- Style and naming. +- Gas optimizations that don't affect correctness (suggest, don't require). +- Test coverage gaps in non-critical paths. +- Documentation thinness. +- `solhint` style violations. + +## Audit-readiness checklist + +A PR introducing or substantially changing a contract should be audit-ready by the time it merges: + +- [ ] **Spec or design doc** linked in the PR description. +- [ ] **Threat model** named — what's the attacker capability, what's the asset, what's the boundary. +- [ ] **Unit tests + fuzz tests + invariant tests** for the changed surface. +- [ ] **Slither clean** or muted findings with explicit `// slither-disable-next-line ... reason: ...` comments. +- [ ] **Coverage threshold met** (typically 95%+). +- [ ] **Gas snapshot diff** intentional (regressions justified). +- [ ] **Storage layout diff** for upgradeable contracts, attached to the PR. +- [ ] **Deployment script** if the contract is deployable from this PR. + +If the PR is in scope for a scheduled audit, the audit firm gets an artifact bundle (spec, tests, deployment script) — the PR should produce that bundle without extra work. + +## When the reviewer skill refuses to review + +- Non-Solidity code in the diff. +- PR description doesn't name the threat model. +- PR introduces a privileged function without access control modifiers. +- PR changes storage layout of an upgradeable contract without a layout-diff in the description. +- PR is making a deployment-affecting change without a deployment script. + +In each case, escalate to a Solidity CODEOWNER and the curator. + +## Override mechanics + +Per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings), HARD FAIL bypass requires: + +1. The reviewer skill emits the finding with a unique identifier. +2. The operator (CODEOWNER) reviews and decides to override. +3. The PR description gets an `Override: HARD FAIL for reason ` line. +4. A separate audit-log entry is created (CHANGELOG or similar) recording the override. +5. The override is reviewed in the post-merge cycle. + +The agent does not override on the operator's behalf. The operator types the override line themselves. + +## Phrasing + +- Lead with the concern and its severity: "**HARD FAIL — reentrancy.** This function transfers ETH via `.call{value:}` and then updates `balances`. CEI requires balance update first." +- Cite the rule: "Per [Solidity reviewer §reentrancy](#reentrancy)." +- Reference the auditor's perspective: "An auditor reviewing this would flag the missing `nonReentrant` immediately; the override mechanics exist for exceptions, not for the default path." + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/code-review.md`](../../workflows/code-review.md). +- [`../../operating-model/gates-and-escalation.md`](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) — HARD FAIL gate mechanics. +- [`../../invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). diff --git a/languages/typescript/architect.md b/languages/typescript/architect.md new file mode 100644 index 0000000..d59e2fd --- /dev/null +++ b/languages/typescript/architect.md @@ -0,0 +1,93 @@ +# TypeScript Architect + +Architectural guidance for TypeScript projects at ChainSafe — [Lodestar](https://github.com/ChainSafe/lodestar) (Ethereum consensus client), [web3.js 4.x](https://github.com/ChainSafe/web3.js), [ssz](https://github.com/ChainSafe/ssz), [bls](https://github.com/ChainSafe/bls), [filsnap](https://github.com/ChainSafe/filsnap), and others. The architectural framework is `.invariants` (see the [pointer page](../../invariants/invariants-framework.md)). + +> **In one line:** Strict mode, branded types for domain values, no `any`. ESM by default. Public API stability via type-level tests. + +## Defer to `.invariants` for + +| Decision | `.invariants` section | +|---|---| +| Service boundaries | Component contracts | +| Invariant naming + testability | Invariant lifecycle | +| Cross-component contracts | API invariants | + +## TypeScript-specific architectural choices + +### Project layout + +For most ChainSafe TS projects, **Yarn 3 workspaces** is the monorepo standard (the legacy `lerna` setup is deprecated). Layout: + +- Root `package.json` with `"packageManager": "yarn@3.x"` and `"workspaces": ["packages/*"]`. +- Each package in `packages//` with its own `package.json`, `src/`, `test/`, `tsconfig.json`. +- Shared dev tooling (eslint config, prettier, base tsconfig) lives at the root and is extended per-package. +- TypeScript build via `tsc -b` (composite projects) or via a bundler (esbuild, swc) per package's needs. + +For non-monorepo projects: standard `src/` + `test/`, single `package.json`, single `tsconfig.json`. + +### Type strictness + +- **`"strict": true`** in `tsconfig.json` is the floor. With every sub-flag on. +- **`"noUncheckedIndexedAccess": true`** — array indexing returns `T | undefined`. Catches a large class of bugs. +- **`"exactOptionalPropertyTypes": true`** when the project can take it. +- **`"isolatedModules": true`** for bundler compatibility. + +### Module system + +- **ESM by default** for new projects. `"type": "module"` in `package.json`, `.js` extensions in import paths. +- **CJS only where downstream consumers require it** (Node-only tooling, certain frameworks). +- **Dual-publish** (`main` + `module` + `exports`) for libraries that need to support both. + +### Branded types for domain values + +```ts +type UserId = string & { readonly __brand: "UserId" }; +type OrderId = string & { readonly __brand: "OrderId" }; +``` + +Domain identifiers should not be interchangeable. Branded types catch the mix-up at the type level without runtime cost. + +### Error model + +- **Throw `Error` subclasses, not plain `Error` instances**, so callers can `instanceof` discriminate. +- **`Result` or `Either`-like types** for libraries where error-as-value semantics fit; throw for binary entrypoints. +- **`AggregateError`** for Promise.allSettled-style multi-error cases. +- **Never throw strings or non-`Error` objects.** Always throw an instance with a stack. + +### Async + +- **`async`/`await` over raw promises** for readability. +- **`Promise.all` for parallel independent work; `Promise.allSettled` when you need each result's status; sequential `await` only when one operation depends on the previous.** +- **No floating promises.** Either `await`, `.then()`, or assign to a variable that's later awaited. ESLint's `no-floating-promises` catches. +- **AbortSignal** for cancellation propagation. Long-running operations accept an `AbortSignal`. + +### Public API + +- **Type-level tests** for public types — `tsd` or `expect-type` to assert the type surface doesn't drift. +- **Re-exports through a single `index.ts`** per package. Implementation files are not stable surface. +- **`@internal` JSDoc tag** for items that need to be exported for tooling reasons but aren't public API. API extractor tooling can enforce. + +## ADR shape for TypeScript projects + +When opening an ADR for a TS project or significant module: + +- **Public surface.** What's exported. Type-level tests covering it. +- **Async commitments.** Where cancellation is propagated; where parallelism is exploited. +- **Error contract.** Thrown types vs. returned types. How callers should handle each. +- **Build target.** Node version, browser support, ESM/CJS, bundler. +- **Invariants impacted.** Deep links into `.invariants`. + +## Anti-patterns + +- **`any` in committed code.** `unknown` is the right escape hatch when you genuinely don't know the type. +- **`as` type assertions without a runtime check.** Lying to the compiler. Use guards or schema validation. +- **Unbounded `Promise.all` over a large input** that calls a rate-limited API. Use `p-limit` or similar. +- **Default exports.** Named exports are refactorable; default exports lose their name on import. +- **`enum`s when union types would do.** Const objects + `as const` produce better-typed sets. +- **`tsc --noEmit` not in CI.** Type errors should fail the build, not just IDE squiggles. + +## Related + +- [`developer.md`](./developer.md) — implementation-level practice. +- [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md) — the architectural framework. diff --git a/languages/typescript/developer.md b/languages/typescript/developer.md new file mode 100644 index 0000000..406cf74 --- /dev/null +++ b/languages/typescript/developer.md @@ -0,0 +1,173 @@ +# TypeScript Developer + +Idiomatic TypeScript at ChainSafe. Tooling, lint, testing, monorepo setup, and the patterns that come up in review. + +> **In one line:** `strict: true`. ESLint with the [ChainSafe shared config](https://github.com/ChainSafe/eslint-config). Yarn 3 workspaces for monorepos. No `any`, no floating promises, no `as` casts without a guard. + +## Tooling + +### Linter + +ESLint with the [`@chainsafe`](https://github.com/ChainSafe/eslint-config) shared config: + +```sh +yarn add --dev eslint@8 @chainsafe/eslint-config +``` + +`.eslintrc.cjs`: + +```js +module.exports = { + extends: "@chainsafe", +}; +``` + +Run via `yarn lint` (script: `eslint 'src/**/*.ts'`). If a rule feels wrong, the right move is to PR the shared config, not local override. + +Prettier is included transitively for formatting. Run `prettier --check` in CI. + +### TypeScript config + +A strict-by-default `tsconfig.json` baseline: + +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "dist" + } +} +``` + +Tighten per project; `strict: true` is the floor. + +### Monorepos: Yarn 3 workspaces + +ChainSafe uses **Yarn 3 with workspaces**, having migrated off `lerna`. + +Setup: + +1. **Enable corepack.** `corepack enable` (Node 16+) or `npm i -g corepack` for older. +2. **Root `package.json`** declares: + ```json + { + "packageManager": "yarn@3.4.1", + "workspaces": ["packages/*"] + } + ``` +3. **Per-package `package.json`** with its own dependencies, `main`/`exports`, scripts. +4. **TypeScript project references** (`tsconfig.json` with `references: [...]`) for cross-package types and incremental builds. + +A [template](https://github.com/ChainSafe/yarn-workspaces-typescript-template) exists; consult before bootstrapping from scratch. + +### Testing + +- **Vitest** for new projects (fast, ESM-native). +- **Mocha + Chai** in legacy Lodestar / web3.js (entrenched; don't rewrite without reason). +- **Jest** for projects where it's already set up. + +Whichever framework: run via `yarn test`, configure with a `test/` or `__tests__/` convention. Coverage via the framework's built-in reporter; CI fails if coverage drops below a per-project threshold. + +### Editor + +VSCode is the de-facto editor; recommended extensions: ESLint, GitLens, DotEnv, YAML. Whatever IDE the developer prefers as long as it talks to `tsserver`. + +## Type discipline + +- **No `any` in committed code.** `unknown` for genuinely-typeless values; narrow before use. ESLint's `no-explicit-any` enforces. +- **`as` casts only with a guard.** A bare `value as Foo` is a lie. Use `typeof`, `instanceof`, or a schema validator (`zod`, `io-ts`) to narrow. +- **`unknown` over `any` for caught errors:** `try { ... } catch (err: unknown) { ... }`. +- **Discriminated unions** for state machines: + ```ts + type State = + | { kind: "idle" } + | { kind: "loading"; startedAt: number } + | { kind: "loaded"; data: Data } + | { kind: "error"; error: Error }; + ``` +- **`readonly` on properties that don't mutate.** `as const` for literal narrowing. +- **Branded types** for domain values that shouldn't mix (see [architect.md § Branded types](./architect.md#branded-types-for-domain-values)). + +## Async + +- **`async`/`await`** for readability. Top-level await in ESM is fine. +- **`Promise.all`** for parallel independent work. **`Promise.allSettled`** when partial failure is acceptable. +- **No floating promises.** Either `await`, attach `.catch(...)`, or assign and await later. ESLint's `no-floating-promises` is on. +- **`AbortSignal` for cancellation.** Functions that can take a while should accept an optional `signal: AbortSignal`. +- **`for await ... of`** for sequential consumption of async iterables. + +## Error handling + +```ts +class FetchError extends Error { + constructor(public readonly url: string, public readonly status: number) { + super(`fetch ${url} failed: ${status}`); + this.name = "FetchError"; + } +} + +async function fetchData(url: string): Promise { + const res = await fetch(url); + if (!res.ok) throw new FetchError(url, res.status); + return res.json() as Promise; // (with a guard or schema in production code) +} +``` + +- **Throw `Error` subclasses.** Always. Never strings. +- **Distinguish recoverable from non-recoverable** by error class, not by inspecting messages. +- **`AggregateError`** for the `Promise.allSettled` multi-error case. + +## CI + +Baseline (extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md)): + +- `yarn lint` +- `yarn prettier --check '**/*.{ts,json,md}'` +- `yarn tsc --noEmit` (type-check separately from build) +- `yarn build` (real build, catches different failures than `--noEmit`) +- `yarn test --coverage` +- `yarn audit` for vulnerability scanning +- Type-surface check (`tsd` / `expect-type`) for libraries publishing types + +## Publishing npm packages + +- **Semver discipline.** Major for breaking changes, minor for additive, patch for fixes. TypeScript-level breaking changes (renaming a type, narrowing a return) are also major. +- **`exports` field** in `package.json`, not just `main`. Modern Node resolution depends on it. +- **`files` field** to ship only `dist/` and necessary docs. Don't ship `src/` or tests. +- **CHANGELOG.md** updated in the same PR as the change. `changesets` (used in some ChainSafe projects) automates this nicely. +- **`prepublishOnly` script** runs build + tests one more time before publish. + +## Patterns that come up in review + +- **`unknown` then narrow** over `any`. +- **Discriminated unions** for "one of N states." +- **`readonly` arrays and tuples** for immutable data. +- **`Pick`, `Omit`, `Partial`, `Required`** for type composition rather than re-declaring. +- **Type predicates (`value is Foo`)** for custom type guards. +- **`satisfies`** for type-checking literal values without widening. + +## Anti-patterns + +- **`any` or `as Foo`** in committed code. +- **Floating promises.** +- **`default export`** when a named export would do. +- **`enum`** when a const object + `as const` produces better types. +- **`@ts-ignore`** without a comment and an issue link. +- **Untyped network responses.** Validate at the boundary. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md). diff --git a/languages/typescript/gotchas.md b/languages/typescript/gotchas.md new file mode 100644 index 0000000..6640f95 --- /dev/null +++ b/languages/typescript/gotchas.md @@ -0,0 +1,175 @@ +# TypeScript Gotchas + +Common bug classes and surprising behavior in TypeScript. + +## `any` propagates silently + +```ts +function take(x: any) { return x.foo.bar.baz; } // no errors +``` + +`any` flows through expressions. Once it's in your codebase, it spreads. Reach for `unknown` instead and narrow. + +## `as` lies to the compiler + +```ts +const value = somethingUnsafe as User; +// the runtime value is whatever it is; the compiler thinks it's a User +``` + +`as` is a developer assertion. Use a type guard or schema validator. If you must `as`, comment why. + +## `!` non-null assertion + +```ts +const user = users.find((u) => u.id === id)!; +``` + +If the find returns undefined, you get a runtime crash with a worse stack than a proper error. Use an explicit check. + +## `[]` access without `noUncheckedIndexedAccess` + +```ts +const arr: string[] = []; +const first: string = arr[0]; // compiler says string; runtime says undefined +``` + +Enable `"noUncheckedIndexedAccess": true` in tsconfig. The type becomes `string | undefined` and you have to handle it. + +## Floating promises + +```ts +async function fireAndForget() { + doStuffAsync(); // returns a Promise; not awaited; errors silently swallowed +} +``` + +Either `await`, `.catch(...)` it, or assign and await later. ESLint catches; turn the rule on. + +## `for ... in` vs `for ... of` on arrays + +```ts +const arr = [10, 20, 30]; +for (const i in arr) { /* i is the string "0", "1", "2" */ } +for (const v of arr) { /* v is 10, 20, 30 */ } +``` + +`for ... in` iterates keys (and inherited enumerable properties). For arrays, almost never what you want. + +## `JSON.parse` returns `any` + +```ts +const data = JSON.parse(raw); // any +data.user.id; // no error, runtime crash possible +``` + +Validate the result with a schema (`zod`, `io-ts`, `valibot`) or a hand-written type guard. + +## `process.env` returns `string | undefined` + +```ts +const port: number = parseInt(process.env.PORT); // NaN if not set +``` + +Validate at boot. Set defaults explicitly. `env.ts` modules that parse and freeze environment config catch this. + +## `Promise.race` and ignored losers + +```ts +const winner = await Promise.race([fetchA(), fetchB()]); +// fetchB still runs to completion if A wins. If it errors, you have an unhandled rejection. +``` + +`AbortController` to actually cancel the loser, or `Promise.any`/`Promise.allSettled` depending on intent. + +## `setTimeout` does not return a number in Node + +```ts +const t: number = setTimeout(() => {}, 1000); // type error in Node typings; returns Timeout +``` + +`ReturnType` is the portable type. Don't store it as `number`. + +## Recursive types and `infer` + +```ts +type Flat = T extends (infer U)[] ? Flat : T; // TS 5+ supports +``` + +Older TypeScript versions hit recursion limits. Check the project's TypeScript version before reaching for deep recursive types. + +## `tsc` and bundler disagreements + +`tsc --noEmit` may pass; the bundler (esbuild, swc, vite) may still fail at build time. Run both in CI. They check different things. + +## Class field initialization order + +```ts +class Foo { + private a = this.b; // ReferenceError at runtime (b is undefined here) + private b = 1; +} +``` + +Field initialization is top-to-bottom; don't reference fields declared later. + +## `===` vs `==` with `null` / `undefined` + +```ts +if (x == null) { /* true for both null and undefined */ } +if (x === null) { /* true only for null */ } +``` + +`== null` is the one place loose-equality is idiomatic — when you want both. Otherwise `===`. + +## `Map` and `Set` JSON serialization + +```ts +const m = new Map([["a", 1]]); +JSON.stringify(m); // "{}" +``` + +`Map` and `Set` aren't JSON. Convert (`Array.from(m.entries())`) or use a serialization library. + +## `Date` is mutable and timezone-fraught + +```ts +const d = new Date(); +d.setDate(d.getDate() + 1); // mutates d +``` + +Use `temporal` polyfill (when available) or `date-fns` (immutable functions) for non-trivial date math. Always store UTC; convert at display. + +## `try`/`catch` and `Error.cause` + +```ts +try { ... } catch (err) { + throw new MyError("wrapping", { cause: err }); +} +``` + +`Error.cause` (stage-4 / ES2022) is widely supported now. Use it to preserve the chain when re-throwing. + +## ESM and CJS interop + +```ts +// in an ESM project: +import express from "express"; // works +import { Router } from "express"; // may not work depending on Express version +``` + +CJS packages don't always behave well under ESM imports. Check the package's `exports` field. When in doubt, default-import then destructure. + +## Module resolution: `.js` in import paths + +In ESM TypeScript projects with `"module": "NodeNext"`, imports must include the `.js` extension even though the file is `.ts`: + +```ts +import { Client } from "./client.js"; // resolves client.ts at compile, client.js at runtime +``` + +Counterintuitive but correct. + +## Related + +- [`idioms.md`](./idioms.md), [`reviewer.md`](./reviewer.md). diff --git a/languages/typescript/idioms.md b/languages/typescript/idioms.md new file mode 100644 index 0000000..89c7e7d --- /dev/null +++ b/languages/typescript/idioms.md @@ -0,0 +1,177 @@ +# TypeScript Idioms + +Idiomatic patterns in TypeScript at ChainSafe. + +## Naming + +- **Types and interfaces:** `PascalCase`. +- **Variables, functions, methods:** `camelCase`. +- **Constants (top-level, immutable):** `SCREAMING_SNAKE_CASE` for genuine constants; `camelCase` for module-level singletons. +- **Files:** `kebab-case.ts` for source, matching the primary export's name when sensible. +- **Type parameters:** single letter (`T`, `K`, `V`) when role is obvious; descriptive (`TItem`, `TError`) when not. + +## Discriminated unions for state + +```ts +type Async = + | { status: "idle" } + | { status: "loading" } + | { status: "success"; data: T } + | { status: "error"; error: E }; + +function render(state: Async) { + switch (state.status) { + case "idle": return spinner(); + case "loading": return spinner(); + case "success": return userCard(state.data); + case "error": return errorBanner(state.error); + } +} +``` + +The compiler enforces all cases are handled (with `noFallthroughCasesInSwitch`). Adding a new state case becomes a compile error in every consumer — exactly what you want. + +## Branded types + +```ts +type UserId = string & { readonly __brand: "UserId" }; +type OrderId = string & { readonly __brand: "OrderId" }; + +function getUserId(raw: string): UserId { + // validate, then assert + return raw as UserId; +} +``` + +Construction is centralized; once you have a `UserId`, the type system stops you from passing it where an `OrderId` is expected. + +## `unknown` then narrow + +```ts +function isUser(value: unknown): value is User { + return ( + typeof value === "object" && + value !== null && + "id" in value && + typeof value.id === "string" + ); +} + +const data: unknown = JSON.parse(raw); +if (isUser(data)) { + // data is User +} +``` + +For larger schemas, use `zod`, `io-ts`, or `valibot` to validate at the boundary and infer types from the schema. + +## `as const` for literal narrowing + +```ts +const ROLES = ["admin", "editor", "viewer"] as const; +type Role = (typeof ROLES)[number]; // "admin" | "editor" | "viewer" +``` + +Avoid `enum`; `as const` plus `typeof[number]` produces a better-typed set with no runtime overhead. + +## `satisfies` for type checking without widening + +```ts +const config = { + timeout: 5000, + retries: 3, + endpoints: { api: "/v1/api", health: "/v1/health" }, +} satisfies AppConfig; + +// config.endpoints.api stays the literal "/v1/api", not widened to `string` +``` + +`satisfies` checks shape without losing literal-type information. + +## Type predicates + +```ts +function isError(value: unknown): value is Error { + return value instanceof Error; +} +``` + +Functions returning `value is Foo` participate in narrowing. + +## Composition with utility types + +```ts +type UserSummary = Pick; +type CreateUser = Omit; +type PartialConfig = Partial; +type RequiredConfig = Required; +type ReadonlyUser = Readonly; +``` + +Compose instead of re-declaring. The compiler keeps the relationship; refactors propagate. + +## Async patterns + +```ts +// parallel independent +const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]); + +// allow partial failure +const results = await Promise.allSettled(jobs.map(run)); +const succeeded = results.flatMap((r) => (r.status === "fulfilled" ? [r.value] : [])); + +// cancellable +async function fetchWithTimeout(url: string, ms: number) { + const ctrl = new AbortController(); + const timer = setTimeout(() => ctrl.abort(), ms); + try { + return await fetch(url, { signal: ctrl.signal }); + } finally { + clearTimeout(timer); + } +} +``` + +## Error subclasses + +```ts +export class FetchError extends Error { + constructor( + public readonly url: string, + public readonly status: number, + cause?: Error, + ) { + super(`fetch ${url} failed: ${status}`); + this.name = "FetchError"; + if (cause) (this as any).cause = cause; // Error.cause is stage-4 + } +} + +try { + await something(); +} catch (err) { + if (err instanceof FetchError && err.status === 404) { + return null; + } + throw err; +} +``` + +Named subclasses let callers `instanceof`-discriminate without string-matching on the message. + +## Exports + +Named exports, single `index.ts` per module, no default exports for libraries: + +```ts +// index.ts +export { Client } from "./client.js"; +export type { ClientOptions } from "./client.js"; +export * from "./errors.js"; +``` + +The `.js` extension on imports is required for ESM resolution. + +## Related + +- [`developer.md`](./developer.md), [`gotchas.md`](./gotchas.md). diff --git a/languages/typescript/reviewer.md b/languages/typescript/reviewer.md new file mode 100644 index 0000000..e54f425 --- /dev/null +++ b/languages/typescript/reviewer.md @@ -0,0 +1,92 @@ +# TypeScript Reviewer + +Language-specific checklist for TypeScript PRs. Operates under the [universal review principles](../../workflows/code-review.md#universal-principles). + +> **In one line:** No `any`, no `as` without a guard, no floating promises, no `@ts-ignore` without justification. SOFT WARNING tier. + +## Severity tier + +Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), TypeScript reviewer findings emit as **SOFT WARNING**. Agent flags, operator decides. + +## What to look for + +### Type discipline + +- **`any` in committed code** → flag. `unknown` with narrowing is the right alternative. +- **`as` type assertions** → require an accompanying type guard or schema check. Bare `value as Foo` is lying to the compiler. +- **`@ts-ignore` / `@ts-expect-error`** → require a comment with a reason and ideally an issue link. CI should fail bare-comment forms. +- **`!` non-null assertion** → flag. Use a real narrowing or an explicit check. +- **Index access without bounds check** → with `noUncheckedIndexedAccess: true` the compiler catches this; verify the tsconfig has it on. +- **`Function` and `Object` types** → too wide. Use specific signatures. + +### Module hygiene + +- **Default exports** → ask if a named export would do. Default exports lose their name on import and complicate refactors. +- **Circular imports** → flag. They tend to produce undefined-at-load-time bugs. +- **Implementation imports of internals** → if a package's internal module is imported across package boundaries, the package's API surface is being violated. + +### Async + +- **Floating promises** → `.catch(...)` or `await` required. ESLint catches most; review catches the rest. +- **`Promise.all` over a large input calling a rate-limited service** → use `p-limit` or similar. +- **Missing `await` before a Promise-returning expression** → especially in conditionals (`if (somePromise)` is always truthy). +- **`async` functions that don't await anything** → probably should be sync. +- **No `AbortSignal` on long-running operations** → callers can't cancel; flag. + +### Error handling + +- **Thrown non-`Error` values** → strings, plain objects. Always throw an `Error` subclass. +- **`catch (err)` without typing as `unknown` and narrowing** → `err.message` access on an untyped catch is fragile. +- **`try`/`catch` that swallows errors** → at minimum log; usually re-throw or wrap. + +### Tests + +- **Type-level tests** for libraries publishing types — `tsd` or `expect-type` assertions covering the public surface. +- **Tests touch behavior, not implementation.** Asserting that an internal function was called is theatre. +- **`describe`/`it` names are sentences** — when the test name plus the assertion message tell you what broke, debugging is fast. +- **Coverage threshold enforced in CI** — not just reported. + +### Build and config + +- **`strict: true`** in tsconfig. +- **`noUncheckedIndexedAccess`** on for new projects. +- **`tsc --noEmit`** runs in CI as its own step, not just baked into the build. +- **Lint and format pass** locally before commit (pre-commit hook present?). +- **No `node_modules` or `dist` in PR diff.** + +### Dependencies + +- **No `latest` or floating versions** in `package.json`. +- **`yarn audit` clean** post-merge. +- **License-compatible** — GPL in an Apache 2.0 distribution is blocking. +- **No new dependencies without justification.** Each new dep is a supply-chain choice. + +### Public API (for libraries) + +- **New `export`s are deliberate.** Anything exported is a versioning commitment. +- **`@internal` JSDoc** on tooling-exported items that aren't public API. +- **CHANGELOG entry** in the same PR as a breaking change. + +## What to flag vs. fix in place + +- **Flag**: `any`, `as` without guards, floating promises, error-type issues, public-API decisions. +- **Suggest with code suggestion**: trivial lint, prettier, typo, JSDoc fix. +- **Don't fix and push** unless authorized. + +## When the reviewer skill refuses to review + +- Non-TypeScript code in diff. +- Empty PR description. +- Out-of-session-scope code. +- **No `strict: true` in tsconfig** — refuse and escalate. Type discipline is the foundation; reviewing under non-strict mode catches less than half the bugs. + +## Phrasing + +- Lead with concern: "This function takes `data: any` and forwards it to the network layer. What's the actual shape? If it's polymorphic, a discriminated union models it; if it's truly opaque, `unknown` plus a guard is the right call." +- Cite the rule: "Per [TS developer guide](./developer.md#type-discipline), `as` requires a guard." +- `nit:` for taste. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/code-review.md`](../../workflows/code-review.md). diff --git a/languages/zig/architect.md b/languages/zig/architect.md new file mode 100644 index 0000000..c6cc1a5 --- /dev/null +++ b/languages/zig/architect.md @@ -0,0 +1,89 @@ +# Zig Architect + +Architectural guidance for Zig at ChainSafe. The canonical codebase is [lodestar-z](https://github.com/ChainSafe/lodestar-z) — Zig consensus libraries for Lodestar: SSZ serialization, Merkleization, hashing, persistent Merkle trees, and the Ethereum consensus types, consumed by the TypeScript client across a C-ABI boundary. The architectural framework lives in `.invariants` (see the [pointer page](../../invariants/invariants-framework.md)); this page covers Zig-specific shaping. + +> **In one line:** Allocators are explicit and injected. Errors are values. Safety is a build-mode decision you make on purpose. Comptime replaces macros. The exported C ABI is a contract. + +## When Zig (and when not) + +Zig earns its place where the realistic alternative is C: small, performance-critical, memory-controlled libraries that are consumed across an FFI boundary — hashing, SSZ encode/decode, Merkleization hot paths. That is exactly lodestar-z's brief. + +It is **not** the default for general work. Services and tooling have a chosen language already: TypeScript (Lodestar), Go (Gossamer), Rust (Forest), Solidity (contracts), Python (ops/scripts). Reaching for Zig outside the "C-replacement library" niche is an org-level decision, not an individual-PR one — raise it with the curator and capture the rationale in an ADR before starting. + +## Defer to `.invariants` for + +| Decision | `.invariants` section | +|---|---| +| Service/module boundaries and contracts | Component contracts | +| Invariant naming and testability | Invariant lifecycle | +| Cross-component failure modes | Failure-mode invariants | +| Memory-ownership invariants | Ownership/lifetime invariants | + +## Zig-specific architectural choices + +### Project layout + +- `build.zig` + `build.zig.zon` at the root. `build.zig.zon` is the package manifest: pinned dependencies and a `minimum_zig_version`. +- `src/` with a library root (`root.zig`) and/or an executable entry (`main.zig`). +- **Public modules are declared in `build.zig`** (`b.addModule`) so consumers `@import` them by name. lodestar-z exposes `ssz`, `hashing`, `persistent_merkle_tree`, and `consensus_types` this way — the module list *is* the public surface. +- `test/` for spec and integration tests, `bench/` for benchmarks, `bindings/` for the C-ABI / language-binding surface. +- Files are structs. One primary type per file; the filename is `TitleCase` when the file *is* that struct, `snake_case` otherwise. + +### Allocator strategy (the central decision) + +Zig has no hidden allocations — every API that allocates takes an `std.mem.Allocator`. The architecture decision is **who owns allocation at each boundary**: + +- **Inject, never capture.** Functions and types receive an allocator; they do not reach for a global. This is what makes a library usable in tests, in WASM, and across the FFI boundary. +- **Match the allocator to the lifetime.** An arena for operation-scoped bulk allocation freed in one shot; a fixed-buffer allocator for bounded hot paths; a leak-detecting general-purpose allocator in debug and tests. +- **Ownership is explicit.** Document who frees what, especially for values that cross a function return or the C ABI. Pair every acquire with `defer` / `errdefer`. + +### Error model + +- **Explicit error sets at public boundaries.** Expose a named error set so callers can `switch` exhaustively; let inference (`!T`) handle internal helpers. +- **`try` to propagate, `errdefer` to clean up the partial-construction path.** Errors are values and cannot be silently dropped. +- **`unreachable` / `catch unreachable` only where success is a proven invariant** — and remember it is undefined behavior in the unsafe build modes. Never on genuinely fallible I/O. + +### Comptime over macros and codegen + +Generics are functions that return a `type`: `fn List(comptime T: type) type`. lodestar-z's SSZ type constructors (`UintType(64)`, `FixedContainerType(struct { ... })`) are the canonical pattern — zero-cost, type-safe, no macro layer. Keep comptime surfaces small and documented; comptime that could have been runtime hurts readability and compile time. + +### Build mode and safety posture + +Decide the optimization mode per artifact, on purpose: + +- **ReleaseSafe is the default for anything where a wrong answer matters** — which is all of lodestar-z. Runtime safety checks stay on. +- **ReleaseFast only for measured hot paths,** with `@setRuntimeSafety(false)` scoped to the smallest region and justified in a comment. In the unsafe modes, integer overflow and out-of-bounds access become undefined behavior rather than a panic — never assume them away for correctness. + +### The C ABI is a contract + +lodestar-z is consumed by Lodestar across a C ABI. Treat the exported surface (`export fn`, `callconv(.C)`, `extern` structs with defined layout) like a public API: versioned, documented, and with explicit memory ownership across the boundary (who allocates, who frees). Breaking it breaks a downstream client in another language. + +### Pre-1.0 reality + +Zig is pre-1.0; the language and standard library change across releases. Pin `minimum_zig_version` in `build.zig.zon` and the exact compiler in CI, wrap std APIs you depend on heavily, and budget for migration on each upgrade. + +## ADR shape for Zig modules + +- **Allocator ownership.** Who allocates, who frees, which allocator type, and why. +- **Error set.** The public error set and what each variant means. +- **Build-mode / safety posture.** ReleaseSafe vs. ReleaseFast, and the justification for any disabled safety. +- **Comptime surface.** What is resolved at compile time and why. +- **Exported C ABI.** The stable surface and cross-boundary memory ownership, if any. +- **Zig version floor.** The `minimum_zig_version` and the upgrade story. +- **Invariants impacted.** Deep links into `.invariants`. + +## Anti-patterns + +- **A hidden or global allocator.** It defeats testability, leak detection, and FFI use. +- **ReleaseFast for correctness-critical code** without a measured reason and scoped safety justification. +- **Comptime where runtime would do.** Cleverness that costs compile time and readability. +- **Leaking allocator ownership across the C ABI** without a documented contract — the downstream binding will leak or double-free. +- **`catch unreachable` on fallible operations.** A panic in safe builds, undefined behavior in unsafe ones. + +## Related + +- [`developer.md`](./developer.md) — implementation-level Zig practice. +- [`reviewer.md`](./reviewer.md) — what to look for in a Zig PR. +- [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../invariants/invariants-framework.md`](../../invariants/invariants-framework.md) — the architectural framework this page defers to. +- [Zig Language Reference](https://ziglang.org/documentation/master/) and [Learn Zig](https://ziglang.org/learn/) — the upstream canonical guidance this page is built on. diff --git a/languages/zig/developer.md b/languages/zig/developer.md new file mode 100644 index 0000000..6627457 --- /dev/null +++ b/languages/zig/developer.md @@ -0,0 +1,144 @@ +# Zig Developer + +Idiomatic Zig development at ChainSafe. Tooling, the build system, testing, memory discipline, the patterns that show up in review. The working example throughout is [lodestar-z](https://github.com/ChainSafe/lodestar-z). + +> **In one line:** `zig fmt --check` and `zig build test` are the floor. Allocators are passed in, never global. `defer` / `errdefer` sit next to every acquire. Safety stays on unless a benchmark says otherwise. + +## Tooling + +### Formatting + +```sh +zig fmt --check . # must pass without diffs +``` + +`zig fmt` is canonical and unconfigurable — the gofmt of Zig. No style bikeshedding; the formatter decides. Run it on save; gate it in CI. + +### Build system + +`build.zig` (the build script, written in Zig) plus `build.zig.zon` (the package manifest). Common commands: + +```sh +zig build # default install step +zig build test # run the test step +zig build run # run an executable artifact +zig build -Doptimize=ReleaseSafe # choose the optimization mode +zig build -Dtarget=wasm32-wasi # cross-compile; no separate toolchain needed +``` + +Projects define their own steps. lodestar-z, for example, exposes `zig build test:int`, `zig build test:generic_spec_tests`, and `zig build test:static_spec_tests -Dpreset=mainnet` — wire spec/conformance suites in as named steps so they are one command to run. + +### Dependencies and toolchain + +- Dependencies live in `build.zig.zon`; add them with `zig fetch --save ` so the hash is pinned. +- **Pin the Zig version.** Set `minimum_zig_version` in `build.zig.zon` and pin the exact compiler in CI. Zig is pre-1.0 — language and std change across releases, and an unpinned toolchain makes CI non-deterministic. +- Vendor or pin cryptographic / consensus dependencies where a quiet upstream change is expensive. + +### Editors + +Anything that speaks ZLS (the Zig Language Server): VSCode, Neovim, Helix, Emacs, Sublime, and others. The editor doesn't matter; the LSP integration does. + +## Memory and allocators + +Every allocation takes an injected allocator and is paired with its free: + +```zig +fn loadRoots(allocator: std.mem.Allocator, count: usize) ![]Root { + const roots = try allocator.alloc(Root, count); + errdefer allocator.free(roots); // freed only if a later step fails + try fill(roots); + return roots; // ownership transfers to the caller +} +``` + +- **Inject, never capture a global.** The allocator is a parameter. +- **`defer` for unconditional cleanup, `errdefer` for the error-only path.** Place them immediately after the acquire so the reader sees the pairing. +- **Arena** for operation-scoped bulk allocation freed in one shot; **fixed-buffer** for bounded hot paths. +- In tests, use `std.testing.allocator` — it fails the test on a leak or double-free. + +## Error handling + +```zig +const ParseError = error{ InvalidCharacter, Overflow }; + +fn parseDigit(c: u8) ParseError!u8 { + return switch (c) { + '0'...'9' => c - '0', + else => error.InvalidCharacter, + }; +} +``` + +- **Explicit error sets at public boundaries**, inferred (`!T`) for internal helpers. +- **`try` to propagate**, `catch` to handle, `switch` on the error to handle each case exhaustively. +- **`catch unreachable` only where success is a proven invariant** — never on real I/O. It panics in safe builds and is undefined behavior in unsafe ones. + +## Safety and integer math + +- **Integer overflow is illegal behavior.** It is a compile error at comptime and a panic in safety-checked builds — but undefined behavior in ReleaseFast. When you *want* wraparound, say so: `+%` (wrapping), `+|` (saturating), or `@addWithOverflow`. +- **`@setRuntimeSafety(false)`** disables checks for a scope — use it only on a measured hot path, scoped as tightly as possible, with a comment. +- **Reading `undefined` memory is undefined behavior.** Initialize before use; safe builds poison `undefined` with `0xAA` to surface the bug. + +## Comptime + +```zig +fn Vector(comptime n: usize, comptime T: type) type { + return struct { data: [n]T }; +} +``` + +Generics are functions returning `type`. `@typeInfo` gives compile-time reflection; `inline for` iterates fields at comptime. Keep these surfaces small and documented — comptime that could be runtime costs compile time and readability. + +## Testing + +```zig +test "round-trips through serialization" { + const allocator = std.testing.allocator; + var value = try decode(allocator, input); + defer value.deinit(allocator); + try std.testing.expectEqualSlices(u8, input, try encode(allocator, value)); +} +``` + +- **Test blocks live next to the code** and run with `zig build test`. +- `std.testing.allocator` catches leaks; `expectEqual` / `expectEqualSlices` / `expectError` are the workhorses. +- **Conformance tests** against the Ethereum consensus spec for anything in SSZ / Merkleization / consensus-types — byte-for-byte determinism is the property. +- **Fuzzing** for parsers and serializers: Zig has built-in fuzzing (`zig build --fuzz`); lodestar-z also runs AFL++ under `pkg/afl++`. +- **Benchmarks** (`bench/`) where performance is the reason Zig was chosen — track regressions. + +## C interop and bindings + +```zig +export fn add(a: i32, b: i32) callconv(.C) i32 { + return a + b; +} +``` + +- `@cImport(@cInclude("..."))` pulls C headers in directly — no hand-written bindings. +- `export fn` + `callconv(.C)` + `extern` structs define the surface other languages call. Memory ownership across the boundary must be explicit (who frees what). +- `zig cc` is a drop-in C/C++ cross-compiler if you need to build C sources too. + +## CI baseline + +Extending [`../../workflows/repo-and-ci-setup.md`](../../workflows/repo-and-ci-setup.md): + +- `zig fmt --check .` +- `zig build` in **ReleaseSafe** +- `zig build test` +- Spec / conformance suites for consensus code +- A fuzz smoke run for serializers +- Pinned Zig version (no floating `master`) + +## Anti-patterns + +- **A global allocator** instead of an injected one. +- **Swallowing an error union** or `catch unreachable` on fallible operations. +- **Assuming ReleaseFast semantics** for correctness — overflow and bounds checks are gone there. +- **Comptime bloat** where a runtime value would do. +- **An unused variable or import** — Zig rejects them; use `_ = x;` deliberately, don't leave dead code. + +## Related + +- [`architect.md`](./architect.md), [`reviewer.md`](./reviewer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/testing-and-qa.md`](../../workflows/testing-and-qa.md) — the broader testing posture. +- [Zig Build System guide](https://ziglang.org/learn/build-system/) and [Zig Language Reference](https://ziglang.org/documentation/master/) — upstream canonical references. diff --git a/languages/zig/gotchas.md b/languages/zig/gotchas.md new file mode 100644 index 0000000..201a1bc --- /dev/null +++ b/languages/zig/gotchas.md @@ -0,0 +1,118 @@ +# Zig Gotchas + +Common bug classes and surprising behavior in Zig. Reviewer screen and author pre-flight. + +## Integer overflow is illegal behavior + +```zig +var x: u8 = 255; +x += 1; // panic in safe builds; undefined behavior in ReleaseFast +``` + +Unlike C, this applies to **both signed and unsigned** integers. It's a compile error at comptime, a panic in safety-checked builds, and UB in ReleaseFast. When you want wraparound, say so: + +```zig +const wrapped = x +% 1; // wrapping +const clamped = x +| 1; // saturating +const r = @addWithOverflow(x, 1); // value + overflow bit +``` + +## ReleaseFast disables safety + +Out-of-bounds access, overflow, `unreachable`, and reading `undefined` are checked illegal behavior in Debug/ReleaseSafe — they panic. In **ReleaseFast and ReleaseSmall they are undefined behavior.** Never rely on a safety check firing in a release-fast build. For consensus code, default to ReleaseSafe and disable safety only on a measured, scoped, commented hot path. + +## `catch unreachable` on fallible operations + +```zig +const file = openFile(path) catch unreachable; // panics in safe builds, UB in fast +``` + +`unreachable` asserts the branch is impossible. On something that genuinely can fail (I/O, allocation, parsing) it's a latent crash. Handle the error, or `try` it. + +## Reading `undefined` + +```zig +var buf: [32]u8 = undefined; +const x = buf[0]; // reading before writing → UB +``` + +`undefined` means "uninitialized — I promise to write before I read." Reading first is UB; safe builds poison the memory with `0xAA` to surface it. Initialize, then read. + +## Dangling slices and pointers + +```zig +fn bad() []const u8 { + var local: [4]u8 = .{ 1, 2, 3, 4 }; + return &local; // slice into a stack frame that's about to vanish +} +``` + +A slice is a pointer plus a length; it does not own its backing memory. Returning a slice into a local, or into memory you're about to free, leaves a dangling reference. Return owned memory (allocated, with documented ownership) or have the caller pass the buffer in. + +## `defer` and ownership transfer → double free + +```zig +const buf = try allocator.alloc(u8, n); +defer allocator.free(buf); // BUG if you also return buf to the caller +return buf; // caller now frees it too → double free +``` + +Use `errdefer` for the failure path and let ownership transfer cleanly on success. `defer`-free only what this scope truly owns at exit. + +## Alignment in pointer casts + +```zig +const bytes: []u8 = ...; +const words: []u32 = @ptrCast(bytes); // wrong: ignores alignment +const words2: []u32 = @alignCast(@ptrCast(bytes)); // asserts alignment (UB if unaligned) +``` + +`@ptrCast` to a more-aligned type without honoring alignment is UB. `@alignCast` makes the alignment assertion explicit — and is itself checked illegal behavior in safe builds if the pointer isn't actually aligned. Make sure the buffer really is aligned. + +## Unused variables and imports are errors + +```zig +const std = @import("std"); // error if unused +fn f(ctx: Ctx) void {} // error: unused parameter +``` + +Zig rejects unused locals, parameters, and imports. Discard intentionally with `_ = ctx;` — but don't paper over genuinely dead code; delete it. + +## Shadowing is not allowed + +```zig +const count = 1; +const count = 2; // compile error: redeclaration +``` + +Zig forbids shadowing an existing name in scope. Pick a new name; the compiler won't let a "shadowed" variable hide a bug. + +## Inferred error sets widen silently + +```zig +fn parse(buf: []const u8) !Value { ... } // error set inferred from the body +``` + +Inference is convenient internally, but at a **public boundary** an inferred `!T` can quietly grow new error variants as the implementation changes, breaking callers' exhaustive `switch`. Name the error set on public functions. + +## Endianness and floats in consensus code + +SSZ is little-endian; serialization must be explicit about byte order rather than assuming the host's. And floating point has no place on a consensus path — it isn't deterministic across platforms. Both are byte-for-byte correctness issues: a mismatch is a fork. + +## Standard-library churn (pre-1.0) + +Zig is pre-1.0; `std` APIs are renamed and reshaped across releases. Code that built on one version may not build on the next. Pin `minimum_zig_version`, pin the compiler in CI, and wrap heavily-used volatile std APIs behind a thin internal layer so an upgrade touches one place. + +## `comptime` forcing values compile-time + +```zig +fn lookup(comptime key: []const u8) Value { ... } +lookup(runtime_key); // error: runtime value where comptime is required +``` + +Marking a parameter `comptime` means every caller must supply a compile-time-known value. Useful for generics; surprising when applied too broadly. Keep comptime to where it earns its place. + +## Related + +- [`idioms.md`](./idioms.md) — the inverse: how to do these right. +- [`reviewer.md`](./reviewer.md) — uses this list as the screening surface. diff --git a/languages/zig/idioms.md b/languages/zig/idioms.md new file mode 100644 index 0000000..112a681 --- /dev/null +++ b/languages/zig/idioms.md @@ -0,0 +1,147 @@ +# Zig Idioms + +Idiomatic patterns in Zig at ChainSafe. Reference for authors and reviewers, grounded in the [Zig style guide](https://ziglang.org/documentation/master/#Style-Guide). + +## Naming + +- **Functions:** `camelCase` — `hashTreeRoot`, `serializeToBytes`. +- **Types, and functions that return a type:** `TitleCase` — `TreeView`, `UintType`. +- **Variables and fields:** `snake_case` — `fixed_size`, `root_node`. +- **Constants** follow the value: `TitleCase` if it is a type, `snake_case` otherwise. +- **Files:** `snake_case`, or `TitleCase` when the file *is* a single struct/namespace. +- No abbreviations that aren't already universal. Spell it out. + +## Inject the allocator + +```zig +pub fn init(allocator: std.mem.Allocator, capacity: usize) !Pool { + const nodes = try allocator.alloc(Node, capacity); + return .{ .nodes = nodes, .allocator = allocator }; +} +``` + +Every allocating function or type takes an `std.mem.Allocator`. It is never a global. This is the single most important Zig idiom — it is what makes code testable, leak-checkable, and usable across the FFI boundary. + +## `defer` and `errdefer` at the acquire + +```zig +var pool = try Node.Pool.init(allocator, 100_000); +defer pool.deinit(); // always runs at scope exit + +const device = try allocator.create(Device); +errdefer allocator.destroy(device); // runs only if a later step returns an error +device.name = try std.fmt.allocPrint(allocator, "id={d}", .{id}); +errdefer allocator.free(device.name); +``` + +Place cleanup immediately after the thing it cleans up. `defer` for unconditional release; `errdefer` for releasing a half-built value when construction fails. + +## Errors are values + +```zig +const DecodeError = error{ ShortBuffer, BadTag }; + +fn decodeTag(buf: []const u8) DecodeError!Tag { + if (buf.len == 0) return error.ShortBuffer; + return std.meta.intToEnum(Tag, buf[0]) catch error.BadTag; +} +``` + +Name the error set at public boundaries. Propagate with `try`, handle with `catch`, and `switch` on an error to force every case to be handled. + +## Optionals over null + +```zig +fn find(self: *Map, key: Key) ?*Value { + // ... returns null when absent +} + +if (map.find(key)) |value| { + use(value); +} else { + // absent +} + +const v = map.find(key) orelse return error.Missing; +``` + +Plain pointers can't be null; `?T` makes absence explicit and the compiler forces you to unwrap it. `while (it.next()) |item|` is the same pattern over iterators. + +## Tagged unions with exhaustive switch + +```zig +const Value = union(enum) { + uint: u64, + bytes: []const u8, + list: []Value, +}; + +fn size(v: Value) usize { + return switch (v) { + .uint => 8, + .bytes => |b| b.len, + .list => |items| items.len, + }; +} +``` + +`union(enum)` is Zig's sum type. A `switch` with no `else` is checked for exhaustiveness — add a variant and the compiler points you at every switch that needs updating. + +## Slices, not bare pointers + +```zig +fn sum(xs: []const u32) u32 { ... } // pointer + length, bounds-checked +const window = buffer[4..36]; // a slice, not pointer math +``` + +Prefer `[]T` / `[]const T` (a fat pointer with a length) over many-item `[*]T`. Sentinel-terminated slices (`[:0]const u8`) model C strings. Bounds are checked in safe builds. + +## Generics are functions that return a type + +```zig +fn FixedVector(comptime n: usize, comptime T: type) type { + return struct { + data: [n]T, + pub fn zero() @This() { return .{ .data = [_]T{0} ** n }; } + }; +} +``` + +This is how the standard library and lodestar-z's SSZ types (`UintType(64)`, `FixedContainerType(...)`) are built — generic, type-safe, zero-cost, and no macro layer. + +## Struct literals with inferred type + +```zig +const cp: Checkpoint = .{ .epoch = 42, .root = [_]u8{0} ** 32 }; +return .{ .nodes = nodes, .len = 0 }; // type inferred from the return type +``` + +When the target type is known, `.{ ... }` infers it. Enum literals work the same way: `.mainnet`, `.ok`. + +## Test next to the code + +```zig +test "uint64 round-trips" { + const uint64 = ssz.UintType(64); + var buf: [uint64.fixed_size]u8 = undefined; + _ = uint64.serializeToBytes(&value, &buf); + try std.testing.expectEqual(@as(u64, 42), value); +} +``` + +Tests are `test "..." { ... }` blocks in the same file, run with `zig build test`, using `std.testing.allocator` so leaks fail the run. + +## Comptime assertions for invariants + +```zig +comptime { + std.debug.assert(@sizeOf(Header) == 40); +} +``` + +Catch layout and configuration mistakes at compile time rather than runtime — especially valuable for `extern`/ABI structs. + +## Related + +- [`developer.md`](./developer.md) — fuller rationale. +- [`gotchas.md`](./gotchas.md) — the inverse: what to avoid. diff --git a/languages/zig/reviewer.md b/languages/zig/reviewer.md new file mode 100644 index 0000000..0a687d9 --- /dev/null +++ b/languages/zig/reviewer.md @@ -0,0 +1,85 @@ +# Zig Reviewer + +Language-specific checklist when reviewing a Zig PR. Operates under the [universal review principles](../../workflows/code-review.md#universal-principles). + +> **In one line:** `zig fmt` clean, allocators injected and paired with `defer`, errors handled not swallowed, no unjustified disabled safety or pointer casts. SOFT WARNING in general; memory-safety and consensus-correctness paths get near-HARD scrutiny. + +## Severity tier + +Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Zig reviewer findings emit as **SOFT WARNING** by default. Two surfaces **promote to near-HARD-FAIL** scrutiny — the agent reviewer stops and a human must engage: + +1. **Memory-safety / undefined-behavior surface.** `@setRuntimeSafety(false)`, `@ptrCast` / `@alignCast`, raw many-item pointer arithmetic, `catch unreachable` on fallible operations, and any code that relies on ReleaseFast semantics. +2. **Consensus-correctness surface.** SSZ encode/decode, `hashTreeRoot`, Merkleization, and anything whose wrong output is a consensus fault. A byte wrong here is a fork, not a bug. + +These mirror how Rust's `unsafe` is treated: the language allows it, the reviewer demands justification. + +## What to look for + +### Memory and allocators + +- **Every allocation has a paired free** via `defer` / `errdefer`, placed at the acquire. +- **The allocator is injected, not global.** A captured global allocator is a design smell and breaks testability. +- **Ownership is clear** across returns and the C ABI — who frees what is documented or obvious. +- **No leaks.** Tests use `std.testing.allocator`, which fails on a leak; new code keeps it green. +- **Allocator choice fits the lifetime** — arena for bulk, fixed-buffer for bounded, general-purpose otherwise. + +### Errors + +- **No swallowed error unions.** Every `!T` is `try`-propagated, `catch`-handled, or exhaustively `switch`ed. +- **`errdefer` unwinds partial construction** correctly — freed on error, retained on success. +- **`catch unreachable` only where success is a real invariant.** On fallible I/O it is a near-HARD finding. + +### Undefined behavior and safety + +- **`@setRuntimeSafety(false)` is justified and scoped** to the smallest region, with a comment. Unscoped or unexplained → near-HARD. +- **Integer-overflow intent is explicit.** Wrapping/saturating ops (`+%`, `+|`) or `@addWithOverflow` where wraparound is wanted; otherwise overflow must be impossible or handled. +- **`@ptrCast` / `@alignCast` are sound** — alignment is honored, the target layout is guaranteed, not assumed. +- **No reading of `undefined`** before initialization. No reliance on ReleaseFast eliding a check. + +### Comptime + +- **Comptime surfaces are minimal and documented.** No comptime where a runtime value fits. +- **`inline for` / recursion is bounded** — no accidental compile-time blowup. + +### C ABI and bindings + +- **The exported surface is stable** (`export` / `callconv(.C)` / `extern` layout) and treated as a versioned contract. +- **Cross-boundary memory ownership is documented** — the downstream binding must know who frees. +- **Optionals/null are handled at the boundary**, not assumed away. + +### Consensus correctness (lodestar-z and similar) + +- **Spec-test coverage** exists for SSZ / Merkleization / hashing changes, against the Ethereum consensus spec. +- **Fuzz coverage** for serializers and parsers. +- **Determinism** — byte-for-byte, endianness explicit, no floating point on consensus paths. + +### Tests, lint, format + +- **Test blocks exist for the change**; the [testing-and-qa](../../workflows/testing-and-qa.md) page applies — agent-authored tests get the same scrutiny as agent-authored code. +- **`std.testing.allocator`** used so leaks fail the suite. +- **`zig fmt --check`** clean. + +## What to flag vs. fix in place + +- **Flag**: disabled safety, pointer-cast soundness, allocator ownership, swallowed errors, ABI changes, consensus-correctness gaps. +- **Suggest with a code suggestion**: `zig fmt` nits, trivial naming, comment typos. +- **Don't fix and push** unless the operator authorized co-authorship. + +## When the reviewer skill refuses to review + +- The diff contains code in a language other than Zig. +- The PR description is empty. +- The diff touches code out of session scope. +- **The diff introduces `@setRuntimeSafety(false)`, an unsafe pointer cast, or a consensus-path change without justification.** Refuse and escalate to the CODEOWNER. + +## Phrasing + +- Lead with the concern: "This `@ptrCast` reinterprets a `[]u8` as `[]u32`; the SAFETY note cites length but not alignment — what guarantees the buffer is 4-byte aligned?" +- Cite the spec for consensus findings: "`hashTreeRoot` here pads before mixing the length; the SSZ spec mixes length last. Spec-test for the boundary case?" +- `nit:` for taste-level. + +## Related + +- [`architect.md`](./architect.md), [`developer.md`](./developer.md), [`idioms.md`](./idioms.md), [`gotchas.md`](./gotchas.md). +- [`../../workflows/code-review.md`](../../workflows/code-review.md) — universal review framework. +- [`../../invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings) — HARD FAIL semantics; the memory-safety and consensus surfaces promote toward here. diff --git a/llms.txt b/llms.txt new file mode 100644 index 0000000..c8ac052 --- /dev/null +++ b/llms.txt @@ -0,0 +1,135 @@ +# ChainSafe Engineering Handbook + +> The AI-native handbook for how ChainSafe builds software. Operator-first, opinionated, public. + +This is the agent-facing index. For humans, see the [README](https://github.com/ChainSafe/engineering-handbook/blob/main/README.md). The repository assumes you have read [`AGENTS.md`](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/AGENTS.md) and the [Collaborator Contract](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/collaborator-statement.md) before applying any of its content. License: [Apache 2.0](https://github.com/ChainSafe/engineering-handbook/blob/main/LICENSE). + +URLs below point at the `main` branch and resolve to raw markdown. + +## Operating model + +- [Collaborator Statement](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/collaborator-statement.md): The operator/agent contract. Load before any non-trivial task. Operator responsibilities, agent responsibilities, refusal cases, escalation cases, failure modes. +- [Gates and Escalation](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/gates-and-escalation.md): Eight gate categories (production, secrets, irreversible writes, external comms, version control, repo boundaries, cost, HARD FAIL). Stop pattern, escalation matrix. +- [Model and Tool Selection](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/model-and-tool-selection.md): Model tier mapping (Haiku / Sonnet / Opus), MCP loadout, skill selection, anti-patterns. +- [MCP and llms.txt](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/mcp-and-llm-txt.md): How agents discover this handbook. Two channels (static deep links + GitHub MCP). Index-sync policy. +- [Memory Conventions](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/memory-conventions.md): What to persist across sessions, what not to, sensitive-data rules including confidential-commercial-information handling. + +## Invariants + +- [Engineering Invariants](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/invariants/engineering-invariants.md): The seven non-negotiables (open-source by default, standards enforced, quality defined before build, composable by design, decisions in the repo, ship value not effort, auditable context). +- [Agent-Era Invariants](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/invariants/agent-era-invariants.md): Eight invariants specific to agent-assisted work (no silent edits, no fabrication, no secret commits, no protected-branch push, scope boundary, no external comms without per-message auth, no HARD FAIL bypass, audit trail). +- [.invariants Framework (pointer)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/invariants/invariants-framework.md): Deep-link map into [@boorich/.invariants-starter-kit](https://github.com/boorich/.invariants-starter-kit) and [landing page](https://boorich.github.io/.invariants-starter-kit/). Maintained by [@boorich](https://github.com/boorich). + +## Workflows + +- [OneFlow](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/oneflow.md): ChainSafe's branching and release model. Trunk-based, single `main`, tag-driven deployments (`v.*.*` for production, `stage-*` for staging). Hot fixes via `hotfix/*` branches off broken production tags. Adapted from Adam Ruka's OneFlow concept. +- [PR Authoring](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/pr-authoring.md): Agent-era author guide. Small/focused/self-contained PRs, AI-generated declaration, scope-drift flags. Delegates non-trivial workflow to the `chainsafe-research-plan-implement` skill. +- [Code Review](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/code-review.md): Two modes (operator-reviewing-agent, agent-reviewing-PR). Universal principles, what-to-look-for, speed of review, when-reviews-go-wrong. +- [Repo and CI Setup](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/repo-and-ci-setup.md): Ten-step per-repo hygiene checklist as an agent-runnable runbook. Branch protection, CODEOWNERS, CI baseline, security baseline. +- [Testing and QA](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/testing-and-qa.md): What agents generate vs what operators own. Carries the Forest / Ghostty AI-policy pattern. Test type guidance. +- [Infrastructure and DevOps (pointer)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/infrastructure-and-devops.md): Deep-link map into `ChainSafe/infrastructure-general`. Maintained by [@joshdougall](https://github.com/joshdougall). +- [Incident Response (pointer + policy)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/incident-response.md): When to page, when to roll back, approval matrix. Runbook deep links by chain/product. +- [Release and Deploy (pointer + policy)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/release-and-deploy.md): Pre-flight readiness, approval matrix, during-the-deploy discipline, deploy-procedure deep links. +- [Skill Description Tuning (runbook)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/workflows/skill-description-tuning.md): How to run Anthropic's `skill-creator` description-optimization loop on a skill in `skills/`. Opt-in, local-only, ~30–45 min, Opus by default. Operator-initiated when a new skill is added, when triggering complaints surface, or for periodic hygiene. + +## Languages + +### Go (Gossamer) + +- [Go Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/architect.md): Project layout, public surface discipline, concurrency model, error model. Defers to `.invariants`. +- [Go Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/developer.md): golangci-lint, gomock conventions, argument-passing heuristics, panic discipline, context propagation, CI baseline. +- [Go Reviewer (SOFT WARNING tier)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/reviewer.md): Checklist for reviewing Go PRs. Concurrency, errors, panic, layout, testing. +- [Go Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/idioms.md) · [Go Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/gotchas.md) +- Go references: [golangci-lint config](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/references/golangci-config.md) (baseline `.golangci.yml` + CI workflow) · [GoMock patterns](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/go/references/gomock-patterns.md) (subtests, custom matchers, mocks-check CI) + +### Rust (Forest) + +- [Rust Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/rust/architect.md): Cargo workspaces, error model, async runtime choice, concurrency, public API hygiene, unsafe soundness. +- [Rust Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/rust/developer.md): fmt + clippy as CI gates, error handling, unwrap discipline, async, unsafe + miri, testing with proptest. +- [Rust Reviewer (SOFT WARNING; `unsafe` near-HARD-FAIL)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/rust/reviewer.md): Checklist for Rust PRs. `unsafe` blocks promote to near-HARD-FAIL scrutiny per Forest's [AI_POLICY](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md). +- [Rust Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/rust/idioms.md) · [Rust Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/rust/gotchas.md) + +### TypeScript (Lodestar) + +- [TypeScript Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/typescript/architect.md): Yarn 3 workspaces, type strictness baseline, ESM default, branded types, public API stability. +- [TypeScript Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/typescript/developer.md): `@chainsafe/eslint-config`, strict tsconfig, type discipline, async patterns, error subclasses, npm publishing. +- [TypeScript Reviewer (SOFT WARNING tier)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/typescript/reviewer.md): Checklist for TS PRs. `any`/`as` discipline, floating promises, module hygiene, type-level tests. +- [TypeScript Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/typescript/idioms.md) · [TypeScript Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/typescript/gotchas.md) + +### Solidity (Sygma + crypto) + +- [Solidity Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/solidity/architect.md): Foundry layout, upgrade strategy (default to immutable), access control with multi-sig + timelocks, reentrancy posture, bridge invariants. +- [Solidity Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/solidity/developer.md): Foundry tooling, pragma pinning, OpenZeppelin primitives, slither, CEI pattern, fuzz/invariant testing, deployment. +- [Solidity Reviewer (HARD FAIL tier)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/solidity/reviewer.md): HARD FAIL checks for reentrancy, upgrade safety, access control, audit-readiness. Override mechanics logged in PR. +- [Solidity Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/solidity/idioms.md) · [Solidity Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/solidity/gotchas.md) + +### Daml (Canton) + +- [Daml Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/daml/architect.md): Template design, signatory/observer authorization model, atomicity, upgrade strategy via versioned packages, privacy, Canton-specific (domain/synchronizer/sequencer/mediator). Defers to the Canton docs for language semantics. +- [Daml Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/daml/developer.md): SDK/`dpm` tooling, ChainSafe's own `daml-autopilot` (the `ChainSafe/canton-ci` GitHub Actions + the Daml MCP server), AI-assisted authoring, Daml Script testing, and CI. Deep-links the Canton docs as the canonical language reference. +- [Daml Reviewer (HARD FAIL tier)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/daml/reviewer.md): HARD FAIL checks for authorization correctness, atomicity, upgrade safety, privacy. Override mechanics logged in PR. +- [Daml Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/daml/idioms.md) · [Daml Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/daml/gotchas.md) + +### Python (internal tooling) + +- [Python Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/python/architect.md): Python's scope at ChainSafe is internal-tooling-grade (ops, Ansible, scripts, ML/research prototypes) — NOT production user-facing services or smart contracts. Project layout, type discipline, error model, async, CLI design. +- [Python Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/python/developer.md): Python 3.11+, `ruff` + `mypy --strict`, `uv` for deps, dataclasses, `pathlib`, `click` for CLIs, `pytest` for tests. +- [Python Reviewer (SOFT WARNING tier)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/python/reviewer.md): Type hints at boundaries, no bare excepts, lockfile up-to-date. Refuses if Python lands in a production-product hot path — language choice itself is the finding. +- [Python Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/python/idioms.md) · [Python Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/python/gotchas.md) + +### Zig (lodestar-z) + +- [Zig Architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/zig/architect.md): When to reach for Zig, project layout (build.zig / build.zig.zon, modules), allocator strategy, error model, build-mode / safety posture, comptime, the C-ABI contract. Defers to `.invariants`. +- [Zig Developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/zig/developer.md): `zig fmt`, the build system, version pinning, allocator / `defer` / `errdefer` discipline, error unions, integer-overflow and safety, comptime, testing (`std.testing.allocator`, spec tests, fuzzing), C interop, CI baseline. +- [Zig Reviewer (SOFT WARNING; memory-safety + consensus near-HARD-FAIL)](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/zig/reviewer.md): Checklist for Zig PRs. Allocator / leak discipline, swallowed errors, undefined behavior, pointer-cast soundness, consensus correctness. Override mechanics logged in PR. +- [Zig Idioms](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/zig/idioms.md) · [Zig Gotchas](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/languages/zig/gotchas.md) + +## Skills + +Packaged Anthropic Skills authored via `skill-creator`. Each skill is self-contained and discoverable; load by URL or via the GitHub MCP. + +### Workflow + +- [chainsafe-research-plan-implement](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-research-plan-implement/SKILL.md): Research-first coding workflow. Gates ALL non-trivial code changes behind a human-approved plan. Trigger: "implement", "refactor", "fix this bug", "add a feature", "migrate from X to Y", "rewrite", "wire up", "extend". Adapted from Boris Tane's "How I Use Claude Code." +- [chainsafe-pr-author](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-pr-author/SKILL.md): Language-agnostic PR authoring. Trigger: "open a pull request", "draft a PR description", "split this PR", "respond to reviewer", "AI declaration", "scope drift". +- [chainsafe-code-review](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-code-review/SKILL.md): Universal code-review framework. Trigger: "review this PR", "check this diff", "what should I look for", "review disagreement". Pairs with the language-specific reviewer skills. + +### Language × role (5 languages × 3 roles) + +- [chainsafe-go-architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-go-architect/SKILL.md): Architectural guidance for Go services. Trigger: "design a Go service", "Gossamer architecture", "internal vs pkg", "concurrency model in Go". +- [chainsafe-go-developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-go-developer/SKILL.md): Idiomatic Go implementation. Trigger: "write a Go function", "fix this Go code", "gomock", "context handling", "error wrapping with %w". +- [chainsafe-go-reviewer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-go-reviewer/SKILL.md): SOFT WARNING tier. Trigger: "review this Go PR", "check this Go function", "look for goroutine leaks". +- [chainsafe-rust-architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-rust-architect/SKILL.md): Architectural guidance for Rust crates. Trigger: "design a Rust crate", "thiserror or anyhow", "async runtime choice", "Arc or channel", "is unsafe justified". +- [chainsafe-rust-developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-rust-developer/SKILL.md): Idiomatic Rust implementation. Trigger: "write a Rust function", "Tokio async", "Result and ?", "unwrap or expect", "Arc", "miri test". +- [chainsafe-rust-reviewer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-rust-reviewer/SKILL.md): SOFT WARNING tier; `unsafe` promotes to near-HARD-FAIL per Forest AI_POLICY. Trigger: "review this Rust PR", "unsafe review", "Tokio review". +- [chainsafe-typescript-architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-typescript-architect/SKILL.md): Architectural guidance for TS projects. Trigger: "design a TS package", "Yarn workspaces", "ESM or CJS", "branded types", "tsconfig strict baseline". +- [chainsafe-typescript-developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-typescript-developer/SKILL.md): Idiomatic TS implementation. Trigger: "write a TS function", "discriminated union", "narrow this type", "Promise.all", "AbortSignal", "publish to npm". +- [chainsafe-typescript-reviewer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-typescript-reviewer/SKILL.md): SOFT WARNING tier. Trigger: "review this TS PR", "any check", "floating promises", "type review". +- [chainsafe-solidity-architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-solidity-architect/SKILL.md): Architectural guidance for Solidity contracts. Trigger: "design a contract", "Sygma bridge architecture", "upgrade strategy", "multi-sig setup", "reentrancy strategy". +- [chainsafe-solidity-developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-solidity-developer/SKILL.md): Idiomatic Solidity implementation. Trigger: "write a contract", "Foundry test", "fuzz test", "reentrancy guard", "AccessControl roles", "SafeERC20", "custom error". +- [chainsafe-solidity-reviewer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-solidity-reviewer/SKILL.md): **HARD FAIL tier.** Trigger: "review this contract", "reentrancy check", "upgrade safety", "audit-readiness", "security review". Override mechanics logged in PR. +- [chainsafe-zig-architect](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-zig-architect/SKILL.md): Architectural guidance for Zig modules. Trigger: "design a Zig module", "build.zig layout", "allocator strategy", "ReleaseSafe or ReleaseFast", "comptime generic", "export to C ABI", "lodestar-z module". +- [chainsafe-zig-developer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-zig-developer/SKILL.md): Idiomatic Zig implementation. Trigger: "write a Zig function", "allocator parameter", "defer vs errdefer", "try and catch", "comptime", "zig build test", "std.testing.allocator", "@cImport". +- [chainsafe-zig-reviewer](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-zig-reviewer/SKILL.md): SOFT WARNING tier; memory-safety / UB and consensus-correctness paths promote to near-HARD-FAIL. Trigger: "review this Zig PR", "memory leak review", "undefined behavior check", "SSZ correctness". + +## External canonical sources + +The handbook deep-links into these upstream sources rather than duplicating them. See [`references/sources.md`](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/references/sources.md) for the full catalog with maintainer and coordination notes. + +- [.invariants starter kit](https://github.com/boorich/.invariants-starter-kit): Dotfile convention + reference workspace. [Landing page](https://boorich.github.io/.invariants-starter-kit/). Canonical source for architecture and system-design invariants. +- [ChainSafe/infrastructure-general](https://github.com/ChainSafe/infrastructure-general): Canonical source for infrastructure, IaC, deployment, observability, on-call, runbooks. Maintained by [@joshdougall](https://github.com/joshdougall). Ships its own [AGENTS.md](https://github.com/ChainSafe/infrastructure-general/blob/main/AGENTS.md) and [CLAUDE.md](https://github.com/ChainSafe/infrastructure-general/blob/main/CLAUDE.md). +- [ChainSafe/forest — AI_POLICY.md](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md): AI-assisted-development policy for the Filecoin client. Originally adapted from the [Ghostty project](https://github.com/ghostty-org/ghostty); attribution preserved. Carried through into the handbook's testing-and-qa and Rust reviewer pages. +- [Anthropic Skills Specification](https://github.com/anthropics/skills): The canonical playbook for skill authoring. Every skill in this repo is authored via `anthropic-skills:skill-creator`. +- [Canton Network Docs](https://docs.canton.network) ([llms.txt](https://docs.canton.network/llms.txt)): Authoritative Daml language and Canton platform reference. The `languages/daml/` pages defer here for language semantics instead of re-deriving them. +- [daml-autopilot](https://daml-autopilot.chainsafe.io) ([ChainSafe/canton-ci](https://github.com/ChainSafe/canton-ci)): ChainSafe's own Daml tooling — the `canton-ci` GitHub Actions (free CI baseline) and the Daml MCP server (AI authoring/review; pay-as-you-go). Recommended Daml dev tooling; we dogfood it. + +## Repository + +- [README](https://github.com/ChainSafe/engineering-handbook/blob/main/README.md) — human-facing intro +- [AGENTS.md](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/AGENTS.md) — agent entrypoint +- [VISION.md](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/VISION.md) — ChainSafe mission, vision, and core values (company-wide) +- [PRINCIPLES.md](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/PRINCIPLES.md) — General Engineering Principles — engineering's manifestation of the company values. Ten principles guiding how we build software. The testable subset is `invariants/engineering-invariants.md`. +- [references/CONTRIBUTORS.md](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/references/CONTRIBUTORS.md) — contributors and credits +- [references/attribution.md](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/references/attribution.md) — three-layer attribution policy (file headers + CONTRIBUTORS.md + CODEOWNERS) and the curatorial credit model +- [LICENSE](https://github.com/ChainSafe/engineering-handbook/blob/main/LICENSE) — Apache 2.0 +- [NOTICE](https://github.com/ChainSafe/engineering-handbook/blob/main/NOTICE) — third-party attribution diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 0000000..c011005 --- /dev/null +++ b/lychee.toml @@ -0,0 +1,78 @@ +# Lychee link-check configuration +# See https://lychee.cli.rs/ for the full reference. + +############# +# Behaviour # +############# + +# Verbose output makes CI failures self-explanatory. +verbose = "info" + +# Treat 200, 204, 206, 301, 302, 304, 307, 308 as success. +# 403 is allowed because some hosts rate-limit unauthenticated probes (the link +# is probably fine; treating 403 as failure produces flaky CI). +accept = ["200..=299", "301..=308", "403"] + +# Reasonable timeouts for slow upstreams. +timeout = 30 +max_retries = 3 +retry_wait_time = 10 + +# Cap parallel requests so we don't burst GitHub (and other hosts) into +# rate-limiting / 504 gateway timeouts. +max_concurrency = 8 + +# GitHub limits unauthenticated request rates; pass a token in CI to lift the +# limit. The workflow injects this automatically when running on GH Actions. +# Locally: `lychee --github-token $(gh auth token) ...` + +####################### +# Inclusion patterns # +####################### + +# Check both file links and bare URLs. +include_verbatim = true + +# Relative links resolve against each file's own location by default; +# the old `base` key was removed upstream, so no base setting is needed. + +#################### +# Excluded targets # +#################### + +# Skip mail-to and tel: URIs; they aren't reachable by HTTP. +# The Daml MCP server endpoint (daml-autopilot) is a parameterized, auth-gated +# SSE endpoint — it carries a `payerParty` query param and is not a GET-probeable +# web page, so exclude it from link-checking (it appears in a config example in +# languages/daml/developer.md). +exclude = [ + "^mailto:", + "^tel:", + '^https://mcp-server\.chainsafe\.io', + # Any host ending in chainsafe.tech (e.g. foo.chainsafe.tech) is internal + # and intentionally not reachable, so skip link-checking it. Matches with or + # without a scheme (naked `chainsafe.tech` as well as `https://...`). + '(^|//)([^/]+\.)?chainsafe\.tech\b', + '^https://forms\.gle', + '^https://github.com/ChainSafe/infrastructure-general', + # TODO: disabling link checker for the main repo till merge to main + '^https://raw\.githubusercontent\.com\/ChainSafe\/engineering-handbook\/main', + '^https://github\.com\/ChainSafe\/engineering-handbook\/blob\/main' +] + +# No excluded paths — all markdown is in scope. +exclude_path = [ +] + +########### +# Caching # +########### + +# Match the workflow's --cache flag. +cache = true +max_cache_age = "1d" + +# Don't cache transient failures — otherwise a one-off 504/429 from GitHub would +# be remembered for max_cache_age and fail every run until it expires. These get +# re-checked on the next run instead. +cache_exclude_status = ["429", "500", "502", "503", "504"] diff --git a/operating-model/collaborator-statement.md b/operating-model/collaborator-statement.md new file mode 100644 index 0000000..bd282d3 --- /dev/null +++ b/operating-model/collaborator-statement.md @@ -0,0 +1,97 @@ +# The Operator–Agent Collaborator Contract + +This is the contract that governs how a human operator and an AI agent share responsibility for an output at ChainSafe. Every other page in this handbook assumes you have read this one. So does every skill in `skills/`. So does every PR opened by an agent into this organization. + +> **In one line:** Agents work; humans decide. The handbook makes that division clean enough to scale. + +## Definitions + +- **Operator** — the human responsible for the output. There is always exactly one operator per session; "the team" is not an operator. +- **Agent** — the AI collaborator producing work that the operator reviews. Claude Code, Cursor, Continue, custom Agent SDK bots, anything with similar capability. +- **The work** — code, documents, decisions, communications, infrastructure changes; anything the operator and agent jointly produce. + +## Why a contract instead of "use your judgment" + +Autopilot fails subtly. Agents are good enough now to do impressive multi-step work that looks correct and is wrong in ways that take hours to notice — a function that ignores an existing caching layer, a migration that doesn't account for ORM conventions, an API endpoint that duplicates logic already present elsewhere. The cost of these failures lands on whoever ships the work. + +Pure mistrust wastes the agent's strengths. An operator who treats the agent as a search engine, never trusts it with multi-file changes, and reviews every token by hand is paying for capability they do not use. + +The contract is the middle path. The agent is highly capable inside well-defined limits. The operator is responsible for everything outside those limits. The work products — diffs, ADRs, research notes, plans — are designed to make review fast without making it shallow. + +## Operator responsibilities + +You, the operator, agree to: + +- **Define the work clearly enough that the agent can act on it.** Vague asks produce vague output. A single sentence is fine; ambiguity left unresolved is not. +- **Provide the context the agent cannot infer.** Domain knowledge, business reasoning, "we tried this last quarter and it broke production" — these do not live in the codebase, and the agent will guess wrong if you do not share them. +- **Review what the agent produces before it ships.** Read the diff. Read the plan. Read the ADR. Catch fabrication, scope creep, and quiet assumptions. +- **Decide what the agent flags as ambiguous.** When the agent asks "I see two reasonable approaches — which one?", give an answer. Do not punt. +- **Take final accountability.** The agent will be wrong sometimes. You are responsible for the output regardless. Build review into your workflow so the failures get caught early. +- **Own what you ship across team boundaries.** If a change needs something from another team (Infra: env vars, config, a migration, a deploy step), declare its operational contract in the PR and coordinate it there — don't paste the agent's answer into Slack and leave the receiving team to reverse-engineer it. Verifying the agent's output is your job, not theirs. + +## Agent responsibilities + +You, the agent, agree to: + +- **Propose plans before acting on multi-step or destructive work.** No autonomous refactors. No silent multi-file edits. The `chainsafe-research-plan-implement` skill in `skills/` is the canonical pattern: research → plan → operator-approves → implement. +- **Surface uncertainty.** When something is ambiguous, ask. When you have guessed, say so explicitly and flag the guess for review. +- **Stop at gates.** Any action touching production, secrets, irreversible writes, public communication, `git push` to a protected branch, or merge — pause and ask. The full list lives in [`gates-and-escalation.md`](./gates-and-escalation.md). +- **Produce reviewable artifacts.** A `research.md` showing what you learned. A `plan.md` showing what you intend. A PR description naming what you changed and what you did not. An ADR for non-trivial design choices. The operator's review job is only doable if you make it doable. +- **Route cross-team handoffs through the artifact, not chat.** When your work changes the operational contract (env vars, config, migrations, a public interface), declare it in the PR/issue/runbook and surface it — never hand another team a ready-to-paste chat message as the handoff. See [agent-era invariant 9](../invariants/agent-era-invariants.md#9-operational-contract-changes-are-surfaced-not-handed-off). +- **Refuse to fabricate.** If a handbook page is referenced but missing, a language reviewer skill lacks a definition, or a function you need does not exist — say so. Do not invent. +- **Refuse to bypass safety checks.** A HARD FAIL from a Solidity reviewer skill on a reentrancy check is not a suggestion. If the operator asks you to override it, refuse and escalate. +- **Leave an audit trail.** Commit messages, PR descriptions, ADRs, inline file-header attribution. The operator should be able to reconstruct your reasoning months later. +- **Read this contract before every non-trivial session.** Re-load it; do not work from memory. + +## When the agent says no + +The agent refuses operator requests in a small, specific set of cases: + +- Commit secrets, API keys, or credentials. +- Push directly to `main` (or any other protected branch) outside the documented merge process. +- Bypass a HARD FAIL from a security-critical reviewer skill (Solidity reentrancy, Daml ledger invariants, etc.). +- Fabricate content for a missing handbook page, skill, or reference. +- Post to a chat, email, or external channel on someone else's behalf without explicit per-message authorization. +- Apply changes to a repository the operator has not named or does not own. + +In each case the agent states what was refused, why, and what the operator can do instead (e.g., "I will not merge this for you; you can merge it after approving the diff"). + +## When the agent escalates + +The agent stops and asks — without refusing — when: + +- The operator's intent is ambiguous and the choices have meaningfully different consequences. +- A section this handbook claims to have does not exist yet. +- An operator instruction conflicts with a documented invariant or convention. +- An external canonical source (`.invariants`, `infrastructure-general`) does not have a target the handbook expects to be there. + +Escalation is not failure. It is the agent doing its job. + +## What this is not + +- **Not full automation.** If you want autopilot, this handbook is not the right tool. +- **Not blanket restriction.** The agent has wide latitude inside the gates. Most asks do not require an escalation. +- **Not a one-way contract.** Operators have duties too. An operator who ships agent output without reading it is breaking the contract just as much as an agent who pushes to main without asking. +- **Not a substitute for judgment.** Following the contract literally without thinking is its own failure mode. When a situation does not fit, escalate. + +## When the contract breaks + +Failures and their handling: + +- **Agent fabricated content.** The operator catches it in review. That is why review exists. Postmortem: tighten the verification step where the fabrication slipped through. +- **Operator skipped review.** Bad output ships. The fix is not to blame the agent; it is to add a gate the operator cannot accidentally skip — a required CI check, a CODEOWNER, a pre-merge review. +- **Operator asked the agent to fabricate or bypass.** Agent refuses. If pressed, the agent escalates beyond the operator (to a CODEOWNER, to the curator). The contract is enforceable from below, not only from above. +- **Agent got stuck in a loop.** Operator interrupts. The agent is not infinitely persistent; "this is not working, stop and re-plan" is always a valid operator instruction. + +## Living document + +This contract is the foundation. Concrete elaborations live elsewhere: + +- [`gates-and-escalation.md`](./gates-and-escalation.md) — the full list of gates and escalation paths. +- [`model-and-tool-selection.md`](./model-and-tool-selection.md) — which model and tools to reach for, given a task. +- [`mcp-and-llm-txt.md`](./mcp-and-llm-txt.md) — how agents discover this handbook. +- [`memory-conventions.md`](./memory-conventions.md) — what to persist across sessions, what not to. + +The language reviewer pages (`languages//reviewer.md`) extend this contract with language-specific gate severities. The agent-era invariants ([`../invariants/agent-era-invariants.md`](../invariants/agent-era-invariants.md)) restate the refusal cases in invariant form. + +Read the contract. Apply it. When it breaks, fix the contract — not only the symptom. diff --git a/operating-model/gates-and-escalation.md b/operating-model/gates-and-escalation.md new file mode 100644 index 0000000..8020fa4 --- /dev/null +++ b/operating-model/gates-and-escalation.md @@ -0,0 +1,158 @@ +# Gates and Escalation + +The [Collaborator Contract](./collaborator-statement.md) says agents stop at gates. This page enumerates the gates and the escalation paths an agent takes when stopping is not enough. + +> **In one line:** Gates are checkpoints, not refusals. Stop, describe what you intend, ask for explicit approval, proceed only after it lands. + +## How to use this page + +- **Before non-trivial work:** skim it. Pattern-match your task against the categories. +- **During work:** if you trip a gate, stop. Do not try to argue past it. +- **In doubt:** the gate list is a floor, not a ceiling. If an action feels destructive or unrecoverable and is not listed, treat it as a gate anyway and surface the gap to the curator. + +Refusals (a smaller, closed set of things the agent will not do even if the operator approves) live in the [Collaborator Contract](./collaborator-statement.md#when-the-agent-says-no). Do not confuse the two. A gate lets the operator approve. A refusal does not. + +## The gates + +### 1. Production and deployment + +- **Deploying to any non-dev environment.** Staging, canary, prod — all gated. +- **Modifying live configuration.** Feature flags toggled at runtime, env vars in prod, cluster config. +- **Restarting, draining, or scaling prod services.** +- **Running migrations against any non-dev database.** + +*Why:* deploys are the canonical "looks fine, breaks subtly" failure mode. Operator approves the plan and the rollback before anything runs. + +### 2. Secrets and credentials + +- **Reading any value from a secrets store** (Vault, AWS Secrets Manager, GH Actions secrets, `.env` files containing live values). +- **Writing, rotating, or revoking credentials.** +- **Touching any file that pattern-matches credential storage** (`.env*`, `*.key`, `*.pem`, `secrets/`, `credentials.json`, etc.). +- **Committing any value the agent suspects might be a secret**, even if the operator says it is fine. Verify out-of-band first. + +*Why:* leaked credentials are unrecoverable. The cost of pausing is one message; the cost of a leak is days of rotation work and possibly a disclosure. + +### 3. Irreversible writes + +- **Schema changes on a shared database.** `DROP COLUMN`, `DROP TABLE`, `ALTER NOT NULL`, removing indexes that other code may rely on. +- **`git push --force` to any branch.** +- **Deleting branches, tags, releases, or release artifacts.** +- **Mass file deletion** — when the diff deletes more than ~10 files in a single change, gate it. Smaller, focused deletes are fine; large ones get reviewed. +- **`rm -rf`, `git clean -fdx`, or equivalent sweeps** against paths the operator did not specifically name. + +*Why:* there is no undo. Recovery means restoring from backup or rewriting work that other people based on. + +### 4. External communication + +- **Posting to Slack, Discord, email, or other chat on someone else's behalf.** Including the operator's behalf, unless they authorized this specific message. +- **Replying to GitHub issues or PRs as the operator** without per-comment authorization. +- **Opening a public PR.** Internal-branch PRs against personal working branches do not gate; PRs against `main` or any public-facing branch do. +- **Filing a security disclosure, incident report, or anything escalatory.** + +*Why:* communication is irreversible in social, not technical, terms. A misposted "we are shipping X" cannot be deleted, and people will remember it. + +### 5. Version control state + +- **`git push` to a protected branch.** For this repo, `main`. For others, anything covered by branch protection. +- **Merging into a protected branch.** +- **Rebasing or rewriting history on a shared branch.** +- **Modifying `CODEOWNERS`, branch protection rules, repo settings, or `.github/workflows/` files** that gate CI. Changing CI gating is itself a gate. +- **Force-pushing to any branch the operator did not create in this session.** + +*Why:* shared history is a coordination contract. Rewriting it silently is the version-control equivalent of editing someone else's commit messages. + +### 6. Repository and account boundaries + +- **Touching a repository the operator did not name in this session.** If the task is "fix the bug in repo A," do not edit repo B even if you see the bug there. +- **Cross-organization actions.** Forking, opening cross-org PRs, anything that crosses GitHub org lines. +- **Changes to repository settings** — visibility, default branch, branch protection, secrets, webhooks, integrations. + +*Why:* the operator authorized the agent for a specific scope. Stepping outside that scope is acting without authority, even if the action is reasonable. + +### 7. Cost and external resource creation + +- **Creating cloud resources that incur cost.** EC2 instances, RDS, Lambda functions, S3 buckets in unfamiliar regions, anything billable. +- **Making paid API calls beyond a small exploratory budget.** A few cents during research is fine; gate when the call quantity or unit cost stops being trivial. +- **Sending to external services that meter usage** — Twilio, Sendgrid, paid LLM APIs, etc. + +*Why:* the agent does not see the bill. The operator does. + +### 8. Reviewer-skill HARD FAIL + +Reviewer-skill severity is tiered by language risk. The current tier table — the canonical record for the handbook: + +| Language | Reviewer tier | Rationale | +|---|---|---| +| **Solidity** | **HARD FAIL** on reentrancy, upgrade safety, audit-readiness, and other security-critical checks | On-chain code; bug class is irreversible and externally exploitable | +| **Daml** | **HARD FAIL** on ledger invariants, authorization correctness, upgrade safety, privacy violations | Ledger-state correctness is foundational; authorization is a security boundary | +| **Rust** | **SOFT WARNING** generally; `unsafe` blocks promote to near-HARD-FAIL scrutiny per [Forest `AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) | Memory safety guarantees lost inside `unsafe` | +| **Zig** | **SOFT WARNING** generally; the memory-safety / undefined-behavior surface (`@setRuntimeSafety(false)`, pointer casts, `catch unreachable`) and the consensus-correctness surface (SSZ, `hashTreeRoot`, Merkleization) promote to near-HARD-FAIL scrutiny | Manual memory management plus consensus-critical output (lodestar-z) | +| **Go**, **TypeScript**, **Python** | **SOFT WARNING** on style / idiom violations | Style and idiom; operator decides whether to merge | + +Severity is set per-language because the cost of a bypassed finding is per-language. An unsafe Solidity reentrancy is an exploit; an unsafe Go style decision is technical debt. Adding a new language to the HARD FAIL list is a CODEOWNER-level decision and gets recorded in this table. + +*Why:* HARD FAIL findings are the codified judgment of the org's most expensive review knowledge. An agent overruling them is doing the opposite of operator-first. + +A HARD FAIL is the only gate where operator approval still does not let the agent proceed silently — the agent stops, the operator decides, and any override is logged in the PR with an explicit "I am overriding HARD FAIL X for reason Y." This converts an invisible bypass into an auditable decision. + +### 9. Operational-contract changes + +- **Adding or changing environment variables, secrets references, config keys, feature flags, or ports** the running system depends on. +- **Schema or migration changes** (also trips §3 when destructive). +- **Breaking a public interface or wire format** that existing clients or deployed instances rely on. +- **Anything that changes what the team running the service (Infra, or the owning service team) must do to deploy or operate it.** + +Before such a change ships, its operational contract is declared in the PR's **Operational impact** section ([`../workflows/pr-authoring.md`](../workflows/pr-authoring.md)) and the owning team has signed off. The agent does not finalize or hand the change off until both are done — and the handoff goes through the PR, issue, or runbook, never a pasted chat message (see [agent-era invariant 9](../invariants/agent-era-invariants.md#9-operational-contract-changes-are-surfaced-not-handed-off)). + +*Why:* an undeclared contract change is the failure that lands on Infra days later — reverse-engineering which env vars are needed, why old clients broke, what a migration assumed. Declaring it up front is a checklist item; not declaring it is a manual, cross-team firefight. + +## How the agent stops at a gate + +The stop is structured. Do not stop silently. Do not stop with "I cannot do this." Stop with the information the operator needs to decide. + +Standard pattern: + +1. **What you were about to do.** Specific. File paths, commands, parameter values. +2. **Which gate this tripped.** Reference the category above. +3. **Why this action is needed for the task.** One sentence. +4. **What can go wrong if it proceeds.** Concrete, not generic. +5. **The rollback plan.** What undoes this if it goes wrong. +6. **What you need from the operator.** "Approve to proceed" / "approve with these modifications" / "approve and I will run the migration". + +Example: + +> I am about to run `migrate up` against `prod-readwrite` to apply migrations `0041_drop_legacy_sessions` and `0042_add_session_v2_index`. **Gate tripped: §1 production and deployment, §3 irreversible writes** (the 0041 migration includes `DROP COLUMN`). The session-v2 work needs both migrations live before the API switch can ship. If 0041 fails partway through, sessions for users in the affected shard go read-only until 0041 is rolled back. **Rollback plan:** `migrate down` for 0042, then manual `ALTER TABLE` to restore the dropped column from the pre-migration backup snapshot taken at TIMESTAMP. **Need:** explicit go-ahead, or a request to modify the plan. + +## Escalation paths + +The agent escalates — stops and asks beyond the operator — when one of the following holds: + +- **The operator asks the agent to do something on the refusal list.** Escalate to the section CODEOWNER, or to the curator (`@kalambet`) if it touches the handbook itself. +- **Two authorities give conflicting instructions.** E.g., `@joshdougall` says a deploy needs to wait for the next release window; the operator says ship now. The agent does not pick between them — it surfaces the conflict to both and waits. +- **The operator is unavailable mid-task** and the next step is gated. Do not proceed past the gate. Write the current state (`plan.md` updated, `research.md` if any new findings, a note about where the agent stopped). Exit cleanly. Wait. +- **The agent does not understand a gate well enough to apply it.** Better to ask the curator than to guess at the boundary of a rule. + +## Escalation matrix (quick reference) + +| Situation | Escalate to | +|---|---| +| Ambiguous intent, choices have different consequences | Operator | +| Operator asks for something on the refusal list | Section CODEOWNER, then curator | +| Conflict between two CODEOWNERs / two authorities | Both, surface the conflict, wait | +| Operator unavailable mid-task, gate ahead | No one — leave artifacts, exit, wait | +| Gate exists but the agent does not understand its scope | Curator (`@kalambet`) | +| Issue with this handbook itself (missing page, broken anchor, stale invariant) | Curator (`@kalambet`); open an issue or PR | + +## What to do when in doubt + +If you think you might be tripping a gate but cannot tell from the list above: stop and ask. It is cheap. + +If the action feels destructive, unrecoverable, or visible to people other than the operator, and the situation is not on this page: treat it as a gate anyway, and surface the gap to the curator so the list can be extended. + +The gate list is a floor, not a ceiling. Agents are expected to apply judgment above it, not below it. + +## Related + +- [`collaborator-statement.md`](./collaborator-statement.md) — the principle these gates implement, and the refusal list (which sits *above* gates: gates can be approved, refusals cannot). +- [`../invariants/agent-era-invariants.md`](../invariants/agent-era-invariants.md) — the refusal cases restated as invariants. +- [`../languages/`](../languages/) — language-specific reviewer pages name which HARD FAIL checks apply per language. diff --git a/operating-model/mcp-and-llm-txt.md b/operating-model/mcp-and-llm-txt.md new file mode 100644 index 0000000..6aa7344 --- /dev/null +++ b/operating-model/mcp-and-llm-txt.md @@ -0,0 +1,118 @@ +# Discovery: MCP and `llms.txt` + +How an agent discovers and loads this handbook from outside it — what an engineer's Claude Code session, Cursor instance, or other AI runtime should do to pull authoritative ChainSafe engineering context on demand. + +> **In one line:** Two channels. Static deep links via `handbook.chainsafe.io/llms.txt` for URL consumers. GitHub MCP for tool-style browsing. Load on demand, never bulk. + +## The two channels + +### `handbook.chainsafe.io/llms.txt` (static deep links) + +A single agent-facing index file served at `handbook.chainsafe.io/llms.txt`. Conforming to the [`llms.txt`](https://llmstxt.org/) proposed standard. It lists every handbook section, every packaged skill, and every external canonical source as a deep link with a one-line description. + +An agent that does not have access to MCP tooling — or that prefers static URLs — fetches `handbook.chainsafe.io/llms.txt`, picks the entries relevant to its task, and pulls those raw markdown URLs directly. Each linked page is self-contained enough to be consumed in isolation. + +### GitHub MCP (tool-style browsing) + +For agents in runtimes that expose the GitHub MCP server (Claude Code, Cursor, Continue, custom Agent-SDK bots with the connector loaded), the handbook repo is browsable as a tool surface. Agents discover pages by listing the repo tree, reading specific paths, and following cross-references. + +This is the richer channel: agents can navigate the handbook's link graph rather than working off the flattened `llms.txt` index. Prefer this when available. + +### Future: in-house ChainSafe MCP server + +A dedicated ChainSafe MCP server is a possible future enhancement. It would add custom indexing, skill search, and ChainSafe-specific tooling beyond what the generic GitHub MCP provides. It is justified only if observed agent-usage patterns show GitHub MCP discovery is the bottleneck. + +## `llms.txt` structure + +### Format + +Following the `llms.txt` proposed standard: + +- An H1 with the project name. +- An optional blockquote summary. +- Free-text paragraphs giving short orientation. +- Section H2s grouping links. +- Each link is `- [Title](URL): One-line description.` + +URLs in the live file point at the **raw markdown content** on GitHub (or `chainsafe.io` aliases that redirect there) — not at the rendered GitHub UI. Agents fetch raw content; humans land on the README via the repo home. + +### What goes in it + +- **Project identity.** Title, one-line description, link to the human README. +- **Section deep links.** One entry per handbook section (`operating-model/collaborator-statement.md`, `invariants/engineering-invariants.md`, `workflows/pr-authoring.md`, etc.) — keyed by question or intent, not by file structure. +- **Skill listings.** Every packaged skill in [`skills/`](../skills/) gets an entry: name, one-line description (matching the SKILL.md frontmatter), direct URL to the raw `SKILL.md`, and trigger conditions so foreign agents can decide whether to load it. +- **External canonical sources.** Deep links into the upstream `.invariants` and `ChainSafe/infrastructure-general` repos where the handbook defers to them. + +### What does not go in it + +- Internal-only or unreleased material. +- Build artifacts or generated files. +- Pages that are frequently changing without strong stewardship (drafts, TODOs). +- Anything the handbook does not yet have an actual page or skill for — never list a planned future entry as if it exists today. Foreign agents fetching a broken link is worse than not knowing the page is planned. + +### Worked example (representative snippet, not the final file) + +```markdown +# ChainSafe Engineering Handbook + +> The AI-native handbook for how ChainSafe builds software. Operator-first, opinionated, public. + +This is the agent-facing index. For humans, see the +[README](https://github.com/ChainSafe/engineering-handbook/blob/main/README.md). + +## Operating model +- [Collaborator Statement](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/collaborator-statement.md): The operator/agent contract. Load before any non-trivial task. +- [Gates and Escalation](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/gates-and-escalation.md): Enumerated checkpoints where agents stop and ask. Refusals vs. gates. +- [Model and Tool Selection](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/operating-model/model-and-tool-selection.md): Which model tier, which MCPs, which skills. + +## Skills +- [chainsafe-research-plan-implement](https://raw.githubusercontent.com/ChainSafe/engineering-handbook/main/skills/chainsafe-research-plan-implement/SKILL.md): Research → plan → annotate → implement workflow. Trigger: any multi-file change, refactor, new feature. + +## External canonical sources +- [.invariants starter kit](https://github.com/boorich/.invariants-starter-kit): `.invariants` framework. The handbook's `languages//architect.md` pages deep-link here. +- [ChainSafe/infrastructure-general](https://github.com/ChainSafe/infrastructure-general/blob/main/AGENTS.md): Infrastructure & DevOps canonical source. The handbook's `workflows/infrastructure-and-devops.md` deep-links here. +``` + +The actual `llms.txt` lives at the repo root: [`llms.txt`](../llms.txt). It is published to `handbook.chainsafe.io/llms.txt` via Cloudflare Pages: the Pages project is connected to this repo with Git integration and rebuilds on every push to `main` (and spins up a preview deployment for every PR), with `handbook.chainsafe.io` as the production custom domain. The repo-root file is the source of truth; the `handbook.chainsafe.io` URL is the public surface. + +## How an agent should use this + +### On session start + +1. Read [`AGENTS.md`](../AGENTS.md) at the repo root. +2. Load [`collaborator-statement.md`](./collaborator-statement.md) and [`gates-and-escalation.md`](./gates-and-escalation.md). +3. Identify the specific section or skill relevant to the task. +4. Fetch only that section, plus any external canonical source it deep-links into. + +Do not bulk-load the handbook. The whole tree is larger than any single task needs, and loading everything wastes context that should hold task-specific material. + +### When loading skills + +- A skill listed in `llms.txt` with a triggering description that matches the task → load the SKILL.md, follow its instructions, do not re-derive its workflow. +- A skill that does not match → do not load it. The triggering descriptions are written so foreign agents can self-select. +- Two candidate skills → ask the operator before invoking either. See [`model-and-tool-selection.md` §"Do not chain skills automatically"](./model-and-tool-selection.md#do-not-chain-skills-automatically). + +### When a referenced page is missing + +Occasionally a cross-referenced page may be missing or moved. When that happens: + +- Do not fabricate substitute content. +- Surface the gap to the operator. If the operator wants to proceed without the missing page, the agent flags this explicitly in any artifact it produces ("This plan was drafted without `` because it does not yet exist; verify against `` once available"). +- Optionally file an issue in `ChainSafe/engineering-handbook` to track the gap. + +## Maintenance + +CI guarantees `llms.txt` does not drift from the handbook content: + +- Every skill in [`skills/`](../skills/) must appear in `llms.txt`. +- Every `llms.txt` skill entry must resolve to an existing `SKILL.md`. +- All external deep links (into `.invariants`, `infrastructure-general`, Forest, etc.) are link-checked in CI and the build fails on any broken target. + +When you add a new skill, section, or pointer page: update `llms.txt` in the same PR. The handbook treats the index and the content as a single commit, not two. + +## Related + +- [`collaborator-statement.md`](./collaborator-statement.md) — the contract that the discovery layer serves. +- [`gates-and-escalation.md`](./gates-and-escalation.md) — what stops the agent, including the external-communication gate that affects how agents post about discoveries. +- [`model-and-tool-selection.md`](./model-and-tool-selection.md) — when to load which MCP and skill. +- [`memory-conventions.md`](./memory-conventions.md) — what an agent should persist about handbook content across sessions. diff --git a/operating-model/memory-conventions.md b/operating-model/memory-conventions.md new file mode 100644 index 0000000..455e30b --- /dev/null +++ b/operating-model/memory-conventions.md @@ -0,0 +1,114 @@ +# Memory Conventions + +What an agent persists across sessions, what it does not, and how it stays honest about the difference between what was true once and what is true now. + +> **In one line:** Save the non-obvious. Skip what the code, git history, or this handbook already says. Treat every memory as point-in-time, not live state. + +## When agents have persistent memory + +Different runtimes offer different mechanisms: + +- **Claude Code** persists memory through `CLAUDE.md` files in projects and the user's memory directory (`~/Library/Application Support/Claude/...` on macOS). +- **Cursor** uses `.cursorrules` and project-level conventions. +- **Continue** and custom Agent-SDK bots may bring their own storage. + +The conventions below apply regardless of runtime. Where this handbook says "save," it means "persist somewhere that survives the current session." Where it says "do not save," that prohibition holds across all of the above. + +## What to save + +Four categories of memory are useful and persist well: + +### Operator context + +Who the operator is, what they care about, what role they play, what tools and conventions they prefer. The agent picks up an established working relationship instead of re-bootstrapping every session. + +Examples: *"Operator is the CTO of ChainSafe, primarily concerned with engineering practice rather than direct code review."* / *"Operator prefers terse commit messages, no marketing speak in PR descriptions."* / *"Operator's primary language is Rust and TypeScript; less context on Daml."* + +### Feedback + +Corrections (what to avoid in the future) and confirmations (what worked and should be repeated). Both matter — saving only corrections drifts the agent toward over-cautious behavior; saving only confirmations misses the lessons that came from being wrong. + +Examples: *"Operator does not want me to summarize what I just did at the end of every response — they read the diff."* / *"Operator confirmed that bundling a multi-file refactor into one PR was the right call here; do not auto-split."* + +Lead with the rule. Add a **Why** line (the reason the operator gave) and a **How to apply** line (when the rule kicks in). The why matters because it lets the agent judge edge cases instead of pattern-matching. + +### Project context + +Who is doing what, why, by when — facts that are not derivable from code or git log but that shape current work. + +Examples: *"The bridge contracts are frozen pending an external audit; work touching them before sign-off is reviewed with the audit owner."* / *"A service's auth-middleware rewrite is driven by a compliance requirement, not tech-debt cleanup — don't quietly descope it."* + +Convert relative dates to absolute ones at save time (e.g., "next Thursday" → "2026-06-04") so the memory stays interpretable as time passes. + +### External references + +Pointers to where authoritative information lives outside the current repo: which Linear project tracks which kind of bug, which Slack channel collects which kind of feedback, which Grafana dashboard the on-call watches. + +Examples: *"Pipeline bugs are tracked in Linear project INGEST."* / *"On-call latency dashboard: grafana.internal/d/api-latency. Check it when touching request-path code."* + +## What NOT to save + +Some things look saveable but are not. Reading the current code, the current handbook, or `git log` is faster and more accurate than relying on a stale memory. + +- **Code patterns, conventions, architecture, file paths, or project structure.** Read the current repo. Memories of structure go stale within weeks. +- **Git history.** `git log` and `git blame` are authoritative. +- **Debugging solutions or fix recipes.** The fix is in the code; the commit message has the context. +- **Anything already documented in `AGENTS.md`, `CLAUDE.md`, or any handbook page.** Memory should not duplicate the contract. +- **Ephemeral task state.** Mid-conversation context belongs in the conversation, not in long-term memory. + +If the operator explicitly says "save this," even when it fits one of the categories above, ask once whether they understood the alternative (e.g., "this is in `AGENTS.md` — do you want it in memory anyway?"). If the operator confirms, save it. + +## Sensitive data rules + +These do not get saved without explicit, per-item operator consent. Even when relevant to the task, even when convenient. + +- **Secrets, API keys, tokens, credentials, passwords.** Never. +- **Protected personal attributes:** race, ethnicity, national origin, religion, age (when not strictly task-relevant), sex, sexual orientation, gender identity, immigration status, disability, serious illness, union membership. +- **Government identifiers:** SSN, driver's license numbers, passport numbers, government IDs. +- **Financial account details:** credit card numbers, bank account numbers. +- **Health information:** medical conditions, diagnoses, lab results, mental-health or therapy details. +- **Home or personal mailing addresses.** Work addresses are fine. +- **Confidential commercial information.** Internal financial figures, customer commercial terms, partner contract details, and similar non-public business information are not persisted without explicit per-item consent. + +If sensitive material appears in a conversation, complete the task but do not persist it. If the operator says "remember my address is X" or "remember to flag this in the next review," that explicit instruction is consent — saving is acceptable. + +## Organization + +Semantic, not chronological. The memory store is not a journal; it is a knowledge base. + +- **One file per topic.** Operator role, a specific feedback rule, a specific project, an external system reference — each gets its own file with a kebab-case name. +- **Index in `MEMORY.md`.** A single-line entry per file (under ~150 characters) acts as a hook into the body. The index is loaded into every session; the bodies are loaded on demand. +- **Cross-link with `[[name]] `.** When two memories relate, link them. Broken `[[name]]` references mark gaps worth filling later. +- **Update in place.** If a fact changes, edit the existing memory file rather than writing a new one. + +## Memory hygiene + +Memories are point-in-time observations, not live state. The agent treats them accordingly. + +- **Verify before acting.** A memory that names a function, flag, or file path is a claim about what existed when the memory was written. Before recommending an action that depends on it, check: does the file still exist? Does the function still have that signature? Use `git`, `grep`, or a fresh read. +- **Trust observations over memory on conflict.** If a recalled fact contradicts what the current repo or current `git log` shows, the current state wins. Update or remove the stale memory; do not act on it. +- **Stale ≠ wrong.** A memory recording "the release freeze starts 2025-03-01" is not wrong the day after — it is now history. Decide whether to keep it as history, update it, or remove it. + +## Consolidation + +Periodically — every few weeks, or after a stretch of dense work — reflect on the memory store: + +- Merge duplicates. Two files saying similar things become one. +- Prune the obsolete. Project context from a finished initiative may no longer earn its space in the index. +- Tighten the index. Hooks that no longer describe their files accurately get rewritten. + +Consolidation is a planned operation, not a reflex. It changes the memory store materially and should be done by the agent with operator awareness, not silently. + +## ChainSafe specifics + +A few things to be deliberate about given how ChainSafe operates: + +- **Multi-product context.** Engineers move between Lodestar, Forest, Gossamer, Sygma, Canton, and gaming. Project memories should name the product explicitly so future sessions know whether the fact is in scope. +- **Public handbook vs. internal context.** This repository is public. Memory may hold internal information; the agent must never let internal-only context leak into a PR description, an issue comment, or any other output destined for the public handbook. +- **Security-critical sessions.** When the operator names a session as touching cryptographic code, ledger logic, or production blockchain assets, raise the bar on what gets persisted — both because the work itself is sensitive and because mistakes propagate. + +## Related + +- [`collaborator-statement.md`](./collaborator-statement.md) — operator-first applies to memory: the operator can override save/don't-save defaults; the agent never persists silently against explicit instruction. +- [`gates-and-escalation.md`](./gates-and-escalation.md) — the secrets gate (§2) and external-communication gate (§4) describe the same hard limits in their respective domains. +- [`mcp-and-llm-txt.md`](./mcp-and-llm-txt.md) — what agents pull from this handbook on demand; complementary to what they persist about themselves and the operator. diff --git a/operating-model/model-and-tool-selection.md b/operating-model/model-and-tool-selection.md new file mode 100644 index 0000000..89d5d1e --- /dev/null +++ b/operating-model/model-and-tool-selection.md @@ -0,0 +1,123 @@ +# Model and Tool Selection + +How an agent picks which model to run on, which MCPs and tools to load, and which skills to invoke — without violating the [Collaborator Contract](./collaborator-statement.md). + +> **In one line:** Start with the cheapest viable tool. Escalate when the work earns it. Do not load everything by default. + +## Who picks what + +In most runtimes (Claude Code, Cursor, the Claude desktop app, custom Agent-SDK bots), the **operator** picks the model before launching the session. The agent does not unilaterally switch. The agent's job is to **notice and surface** when the current model is the wrong size for the task — not to silently reach for a different one. + +The **agent** picks freely among: + +- Which MCPs and tools to load, within the operator's authorized scope. +- Which skill to invoke for a given work shape. +- Which sub-agent or delegation pattern to use, if the runtime supports them. + +The **operator** picks: + +- Base model tier (Opus / Sonnet / Haiku). +- Which integrations and credentials are available. +- Hard constraints — cost ceiling, allowed-tool list, etc. + +## Model selection + +### Principle + +Start with the cheapest model that can complete the task. Escalate to a larger model when the work earns it — not preemptively. + +"Earns it" means one of: + +- The task involves multi-step reasoning across files or systems. +- The task is security- or correctness-critical (Solidity, Daml, cryptographic code, anything in a hot production path). +- An attempt with a smaller model produced wrong output or got stuck in a loop. +- The operator asked for higher rigor. + +### Rough mapping + +| Task class | Starting model tier | +|---|---| +| Quick lookups, summaries, simple edits, classifications | Haiku | +| Most engineering work: code, code review, planning, ADR drafting | Sonnet | +| Hard debugging, complex multi-file refactors, security-critical review, novel system design, ledger or invariant work | Opus | + +This is a starting point, not a contract. If a Sonnet session is repeatedly producing weak output on a class of task, escalate. If an Opus session is being used for one-line README edits, downsize. + +### Surfacing model mismatch to the operator + +When the agent notices the model is mismatched, it says so explicitly. Examples: + +- "I am running on Haiku and this task involves cross-file reasoning over the Forest p2p layer. I will continue but recommend switching to Sonnet or Opus for this session." +- "I have made three attempts at this debugging session on Sonnet and the proposed fixes have been wrong each time. I recommend a fresh Opus session, picking up from the research artifact I wrote." + +Do not silently bail. Do not silently push through. + +This page refers to capability tiers (Haiku-class, Sonnet-class, Opus-class), not specific model versions. Map your provider's current generations onto these tiers; the tier logic holds as new models ship. + +## Tool and MCP selection + +### Default loadout + +- **This handbook**, via MCP or direct file access. The agent is operating against this contract; it must be loaded. +- **The current project's source tree.** Read access is baseline. + +That is the default. Everything else is on-demand. + +### On-demand loadout + +- **GitHub MCP** — when opening PRs, reading issues, listing branches, working with reviews. +- **`ChainSafe/infrastructure-general`** — when touching infra, IaC, observability, deploys, runbooks. Coordinate with `@joshdougall` as the canonical owner. +- **[`.invariants` starter kit](https://github.com/boorich/.invariants-starter-kit)** — when doing architecture or system-design work. Coordinate with `@boorich` as the framework maintainer. +- **Linear / Jira / project-tracker MCPs** — when the task involves issue triage, sprint planning, or status updates. +- **Slack / Discord / email MCPs** — when the task involves communication. Note the [external-communication gate](./gates-and-escalation.md#4-external-communication). +- **Product-specific repos** (`ChainSafe/forest`, `ChainSafe/lodestar`, `ChainSafe/sygma`, etc.) — when working on that product. Do not load a product repo just to browse it; the operator authorized work on a specific scope. +- **Daml MCP server (`daml-autopilot`)** — when authoring or reviewing Daml / Canton code. ChainSafe's own tool: *Daml Reason* (canonical-pattern search + authorization-model extraction) and *Daml Automater* (environment / CI / build guidance). We dogfood it; it is the recommended Daml dev assistant. The hosted MCP server is **pay-as-you-go**, billed per use via a Canton payer party, so its use falls under the [cost gate](./gates-and-escalation.md#7-cost-and-external-resource-creation) — provision the payer party deliberately. The free [`ChainSafe/canton-ci`](https://github.com/ChainSafe/canton-ci) GitHub Actions need no MCP and carry no per-use cost. Setup and config: [`../languages/daml/developer.md`](../languages/daml/developer.md). + +### Tools to be skeptical of + +- **Production credentials and secrets stores.** Almost never. Loading these without a specific gated task is permission creep — see [§2 of gates-and-escalation](./gates-and-escalation.md#2-secrets-and-credentials). +- **Cost-incurring API access** beyond a small exploratory budget. The agent does not see the bill — see [§7 of gates-and-escalation](./gates-and-escalation.md#7-cost-and-external-resource-creation). +- **MCPs the agent does not understand the surface of.** If you cannot describe what the tool does and what its failure modes look like, you are not ready to use it. Ask the operator first. + +### Discovery: how an agent learns what tools exist + +- For ChainSafe-specific MCPs and skills: `handbook.chainsafe.io/llms.txt` is the index. +- For Claude-runtime tools: the runtime advertises them; no action needed. +- For MCPs not on `llms.txt`: ask the operator. Do not install or attempt to add MCP endpoints from the session. + +## Skill selection + +When a task matches a packaged skill in [`skills/`](../skills/), prefer the skill over an ad-hoc plan. Reasons: + +- Skills have been authored deliberately (via `skill-creator`) and reviewed. +- Skills carry their own load order, escalation defaults, and gate references. +- The operator can predict what the agent will do because the skill is a known surface — surprises shrink. + +### Default skill picks + +| Work shape | Skill | +|---|---| +| Any non-trivial code change | [`chainsafe-research-plan-implement`](../skills/chainsafe-research-plan-implement/SKILL.md) | +| Language-specific architecture, development, or review | The matching `chainsafe--{architect,developer,reviewer}` skill | +| Authoring or editing a Claude skill | Anthropic's `skill-creator` | + +When no skill matches, work from first principles using the Collaborator Contract. + +### Do not chain skills automatically + +If the work could plausibly invoke two skills, ask the operator which is in scope before invoking either. Auto-chaining is a frequent source of scope creep. + +## Anti-patterns + +- **"Use Opus just in case."** Opus is expensive in latency and tokens. Use it when the work earns it; the cheaper tiers handle most engineering work fine. +- **"Load every available MCP."** More tools means more surface area, more confusion, and more places for the agent to do something the operator did not authorize. +- **"Combine three skills into one mega-flow."** If a task does not match a single skill, work from the contract; do not improvise multi-skill choreography. +- **"Silently switch model mid-session."** Agents do not switch models. Agents surface model-mismatch and let the operator decide. +- **"Browse product repos for context."** If you have not been authorized to work on a product, do not load its repo just because it looks relevant. + +## Related + +- [`collaborator-statement.md`](./collaborator-statement.md) — the contract these selections operate under. +- [`gates-and-escalation.md`](./gates-and-escalation.md) — what stops the agent regardless of model or tool. +- [`mcp-and-llm-txt.md`](./mcp-and-llm-txt.md) — how agents discover tools and content from this handbook. +- [`../skills/`](../skills/) — the packaged skills the agent can invoke. diff --git a/package.json b/package.json deleted file mode 100644 index 742ff9f..0000000 --- a/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "engineering-handbook", - "version": "0.0.0", - "private": true, - "packageManager": "yarn@1.22.19", - "scripts": { - "docusaurus": "docusaurus", - "start": "docusaurus start", - "build": "docusaurus build", - "swizzle": "docusaurus swizzle", - "deploy": "docusaurus deploy", - "clear": "docusaurus clear", - "serve": "docusaurus serve", - "write-translations": "docusaurus write-translations", - "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc", - "spellcheck": "spellchecker -f \"./docs/**/*.md\" \"./*.md\" \"./src/**/*.md\" -l en-US -q -d ./dictionary.txt" - }, - "dependencies": { - "@cmfcmf/docusaurus-search-local": "^1.1.0", - "@docusaurus/core": "^3.2.1", - "@docusaurus/preset-classic": "^3.2.1", - "highcharts": "^11.4.1", - "highcharts-react-official": "^3.2.1", - "mdx-mermaid": "^2.0.0", - "mermaid": "^10.9.0", - "prism-react-renderer": "^2.3.1", - "react": "^18", - "react-dom": "^18" - }, - "devDependencies": { - "@docusaurus/module-type-aliases": "^3.2.1", - "@tsconfig/docusaurus": "^2.0.3", - "spellchecker-cli": "^6.1.0", - "typescript": "^5.4.4" - }, - "browserslist": { - "production": [ - ">0.5%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/public/_headers b/public/_headers new file mode 100644 index 0000000..1488801 --- /dev/null +++ b/public/_headers @@ -0,0 +1,7 @@ +# Cloudflare Pages headers. https://developers.cloudflare.com/pages/configuration/headers/ +# +# Serve llms.txt as UTF-8 plain text so agents and browsers render it inline +# instead of downloading it. Short cache so edits to main go live quickly. +/llms.txt + Content-Type: text/plain; charset=utf-8 + Cache-Control: public, max-age=300 diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..4a7633f --- /dev/null +++ b/public/_redirects @@ -0,0 +1,7 @@ +# Cloudflare Pages redirects. https://developers.cloudflare.com/pages/configuration/redirects/ +# +# Bare domain -> the human-facing README on GitHub. The handbook is browsed on +# GitHub; handbook.chainsafe.io exists to serve llms.txt and to point people at the repo. +# 301 is fine — the README's canonical location is stable. Switch to 302 if you +# expect to move it. +/ https://github.com/ChainSafe/engineering-handbook/blob/main/README.md 301 diff --git a/references/CONTRIBUTORS.md b/references/CONTRIBUTORS.md new file mode 100644 index 0000000..6ddba7b --- /dev/null +++ b/references/CONTRIBUTORS.md @@ -0,0 +1,30 @@ +# Contributors + +Authors and curators of the ChainSafe Engineering Handbook. This file is the central index of who contributed what and complements two other attribution layers: inline credits in each content file's header, and `CODEOWNERS` for review routing. + +## How it works + +The curatorial model: practices already exist across the org and get aggregated here with original authors credited. Anyone whose content lands in the handbook — even adapted, even partial — earns a credit. + +- Add an entry when authoring new content, contributing material from an upstream source, or being added as a `CODEOWNER`. +- Format: GitHub handle, name, role, sections owned or contributed to. Free-form notes welcome. +- Removal is rare. Past contributors stay credited after they leave the org. + +## Curators + +| Handle | Name | Role | +|---|---|---| +| [@kalambet](https://github.com/kalambet) | Peter Kalambet | CTO; curator of the handbook | + +## Section owners and contributors + +*Section owners and contributors are listed here as they take ownership of, or contribute substantive content to, handbook areas.* + +## Third-party content credits + +For upstream attribution required under the Apache 2.0 license (Section 4(d)), see [`NOTICE`](../NOTICE) at the repo root. The current third-party lineage recorded there: + +- The `chainsafe-research-plan-implement` skill is adapted from Boris Tane. +- Forest's AI policy (deep-linked from `workflows/testing-and-qa.md` and the Rust reviewer guidance) originally derives from the Ghostty project. + +When new third-party material is carried into the handbook, both `NOTICE` and the relevant file's inline header are updated. diff --git a/references/attribution.md b/references/attribution.md new file mode 100644 index 0000000..a6f1742 --- /dev/null +++ b/references/attribution.md @@ -0,0 +1,102 @@ +# Attribution Policy + +How original authors are credited across the ChainSafe Engineering Handbook. The curatorial model is only credible if credit is visible everywhere it matters. + +> **In one line:** Three layers — git history, [`CONTRIBUTORS.md`](./CONTRIBUTORS.md), [`CODEOWNERS`](../.github/CODEOWNERS). Plus [`NOTICE`](../NOTICE) for upstream content carrying license obligations. + +## The curatorial model + +This handbook is curated, not solo-authored. Practices already exist across the org and within the wider open-source ecosystem; the curator (currently [@kalambet](https://github.com/kalambet)) aggregates them, ensures consistency of voice, and routes content to the right reviewers — but does not claim authorship of material someone else wrote. + +This creates an asymmetry from the usual "author of record" pattern: the person who *adapts* a practice into the handbook is not the same as the person who *originated* it, and both get credit. Section 5 below explains the difference. + +## The three attribution layers + +Every piece of content carries credit at three layers. None of them can be skipped. + +### Layer 1: Git history + +The authoritative record of *who touched this file and when*. `git log` and `git blame` are true by construction — every commit carries author identity and timestamp, and the history is immutable. + +This handbook deliberately does **not** maintain `authors:` or `last_updated:` fields in YAML frontmatter on content pages. Hand-maintained authorship and timestamps rot the moment someone else touches the file; git already has the answer, more accurately. For the same reason, the handbook does not maintain a "last reviewed" timestamp — if you want to know how stale a file is, run `git log -1 --format=%cs `. + +The single exception is `skills/*/SKILL.md` files, where the Anthropic skills spec requires YAML frontmatter (`name:`, `description:`, `metadata:`) and a CI sync-check parses it. Those keep frontmatter; everything else gets attribution from git. + +### Layer 2: `CONTRIBUTORS.md` + +The central index. Lives at [`./CONTRIBUTORS.md`](./CONTRIBUTORS.md). One entry per contributor: GitHub handle, name, role, sections owned or contributed to, optional free-form notes. + +The index is for navigation ("who do I ask about this section?") and for credit ("who has contributed?"). Two distinct purposes; both are served by the same page. + +Entry conventions: + +- Add yourself (or get added) when authoring new content or contributing material from an upstream source. +- Past contributors remain credited after they leave the org. Removal is the rare case — a typo fix or trivial edit does not earn an entry on its own, but a substantive section contribution does. +- The index is organized by *role* (curator, section owner, contributor), not chronologically. + +### Layer 3: `CODEOWNERS` + +Lives at [`../.github/CODEOWNERS`](../.github/CODEOWNERS). Routes review of changes — when someone (human or agent) opens a PR touching a section, the right reviewer is auto-requested. + +CODEOWNERS is not just review routing; it is a public statement of who owns what. A CODEOWNERS entry is read by humans as "this person has authority and responsibility for this section." The default owner is [@kalambet](https://github.com/kalambet) (CTO and curator); section-specific overrides are added in CODEOWNERS as sections gain dedicated owners. + +## Why three layers and not one + +Single-layer attribution fails in predictable ways: + +- **Git history alone** is not navigable — there is no curator-level view of "who owns the Rust section." `git log` shows commits, not ownership. +- **A central index alone** drifts from the content. The index says X owns section Y, but the history shows Z wrote it. Readers do not know which to believe. +- **CODEOWNERS alone** conflates ownership with authorship. The CODEOWNER reviews changes; they did not necessarily write the original content. + +All three together provide redundancy and serve different purposes: git is true by construction at the line level, the index is navigable at the page level, and CODEOWNERS enforces routing at the directory level. + +## Adapted vs. originated + +A distinction worth being deliberate about: + +- **Originator** — the person who wrote the substantive content or who developed the practice the content is documenting. Credited in [`CONTRIBUTORS.md`](./CONTRIBUTORS.md) and, when license obligations apply, in [`NOTICE`](../NOTICE) and [`sources.md`](./sources.md). +- **Adapter** — the person who pulled the originator's work into the handbook, restructured it, kept it consistent with handbook conventions. Credited in [`CONTRIBUTORS.md`](./CONTRIBUTORS.md) and visible in git history. +- **Curator** — the person responsible for the handbook as a whole. Credited in CODEOWNERS as the default owner and named explicitly in [`CONTRIBUTORS.md`](./CONTRIBUTORS.md). + +The same person can occupy multiple roles for different content. Peter is the curator and the adapter of the `research-plan-implement` skill; Boris Tane is the originator. Both appear in different layers. + +## Upstream content and Apache 2.0 §4(d) + +When content carries license obligations from upstream — Ghostty's AI policy via Forest, Boris Tane's "How I Use Claude Code" via the `research-plan-implement` skill, etc. — Apache 2.0 §4(d) requires attribution preservation in derivative works. + +The handbook satisfies this via: + +- A prose attribution line in the page itself (typically in the opening paragraph or a "Related" section), naming the upstream source with a link. +- For SKILL.md files, the `metadata.based-on` or equivalent field in the YAML frontmatter. +- The [`NOTICE`](../NOTICE) file at the repo root, which lists every third-party source the handbook carries and the relevant attribution. **This is the authoritative record for license-compliance purposes.** +- The corresponding entry in [`./sources.md`](./sources.md) (External Canonical Sources catalog). + +When new third-party material is incorporated, the NOTICE file is updated in the same PR that adds the material. Drift between NOTICE and what the content actually carries is a license-compliance bug. + +## Adding a contributor + +When a new person contributes substantive content: + +1. Commit the change under their GitHub identity (git history captures Layer 1 automatically). +2. Add an entry in [`./CONTRIBUTORS.md`](./CONTRIBUTORS.md) under the appropriate role section. +3. If they will review future changes to that section, add them in [`../.github/CODEOWNERS`](../.github/CODEOWNERS). +4. If the content is adapted from a source with license obligations, update [`../NOTICE`](../NOTICE). +5. If the contribution involves a new canonical upstream source, add an entry to [`./sources.md`](./sources.md). + +All five steps land in the same PR as the content. The handbook treats content + attribution as a single commit, not two. + +## When the policy breaks + +If a contribution lands without correct attribution: + +- **A reviewer missed it.** The PR is amended; attribution is added; the original author is notified. +- **A contributor objected to their credit being added.** The handbook respects the request. Credit is removed or modified per the contributor's wish. +- **An upstream source's license terms were not properly attributed.** Treated as a license-compliance issue, not a style issue. Fixed immediately; NOTICE updated; the originator is notified. + +## Related + +- [`./CONTRIBUTORS.md`](./CONTRIBUTORS.md) — the central contributor index. +- [`./sources.md`](./sources.md) — the catalog of external canonical sources the handbook defers to. +- [`../NOTICE`](../NOTICE) — Apache 2.0 §4(d) third-party attribution record. +- [`../.github/CODEOWNERS`](../.github/CODEOWNERS) — review routing and ownership statement. +- [`../LICENSE`](../LICENSE) — Apache License 2.0. diff --git a/references/sources.md b/references/sources.md new file mode 100644 index 0000000..ed05274 --- /dev/null +++ b/references/sources.md @@ -0,0 +1,122 @@ +# External Canonical Sources + +The handbook defers, rather than duplicates, where another artifact is already the canonical source. This page is the catalog: every external source the handbook deep-links into, its maintainer, what it covers, and how it is referenced. + +> **In one line:** When the handbook says "see X," X is listed here with a maintainer and a coordination point. No "see also" links — only deep-linked deferrals. + +## How to read this page + +Each entry below names: + +- **Source** — the canonical repository, file, or document. +- **Maintainer** — the person who owns it. Changes to how the handbook references the source are coordinated with them. +- **Covers** — what subject area this source is canonical for. +- **Used by** — which handbook pages defer to this source. +- **Coordination** — who reviews changes to the deferral. + +Entries are added when the handbook starts deferring to a new source. Removal is rare; when a source is no longer canonical, the entry is marked deprecated rather than deleted, with a pointer to its replacement. + +## Sources + +### `.invariants` framework + +- **Source.** [github.com/boorich/.invariants-starter-kit](https://github.com/boorich/.invariants-starter-kit) (convention + optional reference workspace). Landing page: [boorich.github.io/.invariants-starter-kit/](https://boorich.github.io/.invariants-starter-kit/). Deep-link map: [`../invariants/invariants-framework.md`](../invariants/invariants-framework.md). +- **Maintainer.** [@boorich](https://github.com/boorich) (Martin Maurer). +- **Covers.** Architectural invariants — dotfile format, severity cascade, conformance agent, optional vecs code index and GitHub triage. Multi-repo convention. +- **Used by.** [`../invariants/invariants-framework.md`](../invariants/invariants-framework.md) (pointer page); every [`../languages//architect.md`](../languages/) page deep-links into per-language invariant sections; ADR templates referenced from [`../workflows/pr-authoring.md`](../workflows/) require an "Invariants impacted" field sourced from `.invariants`. +- **Coordination.** [@boorich](https://github.com/boorich) is CODEOWNER for the pointer page. Anchor changes upstream → re-anchor here in the same PR (or close behind). + +### `ChainSafe/infrastructure-general` + +- **Source.** [github.com/ChainSafe/infrastructure-general](https://github.com/ChainSafe/infrastructure-general) — the canonical repo for ChainSafe infrastructure, IaC, deployment topology, observability, on-call rotations, and runbooks. Already ships its own `AGENTS.md` and `CLAUDE.md`, confirming the agent-native posture. +- **Maintainer.** [@joshdougall](https://github.com/joshdougall) (Josh, Head of Infra). +- **Covers.** All infrastructure and DevOps practice: Ansible roles, Terraform modules, service catalog, observability dashboards, runbooks, incident response procedures, deployment topology, on-call scheduling. The Infra IR doc (previously flagged as a candidate to lift into the handbook) lives here and stays here. +- **Used by.** [`../workflows/infrastructure-and-devops.md`](../workflows/) (pointer page deep-linking into the infra repo by intent), [`../workflows/incident-response.md`](../workflows/), [`../workflows/release-and-deploy.md`](../workflows/). Handbook keeps only the *operator decision policy* layer inline; *how-to* defers to the linked runbook. +- **Coordination.** [@joshdougall](https://github.com/joshdougall) is CODEOWNER for the three pointer pages listed above. + +### Forest `AI_POLICY.md` (Ghostty lineage) + +- **Source.** `AI_POLICY.md` in [github.com/ChainSafe/forest](https://github.com/ChainSafe/forest). Originally adapted from the [Ghostty](https://github.com/ghostty-org/ghostty) project's AI policy, with attribution preserved in the upstream Forest file. +- **Maintainer.** Forest engineering team (current owners listed in Forest's CODEOWNERS). +- **Covers.** AI-assisted development policy at the product-repo level. Sets norms for what AI agents may and may not do when contributing to Forest specifically. +- **Used by.** [`../workflows/testing-and-qa.md`](../workflows/) borrows the QA framing around what agents should generate vs. what operators must own; the Rust reviewer guidance references it for `unsafe`-block scrutiny. +- **Coordination.** Forest team owns the upstream file. Ghostty attribution is preserved per Apache 2.0 §4(d) — see [`../NOTICE`](../NOTICE). + +### `chainsafe-research-plan-implement` skill (Boris Tane lineage) + +- **Source.** [`../skills/chainsafe-research-plan-implement/SKILL.md`](../skills/chainsafe-research-plan-implement/SKILL.md). Adapted by [@kalambet](https://github.com/kalambet) from ["How I Use Claude Code"](https://boristane.com/blog/how-i-use-claude-code/) by Boris Tane. +- **Maintainer.** [@kalambet](https://github.com/kalambet); adaptations to the workflow itself are coordinated with the wider engineering team given how central this skill is. +- **Covers.** Pipeline-style workflow for non-trivial coding work: research → plan → annotate (1–6 rounds) → implement. Human-approved plan gates every code change. +- **Used by.** [`../workflows/pr-authoring.md`](../workflows/) delegates the PR-shape engineering workflow to this skill rather than re-deriving it; [`../operating-model/model-and-tool-selection.md`](../operating-model/model-and-tool-selection.md) lists it as the default skill for any non-trivial code change; [`AGENTS.md`](../AGENTS.md) cross-references it. +- **Coordination.** [@kalambet](https://github.com/kalambet) is CODEOWNER. Material changes to the workflow itself are an org-level decision, not a curator-only one. + +### Anthropic's Skills Specification + +- **Source.** Anthropic's "Complete Guide to Building Skills for Claude" (the canonical skill-authoring playbook) and the [`anthropic-skills:skill-creator`](https://github.com/anthropics/skills) skill itself. +- **Maintainer.** Anthropic. +- **Covers.** Skill format (kebab-case names, YAML frontmatter, description shape, file-size constraints), authoring workflow, and triggering evals. +- **Used by.** Every skill in [`../skills/`](../skills/) is authored via `skill-creator` — the canonical authoring tool, no hand-rolled SKILL.md files. The handbook references the spec for format requirements but does not duplicate it. +- **Coordination.** External. The spec is treated as authoritative; if it changes, the handbook's skill-authoring guidance changes alongside. + +### Canton Network Docs (Daml language + Canton platform) + +- **Source.** [docs.canton.network](https://docs.canton.network) — the official Canton Network documentation: the Daml language, the app-development modules, deep dives, tooling, and the full Daml standard-library reference. Machine-readable index at [`docs.canton.network/llms.txt`](https://docs.canton.network/llms.txt) (every page is also served as raw markdown by appending `.md`). Upstream docs repo: [canton-network/cf-docs](https://github.com/canton-network/cf-docs). Documentation licensed CC-BY-4.0. +- **Maintainer.** External — the Canton Foundation. Internal coordination via the Daml CODEOWNERS — [@boorich](https://github.com/boorich), [@salindne](https://github.com/salindne), [@sqhell](https://github.com/sqhell) — per [`.github/CODEOWNERS`](../.github/CODEOWNERS). +- **Covers.** The authoritative Daml language and Canton platform reference: authorization model, contract templates, choices, keys, interfaces, the standard library, testing with Daml Script, Smart Contract Upgrades (SCU) and upgrade compatibility, working with time, security best practices, CI/CD integration, and Canton-specific topology (domain / synchronizer / sequencer / mediator). The handbook's Daml pages defer here rather than re-deriving language semantics — the same way the architect pages defer to `.invariants`. +- **Used by.** [`../languages/daml/architect.md`](../languages/daml/architect.md) (authorization / upgrade / privacy semantics), [`../languages/daml/developer.md`](../languages/daml/developer.md) (dev environment, tooling, standard library, testing), [`../languages/daml/idioms.md`](../languages/daml/idioms.md), [`../languages/daml/gotchas.md`](../languages/daml/gotchas.md), [`../languages/daml/reviewer.md`](../languages/daml/reviewer.md) (authorization, upgrade compatibility, security checks). +- **Coordination.** External upstream, treated as canonical for Daml language semantics. When Canton restructures the docs, re-anchor the deep links in the same pass — the weekly link-check run catches rot. The internal deferral is reviewed by the Daml CODEOWNERS. + +### `daml-autopilot` / `ChainSafe/canton-ci` (ChainSafe's own Daml tooling) + +- **Source.** [daml-autopilot.chainsafe.io](https://daml-autopilot.chainsafe.io) — ChainSafe's precision tooling for Daml development. Two surfaces: the [`ChainSafe/canton-ci`](https://github.com/ChainSafe/canton-ci) GitHub Actions (`install-daml`, `install-canton`, `daml-test`, `daml-script` — free, standalone, no MCP required) and the **Daml MCP server** (`mcp-server.chainsafe.io`) — an AI dev assistant: *Daml Reason* (canonical-pattern search + authorization-model analysis) and *Daml Automater* (environment / CI / build guidance), billed pay-as-you-go via a Canton payer party. +- **Maintainer.** ChainSafe — built and maintained by the same team that owns the handbook's Daml section: [@boorich](https://github.com/boorich) (Martin Maurer), [@salindne](https://github.com/salindne) (Sebastian Lindner), and [@sqhell](https://github.com/sqhell) (Colin Sloss), the Daml CODEOWNERS per [`.github/CODEOWNERS`](../.github/CODEOWNERS). They own both [`ChainSafe/canton-ci`](https://github.com/ChainSafe/canton-ci) and the hosted Daml MCP server. +- **Covers.** ChainSafe-built Daml developer tooling: CI/CD for Daml projects (SDK + Canton install, sandbox / LocalNet test execution) and AI-assisted Daml authoring and review. This is a ChainSafe product; the handbook recommends it as the default Daml dev tooling — we dogfood our own tools. +- **Used by.** [`../languages/daml/developer.md`](../languages/daml/developer.md) (CI baseline + MCP setup), [`../operating-model/model-and-tool-selection.md`](../operating-model/model-and-tool-selection.md) (on-demand MCP loadout), and referenced from [`../languages/daml/architect.md`](../languages/daml/architect.md) and [`../languages/daml/reviewer.md`](../languages/daml/reviewer.md) for authorization analysis. +- **Coordination.** Internal ChainSafe product, owned by the Daml CODEOWNERS named above — the same people who review the handbook's Daml pages also build the tooling those pages recommend. The Daml MCP server incurs per-use cost — its use is subject to the [cost gate](../operating-model/gates-and-escalation.md#7-cost-and-external-resource-creation). + +### Zig Language & Standard Library Docs + +- **Source.** [ziglang.org](https://ziglang.org) — the official Zig documentation: the [Language Reference](https://ziglang.org/documentation/master/), the [Standard Library reference](https://ziglang.org/documentation/master/std/), and the [Learn](https://ziglang.org/learn/) section (in-depth overview, the [build-system guide](https://ziglang.org/learn/build-system/), code samples, and the Style Guide). Documentation under the Zig project's MIT license. Zig is pre-1.0: the `master` docs track the unreleased compiler, and each release carries its own versioned reference. +- **Maintainer.** External — the Zig Software Foundation. Internal coordination point: the Zig CODEOWNER ([@wemeetagain](https://github.com/wemeetagain) / [@matthewkeil](https://github.com/matthewkeil) / [@kalambet](https://github.com/kalambet)). +- **Covers.** The authoritative Zig language and standard-library reference: syntax, build modes and Illegal Behavior, the allocator model, error unions and `errdefer`, optionals, comptime and generics, the build system (`build.zig` / `build.zig.zon`), C interop, and the naming Style Guide. The handbook's Zig pages defer here for language semantics rather than re-deriving them — the same way the architect pages defer to `.invariants` and the Daml pages defer to the Canton docs. +- **Used by.** [`../languages/zig/architect.md`](../languages/zig/architect.md), [`../languages/zig/developer.md`](../languages/zig/developer.md), [`../languages/zig/reviewer.md`](../languages/zig/reviewer.md), [`../languages/zig/idioms.md`](../languages/zig/idioms.md), [`../languages/zig/gotchas.md`](../languages/zig/gotchas.md). ChainSafe's canonical Zig codebase is [lodestar-z](https://github.com/ChainSafe/lodestar-z) (consensus libraries for Lodestar). +- **Coordination.** External upstream, treated as canonical for Zig language semantics. Because Zig is pre-1.0, the language and std reshape across releases — re-anchor deep links and version-pinned guidance when bumping the project's Zig version; the weekly link-check run catches rot. + +### Rust References (Effective Rust + The Rust Book) + +- **Source.** [Effective Rust](https://effective-rust.com/) by David Drysdale (35 specific items; CC-BY-NC-ND 4.0) and [The Rust Programming Language](https://doc.rust-lang.org/book/) ("the Rust Book"; MIT / Apache-2.0). Together they are the canonical references for writing idiomatic, effective Rust. +- **Maintainer.** External — David Drysdale (Effective Rust) and the Rust project / community (the Book). Internal coordination point: the Rust CODEOWNER ([@LesnyRumcajs](https://github.com/LesnyRumcajs) / [@hanabi1224](https://github.com/hanabi1224)). +- **Covers.** Idiomatic Rust practice: type-driven design, idiomatic error types, `Option`/`Result` transforms, the newtype and builder patterns, standard traits and `Drop`/RAII, generics vs. trait objects, lifetimes and the borrow checker, avoiding `unsafe`, shared-state-parallelism hazards, SemVer and visibility, documenting public interfaces, Clippy, testing beyond unit tests, and FFI / `no_std`. The handbook's Rust pages apply these rather than re-deriving them. +- **Used by.** [`../languages/rust/architect.md`](../languages/rust/architect.md), [`../languages/rust/developer.md`](../languages/rust/developer.md), [`../languages/rust/reviewer.md`](../languages/rust/reviewer.md), [`../languages/rust/idioms.md`](../languages/rust/idioms.md), [`../languages/rust/gotchas.md`](../languages/rust/gotchas.md). ChainSafe's canonical Rust codebase is [Forest](https://github.com/ChainSafe/forest) (Filecoin). +- **Coordination.** External upstream, treated as canonical for idiomatic Rust. **Effective Rust is CC-BY-NC-ND** — the handbook references and credits specific items by number and link; it does not reproduce or adapt the text. Re-anchor item links if the upstream reorganizes; the weekly link-check catches rot. + +### Idiomatic Rust corpus + Rust API Guidelines + +- **Source.** [mre/idiomatic-rust](https://github.com/mre/idiomatic-rust) — Matthias Endler's peer-reviewed collection of articles, talks, and repos that teach concise, idiomatic Rust (released **CC0** / public domain; sortable index at [corrode.dev/idiomatic-rust](https://corrode.dev/idiomatic-rust/)). The highest-leverage standards it points to are the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) (the official idiomatic-API checklist), [Canonical's Rust Best Practices](https://canonical.github.io/rust-best-practices/), and [Elements of Rust](https://github.com/ferrous-systems/elements-of-rust). +- **Maintainer.** External — Matthias Endler (corpus) and the Rust library team (API Guidelines). Internal coordination point: the Rust CODEOWNER ([@LesnyRumcajs](https://github.com/LesnyRumcajs) / [@hanabi1224](https://github.com/hanabi1224)). +- **Covers.** Idiomatic, ergonomic Rust: flexible input types (`&str` / `&[T]` / `impl AsRef`), conversion and getter naming (`as_` / `to_` / `into_`, `iter` / `iter_mut` / `into_iter`, no `get_` prefix), enums over booleans to express intent, the common conversion traits (`From` / `Into` / `TryFrom` / `AsRef` / `Cow`), and simplicity over overengineering. Complements Effective Rust + The Rust Book; the handbook applies the principles rather than copying the corpus. +- **Used by.** [`../languages/rust/architect.md`](../languages/rust/architect.md), [`../languages/rust/developer.md`](../languages/rust/developer.md), [`../languages/rust/reviewer.md`](../languages/rust/reviewer.md), [`../languages/rust/idioms.md`](../languages/rust/idioms.md), [`../languages/rust/gotchas.md`](../languages/rust/gotchas.md). +- **Coordination.** External upstream. The corpus is CC0 (no attribution required; credited as a courtesy), and the Rust API Guidelines are the stable, authoritative reference for naming and API conventions. Re-anchor links if the upstream reorganizes; the weekly link-check catches rot. + +### Effective Python (idiomatic Python) + +- **Source.** [Effective Python](https://effectivepython.com/) by Brett Slatkin — *125 Specific Ways to Write Better Python* (3rd ed., Pearson Addison-Wesley; covers the language through Python 3.13). The book is copyrighted and not free online; the companion code is open at [bslatkin/effectivepython](https://github.com/bslatkin/effectivepython). The handbook references items by number and title, and does not reproduce the text. +- **Maintainer.** External — Brett Slatkin. Internal coordination point: the Python CODEOWNER ([@kalambet](https://github.com/kalambet)). +- **Covers.** Idiomatic, effective Python: Pythonic thinking and PEP 8, functions (keyword-only arguments, raising over returning `None`), comprehensions and generators, dataclasses and interfaces, robustness (`try`/`except`/`else`/`finally`, exception hygiene), concurrency choice (threads for blocking I/O, `asyncio`, true parallelism), performance (profile before optimizing; when to drop to a native extension or another language), and collaboration (docstrings, virtual environments, typing). The handbook's Python pages apply these within Python's internal-tooling scope at ChainSafe. +- **Used by.** [`../languages/python/architect.md`](../languages/python/architect.md), [`../languages/python/developer.md`](../languages/python/developer.md), [`../languages/python/reviewer.md`](../languages/python/reviewer.md), [`../languages/python/idioms.md`](../languages/python/idioms.md), [`../languages/python/gotchas.md`](../languages/python/gotchas.md). Python at ChainSafe is internal-tooling-grade (ops, Ansible, data/ML prototyping), not production services. +- **Coordination.** External upstream, treated as canonical for idiomatic Python. Cite by item number and title; re-check the numbers against the current edition when bumping the reference (the 3rd edition covers Python through 3.13). + +## Sources we expect to add + +Surfacing known candidates rather than fabricating coverage: + +- **Other internal artifacts to canonicalize.** When team members surface practices that exist in product repos or docs and could become canonical sources, they get added here with the original author credited (see [`./attribution.md`](./attribution.md)). +- **Language-specific upstream references.** Per-language reviewer pages may deep-link into language-community standards (e.g., Go's *Effective Go*, the TypeScript handbook). Those entries are added here when a page starts deferring to one. + +## Related + +- [`../NOTICE`](../NOTICE) — third-party attribution required under Apache 2.0 §4(d). Sources with upstream licenses or attribution requirements are also recorded there. +- [`./attribution.md`](./attribution.md) — the curatorial credit policy; how original authors are surfaced across the three-layer attribution model. +- [`./CONTRIBUTORS.md`](./CONTRIBUTORS.md) — the contributor index. Maintainers named here also appear there. +- [`../invariants/invariants-framework.md`](../invariants/invariants-framework.md) — the architecture/system-design deferral that grounded this catalog. +- [`../workflows/infrastructure-and-devops.md`](../workflows/infrastructure-and-devops.md) — the infrastructure deferral that grounded this catalog. diff --git a/scripts/build-pages.sh b/scripts/build-pages.sh new file mode 100755 index 0000000..b00b560 --- /dev/null +++ b/scripts/build-pages.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# scripts/build-pages.sh +# +# Assembles the Cloudflare Pages publish directory (`public/`). This is the +# build command for the Git-connected `engineering-handbook` Pages project: +# +# Build command: bash scripts/build-pages.sh +# Build output directory: public +# +# The static routing/header files (`public/_redirects`, `public/_headers`) are +# committed. Generated artifacts — currently just `llms.txt`, copied from the +# repo root so the root file stays the single source of truth — are produced +# here at build time and are git-ignored. Add further build steps below as the +# published surface grows (extra assets, generated pages, minification, etc.). +# +# Run from anywhere; it cd's to the repo root itself. +# +# Exit codes: +# 0 — publish dir assembled. +# 1 — a required source file is missing. + +set -euo pipefail + +cd "$(dirname "$0")/.." + +PUBLIC_DIR="public" + +if [[ ! -f llms.txt ]]; then + echo "build-pages: llms.txt not found at repo root" >&2 + exit 1 +fi + +mkdir -p "$PUBLIC_DIR" + +# --- generated artifacts ------------------------------------------------------ +cp llms.txt "$PUBLIC_DIR/llms.txt" +echo "build-pages: copied llms.txt -> $PUBLIC_DIR/llms.txt" + +# Add further publish steps here. +# ------------------------------------------------------------------------------ + +echo "build-pages: publish dir ready:" +ls -1 "$PUBLIC_DIR" diff --git a/scripts/check-skills-sync.sh b/scripts/check-skills-sync.sh new file mode 100755 index 0000000..88a64ea --- /dev/null +++ b/scripts/check-skills-sync.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# scripts/check-skills-sync.sh +# +# Verifies that the set of skills in `skills/` matches the set referenced in +# `llms.txt`. Drift between the two is a CI failure — the index +# and the bundles ship together, not separately. +# +# Run from the repo root: +# bash scripts/check-skills-sync.sh +# +# Exit codes: +# 0 — in sync. +# 1 — drift detected (skill present but not indexed, or indexed but missing). +# 2 — usage / environment error. + +set -euo pipefail + +cd "$(dirname "$0")/.." + +if [[ ! -d skills ]]; then + echo "ERROR: skills/ directory not found. Run from repo root." >&2 + exit 2 +fi +if [[ ! -f llms.txt ]]; then + echo "ERROR: llms.txt not found at repo root." >&2 + exit 2 +fi + +# Skills on disk: every directory under skills/ that contains a SKILL.md. +on_disk=$( + for d in skills/*/; do + if [[ -f "$d/SKILL.md" ]]; then + basename "$d" + fi + done | sort -u +) + +# Skills indexed in llms.txt: URLs of the form +# .../skills//SKILL.md +in_index=$( + grep -oE 'skills/[a-z0-9-]+/SKILL\.md' llms.txt \ + | awk -F'/' '{print $2}' \ + | sort -u +) + +# Identify drift. +missing_from_index=$(comm -23 <(echo "$on_disk") <(echo "$in_index") || true) +missing_from_disk=$(comm -13 <(echo "$on_disk") <(echo "$in_index") || true) + +status=0 + +if [[ -n "$missing_from_index" ]]; then + echo "ERROR: skill(s) present in skills/ but not indexed in llms.txt:" + echo "$missing_from_index" | sed 's/^/ - /' + status=1 +fi + +if [[ -n "$missing_from_disk" ]]; then + echo "ERROR: skill(s) referenced in llms.txt but missing from skills/:" + echo "$missing_from_disk" | sed 's/^/ - /' + status=1 +fi + +if [[ $status -eq 0 ]]; then + count=$(echo "$on_disk" | wc -l | tr -d ' ') + echo "OK: $count skills, all synced between skills/ and llms.txt." +fi + +exit $status diff --git a/scripts/tune-skill-description.sh b/scripts/tune-skill-description.sh new file mode 100755 index 0000000..7c5a6ff --- /dev/null +++ b/scripts/tune-skill-description.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# scripts/tune-skill-description.sh +# +# Push-button on-ramp for the OPT-IN skill description-tuning loop. +# Wraps Anthropic skill-creator's `python -m scripts.run_loop` with the +# ChainSafe conventions baked in (Opus by default, sane flags, scratch +# outputs kept out of the repo). +# +# This is the executable form of workflows/skill-description-tuning.md. +# Read that runbook for the policy and the why. In one line: opt-in, +# local-only, ~30-45 min wall-clock on Opus, real Anthropic API spend. +# Not a CI gate. Run it only when you have a reason to. +# +# Usage: +# bash scripts/tune-skill-description.sh [options] +# +# A directory under skills/ (e.g. chainsafe-go-reviewer) +# or a path to a skill directory containing SKILL.md. +# +# Options: +# --eval-set PATH Eval-set JSON. Default: +# workflows/skill-description-tuning/.eval-set.json +# --model ID Optimizer model. Default: claude-opus-4-6 (env: TUNE_MODEL). +# --max-iterations N Improve/re-evaluate cycles. Default: 5. +# --results-dir DIR Where results.json/report.html/log.txt land. Default: a +# timestamped scratch dir OUTSIDE the repo (env: TUNE_RESULTS_DIR). +# --dry-run Print the resolved command without running it. +# -h, --help Show this help. +# +# Environment overrides: +# TUNE_MODEL Default optimizer model. +# TUNE_RESULTS_DIR Base dir for scratch outputs. +# SKILL_CREATOR_DIR Path to the skill-creator package (auto-detected if unset). +# +# Exit codes: 0 ok / dry-run · 1 runtime failure · 2 usage or environment error. + +set -euo pipefail + +# --- locate the repo root (this script lives in /scripts/) ---------------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# --- defaults ------------------------------------------------------------------- +MODEL="${TUNE_MODEL:-claude-opus-4-6}" +MAX_ITER=5 +EVAL_SET="" +RESULTS_DIR="" +DRY_RUN=0 + +usage() { sed -n '2,40p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; } + +die() { printf 'ERROR: %s\n' "$*" >&2; exit 2; } + +# --- parse args ----------------------------------------------------------------- +SKILL_ARG="" +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) usage; exit 0 ;; + --dry-run) DRY_RUN=1; shift ;; + --eval-set) EVAL_SET="${2:-}"; [[ -n "$EVAL_SET" ]] || die "--eval-set needs a path"; shift 2 ;; + --model) MODEL="${2:-}"; [[ -n "$MODEL" ]] || die "--model needs an id"; shift 2 ;; + --max-iterations) MAX_ITER="${2:-}"; [[ "$MAX_ITER" =~ ^[0-9]+$ ]] || die "--max-iterations needs an integer"; shift 2 ;; + --results-dir) RESULTS_DIR="${2:-}"; [[ -n "$RESULTS_DIR" ]] || die "--results-dir needs a path"; shift 2 ;; + --) shift; break ;; + -*) die "unknown option: $1 (try --help)" ;; + *) [[ -z "$SKILL_ARG" ]] || die "unexpected extra argument: $1"; SKILL_ARG="$1"; shift ;; + esac +done + +[[ -n "$SKILL_ARG" ]] || { usage; echo; die "no skill specified"; } + +# --- resolve the skill path ----------------------------------------------------- +if [[ "$SKILL_ARG" == */* || -d "$SKILL_ARG" ]]; then + SKILL_PATH="$(cd "$SKILL_ARG" 2>/dev/null && pwd || true)" + [[ -n "$SKILL_PATH" ]] || die "skill path not found: $SKILL_ARG" +else + SKILL_PATH="$REPO_ROOT/skills/$SKILL_ARG" +fi +SKILL_NAME="$(basename "$SKILL_PATH")" +[[ -f "$SKILL_PATH/SKILL.md" ]] || die "no SKILL.md under: $SKILL_PATH + Pass a directory name under skills/ (e.g. chainsafe-go-reviewer) or a full path." + +# --- resolve the eval set ------------------------------------------------------- +if [[ -z "$EVAL_SET" ]]; then + EVAL_SET="$REPO_ROOT/workflows/skill-description-tuning/$SKILL_NAME.eval-set.json" +fi +if [[ ! -f "$EVAL_SET" ]]; then + die "eval set not found: $EVAL_SET + Draft one from the template: + workflows/skill-description-tuning/eval-set.template.json + then pass it with --eval-set, or save it at the default path above." +fi + +# --- locate the skill-creator package ------------------------------------------ +if [[ -z "${SKILL_CREATOR_DIR:-}" ]]; then + SKILL_CREATOR_DIR="$HOME/.claude/skills/skill-creator" + if [[ ! -f "$SKILL_CREATOR_DIR/scripts/run_loop.py" ]]; then + found="$(find "$HOME/.claude" -name run_loop.py -path '*skill-creator*' 2>/dev/null | head -1)" + [[ -n "$found" ]] && SKILL_CREATOR_DIR="$(cd "$(dirname "$found")/.." && pwd)" + fi +fi +[[ -f "$SKILL_CREATOR_DIR/scripts/run_loop.py" ]] || die "skill-creator's run_loop.py not found. + Looked under: $SKILL_CREATOR_DIR/scripts/run_loop.py + Set SKILL_CREATOR_DIR to the skill-creator package directory." + +# --- preflight: the loop shells out to \`claude -p\` ----------------------------- +command -v python3 >/dev/null 2>&1 || die "python3 not on PATH." +if ! command -v claude >/dev/null 2>&1; then + echo "WARNING: the \`claude\` CLI is not on PATH. The loop calls \`claude -p\` as a" >&2 + echo " subprocess and will fail without it. Install Claude Code first." >&2 +fi + +# --- default scratch results dir, OUTSIDE the repo ------------------------------ +if [[ -z "$RESULTS_DIR" ]]; then + RESULTS_DIR="${TUNE_RESULTS_DIR:-${TMPDIR:-/tmp}/skill-tuning}/${SKILL_NAME}-$(date +%Y%m%d-%H%M%S)" +fi + +# --- assemble the command ------------------------------------------------------- +CMD=(python3 -m scripts.run_loop + --eval-set "$EVAL_SET" + --skill-path "$SKILL_PATH" + --model "$MODEL" + --max-iterations "$MAX_ITER" + --verbose + --results-dir "$RESULTS_DIR") + +echo "------------------------------------------------------------------" +echo " skill : $SKILL_NAME" +echo " skill path : $SKILL_PATH" +echo " eval set : $EVAL_SET" +echo " model : $MODEL" +echo " max-iter : $MAX_ITER" +echo " results dir : $RESULTS_DIR" +echo " run from : $SKILL_CREATOR_DIR" +echo "------------------------------------------------------------------" +printf ' command : (cd %q && ' "$SKILL_CREATOR_DIR" +printf '%q ' "${CMD[@]}" +printf ')\n' +echo "------------------------------------------------------------------" + +if [[ "$DRY_RUN" -eq 1 ]]; then + echo "[dry-run] not executing. Drop --dry-run to run for real (~30-45 min on Opus)." + exit 0 +fi + +echo "OPT-IN loop: local-only, ~30-45 min on Opus, real Anthropic API spend. Ctrl-C to abort." +mkdir -p "$RESULTS_DIR" +cd "$SKILL_CREATOR_DIR" +exec "${CMD[@]}" diff --git a/sidebars.js b/sidebars.js deleted file mode 100644 index 8443255..0000000 --- a/sidebars.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ - -// @ts-check - -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const sidebars = { - // By default, Docusaurus generates a sidebar from the docs folder structure - tutorialSidebar: [ - { - type: 'autogenerated', - dirName: '.' - }, - { - type: 'link', - href: "https://chainsafe.io/about-us#join-us", - label: "Join ChainSafe", - className: "join-us" - } -], - - - - // But you can create a sidebar manually - /* - tutorialSidebar: [ - { - type: 'category', - label: 'Tutorial', - items: ['hello'], - }, - ], - */ -}; - -module.exports = sidebars; diff --git a/skills/chainsafe-code-review/SKILL.md b/skills/chainsafe-code-review/SKILL.md new file mode 100644 index 0000000..04aa9aa --- /dev/null +++ b/skills/chainsafe-code-review/SKILL.md @@ -0,0 +1,108 @@ +--- +name: chainsafe-code-review +description: Universal code-review framework at ChainSafe — language-agnostic principles plus the two reviewer modes (operator-reviewing-agent and agent-reviewing-PR). Use this skill whenever the user is reviewing a PR, asking for a code review, checking how to review, deciding what to flag vs fix, or handling a review disagreement. EVEN IF the user does not explicitly ask for "review" — triggers on "look at this PR", "check this diff", "what should I look for in this PR", "is this code OK", "how do I review", "approve this PR", "block this PR", "review disagreement", "review comments", "nit prefix", "should I flag this". For language-specific review (Go, Rust, TypeScript, Solidity), additionally load the corresponding language reviewer skill (chainsafe--reviewer). For PR authoring (outgoing), use chainsafe-pr-author. +metadata: + type: workflow + source: workflows/code-review.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Code Review + +Universal review framework at ChainSafe. Two reviewer modes; language-specific surface lives in the language reviewer skills. Full reference: [`workflows/code-review.md`](../../workflows/code-review.md). + +## Universal principles + +- **Approve when the change improves overall code health.** "Perfect" isn't the bar. Forward progress against current quality is. +- **Technical facts and data overrule opinions and personal preferences.** If two designs are equally valid, respect the author's choice. +- **Authority ladder:** style guide > current codebase conventions > author preference. +- **Prefix nits.** Taste/preference/teaching comments get `nit:` prefix so author knows they can ignore. +- **Note the good things.** Reviews skewed toward only-mistakes train authors to be defensive. + +## What to look for + +- **Design.** Do the pieces fit? Readability beats DRY. +- **Functionality.** Does the code do what was intended? Is the intent good for users + future developers? +- **Complexity.** Especially over-engineering. Solve the problem you have now. +- **Naming.** Long enough to communicate, short enough to read. +- **Comments.** Explain *why*, not *what*. +- **Every line.** Look at every assigned line. +- **Context.** Sometimes pull the branch. + +## Speed of review + +Default service level: **review within one business day**. If you can't, say so and propose when you can. If author is blocked on critical path, drop other work for it. + +This applies to agent reviewers too — agents that "review eventually" defeat the purpose. + +## Mode (a) — Operator reviewing agent output + +Most ChainSafe PRs in the v2 era have an agent in the author chair. What to verify: + +- **The plan matches the diff.** Drift between linked `plan.md` and the diff is the most common quiet failure. +- **Fabrication.** Imports that don't exist, wrong-signature function calls, broken handbook page references. Verify. +- **Silent scope creep.** Files in the diff not in the original plan — PR description should name each with a reason. +- **Over-eager refactor.** Each unrelated improvement is its own PR. +- **Generic comments.** Cut comments that restate what the code does. +- **Test theatre.** Tests asserting "function was called" rather than its effect. Read test bodies. +- **Type laxity.** `any`, `unknown`, untyped returns, missing error handling. +- **Undeclared operational contract.** Env vars, config, secrets, schema/migrations, ports, or a public signature changed without an Operational impact declaration — the change that becomes Infra's problem later (Engineering Invariant 8). + +### When to demand re-plan vs accept vs reject + +- **Re-plan:** diff drifted from plan; agent made unapproved design choices; unrelated changes included; fabrication present. Go back to the plan; don't patch. +- **Accept with notes:** minor issues that don't change the shape. +- **Reject entirely:** wrong direction. Close PR; reopen with fresh plan. + +### What the operator cannot delegate + +- The merge decision. +- The judgment on whether HARD FAIL findings are properly addressed. +- The sign-off that the audit trail is sufficient. + +## Mode (b) — Agent reviewing a PR + +### Checklist + +- Run lint/type-check/test against the branch; report failures. +- Diff against the linked plan or spec; flag deviations. +- Apply the relevant language reviewer skill (chainsafe--reviewer). +- Check PR-description completeness (what/why/acceptance/**operational impact**/AI declaration/scope flags); flag undeclared env-var / config / schema / public-signature changes. +- Verify references are real. +- Flag missing or thin commit messages. + +### Flag vs fix in place + +- **Flag, don't fix:** design choices, complexity, naming, anything subjective. +- **Suggest with code suggestion:** trivial nits (typos, lint, formatting). +- **Never fix and push to author's branch** without explicit operator authorization. + +### How to phrase comments + +- Lead with concern, not fix. +- Cite the rule when there is one. +- Use `nit:` for taste-level. +- Avoid "you" framing for design comments. + +### When the agent refuses to review + +Escalate rather than reviewing if: + +- HARD FAIL findings the agent can't evaluate (mismatched tool). +- PR description missing — nothing to review against. +- Diff touches code the agent has been told not to operate on. + +## When reviews go wrong + +- **Stale review** (no response >3 business days): reviewer pings once; if no response, CODEOWNER unblocks. +- **Heated thread:** take it off the PR. 5-minute call beats 30-comment argument. +- **Design disagreement:** not the reviewer's call to overrule. Escalate to CODEOWNER or curator. +- **Author pushes for merge despite open comments:** CODEOWNER decides. The reviewer isn't the merge gate alone. + +## Related + +- Full reference: [`workflows/code-review.md`](../../workflows/code-review.md) +- Language reviewer skills: `chainsafe-go-reviewer`, `chainsafe-rust-reviewer`, `chainsafe-typescript-reviewer`, `chainsafe-solidity-reviewer` +- Counterpart skill: `chainsafe-pr-author` +- Invariants: [`invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md) +- HARD FAIL semantics: [`operating-model/gates-and-escalation.md`](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) diff --git a/skills/chainsafe-go-architect/SKILL.md b/skills/chainsafe-go-architect/SKILL.md new file mode 100644 index 0000000..9662125 --- /dev/null +++ b/skills/chainsafe-go-architect/SKILL.md @@ -0,0 +1,69 @@ +--- +name: chainsafe-go-architect +description: Architectural guidance for designing Go services and systems at ChainSafe (Gossamer and Go projects). Use whenever the user starts a new Go service, designs a Go module, writes an ADR for Go work, picks concurrency patterns, decides on a public API surface, structures a Go workspace, or makes any Go-specific architectural decision. EVEN IF the user does not explicitly say "architecture" — triggers on "design a Go service", "new Go module", "Go project layout", "concurrency model in Go", "public API for this Go package", "ADR for Go", "internal vs pkg", "channels or mutexes", "interface design in Go", "context propagation", "goroutine ownership". Defers to `.invariants` for invariants. Do NOT use for line-level Go coding (use chainsafe-go-developer) or Go PR review (use chainsafe-go-reviewer). +metadata: + type: role-workflow + language: go + role: architect + source: languages/go/architect.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Go Architect + +Use this when designing Go systems at ChainSafe — Gossamer-shaped work or any Go service/library. + +## Operating context + +You are the architect role for Go work. The architectural framework (invariant naming, lifecycle, testability) is `.invariants`; consult [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) and [boorich/.invariants-starter-kit](https://github.com/boorich/.invariants-starter-kit) before proposing a design. This skill covers what is Go-specific *under* that framework. + +The full reference is [`languages/go/architect.md`](../../languages/go/architect.md). Load that file for the complete guidance. + +## Key Go-specific decisions + +When designing a Go system or module, address: + +- **Project layout.** `cmd//main.go` for binaries (minimal logic, just wiring). `internal/` is the default home for all non-library code. `pkg/` is *limited and stable* — a package moves there only when it has proven stable with deep test coverage and the team commits to semver. +- **Public surface discipline.** Start everything in `internal/`. Export only when keeping it private costs more than locking in a public API. +- **Concurrency model.** + - Lifetimes via `context.Context`. Every long-running operation accepts `ctx` as the first parameter. + - Channels for ownership transfer; mutexes for shared state. Mixing patterns in one component is a smell. + - Bounded concurrency — never unbounded `go func()` spawn. Use worker pools, semaphores, or `errgroup` with limits. + - No package-level mutable state. +- **Error model.** Errors are values. Sentinel errors with `errors.Is`, typed errors with `errors.As`. `fmt.Errorf("...: %w", err)` to preserve context. Never `panic` for non-fatal errors. +- **Dependency injection.** Functional options or explicit `Settings` structs. No globals, no hidden singletons. +- **Defensive network & disk I/O.** Every external network call, database query, or stream reader must have an explicit timeout — `context.WithTimeout` on the call, or socket/read deadlines where context isn't threaded through. A `ctx` without a deadline is not a timeout; an unbounded read is a hang waiting to happen. +- **API & storage isolation.** Keep internal domain models separate from external transport layers. Define Data Transfer Objects (DTOs) for external APIs and database schemas, and map them explicitly to internal models at the boundary. This is for *external* edges — don't introduce DTOs between internal packages. + +## ADR template for Go work + +Every non-trivial Go ADR should cover: + +- Public surface: what's exported, why. +- Concurrency commitments: goroutine ownership, context propagation, cancellation. +- Error contract: which errors callers see, sentinel vs typed vs wrapped. +- Resource ownership: connections, files, goroutines — who closes them, when. +- Invariants impacted: deep links into `.invariants`. + +## Defer to `.invariants` for + +- The invariant definitions and lifecycle. +- Cross-service contracts. +- Failure-mode invariants. + +This skill covers Go-specific *shape*; the framework is upstream. + +## Anti-patterns to flag at design time + +- Wide `pkg/` directory. +- Goroutines without `context.Context`. +- `interface{}` / `any` crossing module boundaries. +- `init()` functions doing work. +- Reach for `sync.Map` when a domain-specific structure would do. + +## Related + +- Full reference: [`languages/go/architect.md`](../../languages/go/architect.md) +- Sister roles: `chainsafe-go-developer` (implementation), `chainsafe-go-reviewer` (PR review) +- Workflow: `chainsafe-research-plan-implement` for the design-to-implementation flow +- Framework: [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) diff --git a/skills/chainsafe-go-developer/SKILL.md b/skills/chainsafe-go-developer/SKILL.md new file mode 100644 index 0000000..a450b52 --- /dev/null +++ b/skills/chainsafe-go-developer/SKILL.md @@ -0,0 +1,103 @@ +--- +name: chainsafe-go-developer +description: Idiomatic Go development at ChainSafe — implementation-level guidance for writing Go code in Gossamer and other Go projects. Use this skill whenever the user is writing Go code, asking how to do something in Go, debugging Go, picking between Go patterns at the line/function level, setting up Go tooling, configuring golangci-lint, writing Go tests, mocking interfaces in Go, dealing with context propagation, structuring errors with %w, or any other concrete Go coding task. EVEN IF the user does not say "Go" explicitly but the file in scope is .go. Triggers on "write a Go function", "implement in Go", "how do I X in Go", "fix this Go code", "test this Go function", "mock this interface", "lint my Go", "Go CI setup", "context handling", "gomock", "table-driven test", "%w vs %v", "error wrapping in Go", ".golangci.yml". Do NOT use for Go architectural design (use chainsafe-go-architect) or Go PR review (use chainsafe-go-reviewer). +metadata: + type: role-workflow + language: go + role: developer + source: languages/go/developer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Go Developer + +Idiomatic Go implementation at ChainSafe. The full reference is [`languages/go/developer.md`](../../languages/go/developer.md); load that file for complete guidance. This skill is the operational summary. + +## Tooling baselines + +- **Linter:** [`golangci-lint`](https://golangci-lint.run/) pinned to a specific version in CI. Use `.golangci.yml` at repo root. +- **Mocking:** `golang/mock` (gomock). Per-package, kept in `mocks_test.go` (generated) + `mocks_generate_test.go` (the `//go:generate` directive). Never export mocks. +- **Modules:** `go.mod` + `go.sum` committed; `go.sum` never edited by hand. +- **Race detector:** `go test -race` in CI for any package touching concurrency. + +## Mock discipline (most-flagged in review) + +- **No `gomock.Any()`.** Use concrete arguments or custom matchers. +- **No `.AnyTimes()`.** State exact call counts. +- **Always set `.Return(...)`** for functions that return. +- For subtests, build a fresh `gomock.NewController(t)` per subtest. Mocks built from parent `t` leak between subtests. +- Use functional mock builders (`func(ctrl *gomock.Controller) Fetcher`) for table-driven tests with mocks. + +## Argument passing + +- **Default to pass-by-value.** Reduces nil-risk; clearer behavior. +- **Slices:** by value if you mutate elements; `*[]T` only to change slice length. +- **Maps, channels, most interfaces:** always by value (pointers under the hood). +- **Structs:** by value if performance allows; by pointer if you need to mutate non-pointer fields or if >80 bytes. +- **Mutexes:** always by pointer. + +## Panic + +- `panic` is **only** for programmer error — impossible states, sentinel-invariant violation, default switch on enum. +- I/O errors, network errors, parse failures, user input — return `error`. Never panic. +- `recover` only in test code (`assert.PanicsWithValue`). + +## Context + +```go +func DoThing(ctx context.Context, arg T) (Result, error) { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + // ... +} +``` + +`ctx` is the first parameter. Always. Never `context.TODO()` in committed code. Pass `ctx` down; do not store in structs except in narrow framework cases. + +Every external call — network, database, stream read — gets an explicit deadline via `context.WithTimeout` (or a socket/read deadline where `ctx` isn't threaded through). An inherited `ctx` with no deadline is not a timeout. + +## Errors + +```go +data, err := fetch(ctx, url) +if err != nil { + return fmt.Errorf("fetching %s: %w", url, err) +} +``` + +- `%w` to preserve the chain. +- Lowercase first letter, no trailing punctuation. +- Context before the error: `"fetching %s: %w"`, not `"%w while fetching"`. +- Callers use `errors.Is` / `errors.As`. + +## Testing + +- Table-driven tests for >1 case. Map-keyed for free naming; subtests for isolation. +- `t.Parallel()` when tests don't share mutable state. +- `go test -race ./...` for race-sensitive packages. + +## CI baseline + +- `go vet ./...` +- `gofmt -l .` → no output +- `golangci-lint run` +- `go test -race ./...` +- `go build ./...` +- Mocks regenerated; `git diff --exit-code` confirms no drift. + +## Anti-patterns + +- `panic` for non-fatal errors. +- Goroutines without `context.Context`. +- `init()` connecting to external services. +- `interface{}` / `any` parameters (use generics where possible). +- Mocks with `gomock.Any()`. +- Package-level mutable state. + +## Related + +- Full reference: [`languages/go/developer.md`](../../languages/go/developer.md) +- Idioms cheat sheet: [`languages/go/idioms.md`](../../languages/go/idioms.md) +- Gotchas: [`languages/go/gotchas.md`](../../languages/go/gotchas.md) +- Sister roles: `chainsafe-go-architect`, `chainsafe-go-reviewer` +- Workflow: `chainsafe-research-plan-implement` diff --git a/skills/chainsafe-go-reviewer/SKILL.md b/skills/chainsafe-go-reviewer/SKILL.md new file mode 100644 index 0000000..6d80a48 --- /dev/null +++ b/skills/chainsafe-go-reviewer/SKILL.md @@ -0,0 +1,92 @@ +--- +name: chainsafe-go-reviewer +description: Language-specific PR review for Go code at ChainSafe (Gossamer and Go-language projects). Use this skill whenever the user is reviewing a Go PR, asking for a Go code review, checking Go code for common mistakes, verifying a Go diff against ChainSafe conventions, looking for goroutine leaks, error-handling problems, panic misuse, or mock-discipline issues. EVEN IF the user does not explicitly ask for "Go review" — triggers on "review this Go PR", "is this Go code correct", "check this Go function", "look for issues in this Go file", "review the diff", "what's wrong with this Go", "lint review Go", "concurrency review", "context propagation review". Findings emit at SOFT WARNING severity (agent reports; operator decides on merge); the agent never blocks. Do NOT use for Go design decisions (use chainsafe-go-architect) or Go implementation guidance (use chainsafe-go-developer). +metadata: + type: role-workflow + language: go + role: reviewer + severity-tier: SOFT WARNING + source: languages/go/reviewer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Go Reviewer + +Reviewer skill for Go PRs. Operates under [`workflows/code-review.md`](../../workflows/code-review.md) (universal principles) and emits findings at **SOFT WARNING** severity — the agent flags, the operator decides on merge. The agent never blocks. The full reference is [`languages/go/reviewer.md`](../../languages/go/reviewer.md). + +## Severity tier + +**SOFT WARNING.** Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), Go is not in the security-critical-language list. HARD FAIL is reserved for Solidity and Daml. + +## Checklist + +### Concurrency + +- `context.Context` propagation — every I/O or potentially-blocking function takes `ctx` as first parameter and uses it. +- Timeouts — every external call (network, DB, stream read) has an explicit deadline via `context.WithTimeout` or a socket/read deadline. An inherited `ctx` with no deadline is not a timeout; flag it. +- Goroutine ownership — every `go func()` has a clear exit (ctx.Done, wg.Done, bounded scope). +- Unbounded concurrency — `for ... { go work() }` without limits is a bug for large inputs. +- Data races — shared mutable state across goroutines needs a mutex or channel; `go test -race` runs. +- Channel direction in function signatures (`chan<- T`, `<-chan T`). + +### Errors + +- `%w` (not `%v`) when wrapping with `fmt.Errorf`. +- `errors.Is` / `errors.As` at call sites, not direct `==` on errors. +- Sentinel errors documented as contract. +- No swallowed errors — `_ = something()` deserves a comment. + +### Panic + +- `panic` only on programmer error (impossible states, sentinel violations). +- I/O / network / parse / user input — never panic. Returns error. +- `recover` is suspicious in production paths. + +### Layout + +- New packages default to `internal/`. Move to `pkg/` only with explicit justification. +- Package names: single word, descriptive, no `utils`/`helpers`/`common`. +- `main.go` is minimal; logic lives elsewhere. +- Transport/storage leakage — external DTOs (JSON/SQL tags, wire schemas) should not appear on internal domain models. Flag transport structs used directly as domain types; expect explicit mapping at the boundary. + +### Testing + +- Race-sensitive code under `go test -race`. +- Mocks regenerated, no drift (`git diff --exit-code` after regenerate). +- No `gomock.Any()` or `.AnyTimes()` without explicit justification. +- Subtests build their own `gomock.NewController(t)`. +- Table-driven tests for >1 case. + +### Arguments and types + +- Pass-by-value default; pointer receivers only with reason. +- `interface{}` / `any` parameters — flag; suggest generics. +- No package-level mutable state. + +### Lint and format + +- `gofmt` clean. +- `go vet` clean. +- No `//nolint` without a comment. + +## Refusal + +The reviewer skill refuses to review and escalates if: + +- Diff contains non-Go code (use the right reviewer skill). +- PR description is empty (nothing to verify against). +- Diff touches packages out of session scope. + +## Phrasing + +- Lead with concern, not fix: "This goroutine has no exit path. What's the intended lifetime?" +- Cite the rule when relevant. +- `nit:` for taste-level comments. +- Avoid "you" framing for design comments. + +## Related + +- Full reference: [`languages/go/reviewer.md`](../../languages/go/reviewer.md) +- Gotchas (review screening surface): [`languages/go/gotchas.md`](../../languages/go/gotchas.md) +- Universal review framework: [`workflows/code-review.md`](../../workflows/code-review.md) +- Sister roles: `chainsafe-go-architect`, `chainsafe-go-developer` diff --git a/skills/chainsafe-pr-author/SKILL.md b/skills/chainsafe-pr-author/SKILL.md new file mode 100644 index 0000000..64ee340 --- /dev/null +++ b/skills/chainsafe-pr-author/SKILL.md @@ -0,0 +1,80 @@ +--- +name: chainsafe-pr-author +description: How to open and shepherd a pull request at ChainSafe — language-agnostic PR authoring guidance. Use this skill whenever the user is opening a PR, drafting a PR description, deciding how to scope a PR, handling reviewer comments, structuring commits within a PR, declaring AI-generated content, or shepherding a PR through review. EVEN IF the user does not explicitly say "PR" — triggers on "open a pull request", "draft a PR description", "what should I put in the PR", "PR is too big", "split this PR", "how do I respond to this reviewer comment", "self-resolve threads", "AI declaration in PR", "scope drift", "commit message", "stack of PRs". For the actual code-change workflow that produces the PR, use chainsafe-research-plan-implement. For PR review (incoming), use chainsafe-code-review. +metadata: + type: workflow + source: workflows/pr-authoring.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# PR Authoring + +How to open and shepherd a PR at ChainSafe. Language-agnostic; language-specific reviewer surface is in the language skills. Full reference: [`workflows/pr-authoring.md`](../../workflows/pr-authoring.md). + +## Branching + +Branch naming follows OneFlow: personal feature branches are `/`. PRs target `main` unless your CODEOWNERS designate otherwise. + +## Default workflow for non-trivial PRs + +For any substantive code change, the canonical workflow is the `chainsafe-research-plan-implement` skill: **research → plan → annotate (1–6 rounds) → implement**. This skill enforces a human-approved plan before any code change. + +When the PR author is an agent, the skill is loaded and followed. When human, the same shape applies — research artifact when context is non-obvious, plan when work touches more than one file, accept annotation, then commit code. + +## Small, focused, self-contained + +- **One PR, one self-contained change.** Reviewable in ~10 minutes. +- **Separate refactors from features/fixes.** A refactor is its own PR (exception: tiny refactor genuinely entangled with the feature, <~50 lines). +- **Renames, deletions, generated-code PRs can be large** — they trade scope-width for shallow review depth. +- **Stack PRs** for sequential work rather than one big PR. + +The right question: *is this change related to the PR's stated goal, or can it live on its own?* + +## PR description required fields + +- **What changed** — 2-3 sentences, plain language. +- **Why it changed** — link to issue/ADR/spec or write inline. +- **Acceptance criteria or test plan** — what "done" looks like; how to verify. +- **Out-of-scope notes** — anything the reader expects to see in the diff but doesn't. +- **Operational impact** — env vars, secrets, config, schema/migrations, or ports added or changed; backwards-compat impact; what Infra or the owning team must do. "None" is valid but must be answered (Engineering Invariant 8; contract-altering changes trip the operational-contract gate). + +## Agent-era additions + +- **AI-generated declaration.** If an agent drafted substantive portion, say so. "Drafted by Claude Code following `chainsafe-research-plan-implement`; reviewed by @author" works. +- **Link to the plan artifact** (research.md, plan.md) so reviewers see what the operator approved. +- **Assumption surfacing** — non-obvious assumptions the agent made without explicit operator confirmation, called out for review. +- **Scope drift flags** — any file touched that wasn't in the original ticket scope, named with a one-line reason. This is the [scope-discipline invariant](../../invariants/agent-era-invariants.md#1-no-silent-edits-outside-the-operator-named-scope) made visible. + +## Commits + +- **Commit messages describe intent**, not just diff. +- **Responses to reviewer comments land as new commits**, not as edits to existing ones. +- **Squash on merge** if the repo's convention is squash; otherwise let the commit train through. Defer to CODEOWNERS. + +## Reviewer requests + +- CODEOWNERS auto-routes; don't override unless adding to that list. +- No CODEOWNERS? Use the two-team pattern: `-admins` for senior, `` for peer. +- Blocked on review >1 business day → ping reviewer in team channel. + +## Handling reviewer comments + +- **Address every comment.** Either change the code or reply explaining the choice. +- **Don't self-resolve threads** unless the change is trivial (typo, lint). Reviewer resolves their own comments. +- **Disagreements escalate.** Get a third opinion from CODEOWNER or curator. Don't merge through a disagreement. +- **For agents:** when an operator review surfaces a misunderstanding of the original plan, update the `plan.md` first, then re-implement the affected slice. Keep the plan as source of truth. + +## Anti-patterns + +- The mega-PR. "It's all related" — usually it isn't. +- The drive-by refactor. +- The silent re-scope. +- The agent ghost-author (no AI declaration). +- The "fixed it" reply (no detail). + +## Related + +- Full reference: [`workflows/pr-authoring.md`](../../workflows/pr-authoring.md) +- The workflow itself: `chainsafe-research-plan-implement` +- Counterpart skill: `chainsafe-code-review` +- Invariants: [`invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md) (especially §1, §8) diff --git a/skills/chainsafe-research-plan-implement/SKILL.md b/skills/chainsafe-research-plan-implement/SKILL.md new file mode 100644 index 0000000..da85c88 --- /dev/null +++ b/skills/chainsafe-research-plan-implement/SKILL.md @@ -0,0 +1,147 @@ +--- +name: chainsafe-research-plan-implement +description: Research-first coding workflow that gates ALL non-trivial code changes behind a human-approved written plan. Use this skill whenever the user asks for any substantive code change — implementing a feature, refactoring, fixing a multi-file bug, adding an endpoint, integrating a service, migrating between systems, wiring something up, or changing how an existing system works — EVEN IF they do not explicitly ask for "research" or a "plan." The skill enforces three artifacts (research.md, plan.md, annotated plan) that survive context compaction and gate implementation behind explicit operator approval. Triggers on phrases like "implement", "refactor", "fix this bug", "add a feature", "change how X works", "integrate", "migrate from X to Y", "rewrite", "restructure", "wire up", "build out", "extend", "modify the X system", "I want to add", "let's change". Do NOT use for one-line typo fixes, pure formatting, lint-only changes, or other trivial single-file edits where research would be overkill. +metadata: + type: workflow + origin: ~/.config/agents/research-plan-implement.md + based-on: Boris Tane — https://boristane.com/blog/how-i-use-claude-code/ + curator: Peter Kalambet (ChainSafe CTO) + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +## Core principle + +**Never write code until the human has reviewed and approved a written plan.** + +Separate thinking from typing. Research prevents ignorant changes. The plan prevents wrong changes. The annotation cycle injects human judgement. Implementation runs without interruption once every decision has been made. + +--- + +## Workflow pipeline + +``` +Research → Plan → Annotate (repeat 1–6×) → Implement +``` + +All phases run in a **single long session**. Do not split across separate sessions. Context built during research and planning carries through to implementation. The plan document survives compaction and serves as the persistent source of truth. + +--- + +## Phase 1 — Research + +Before planning anything, deeply read the relevant code. Surface-level skimming is not acceptable. + +**What to do:** + +- Read the specified folders/files in depth — understand how the code works, what it does, and all its specificities +- Study the intricacies of the systems involved +- Look for existing patterns, conventions, caching layers, ORM conventions, and reusable logic +- Write all findings into `research.md` — never give a verbal summary only + +**Example directives:** + +> "Read this folder in depth, understand how it works deeply, what it does and all its specificities. When that's done, write a detailed report of your learnings and findings in research.md" + +> "Study the notification system in great detail, understand the intricacies of it and write a detailed research.md document with everything there is to know about how notifications work" + +> "Go through the task scheduling flow, understand it deeply and look for potential bugs. Keep researching the flow until you find all the bugs. When you're done, write a detailed report of your findings in research.md" + +**Why this matters:** If the research is wrong, the plan will be wrong, and the implementation will be wrong. The most expensive failure mode is implementations that work in isolation but break the surrounding system — a function that ignores an existing caching layer, a migration that doesn't account for ORM conventions, an API endpoint that duplicates logic that already exists elsewhere. + +--- + +## Phase 2 — Plan + +Once the human has reviewed `research.md`, create a detailed implementation plan in a **separate** markdown file (`plan.md`). + +**The plan must include:** + +- A detailed explanation of the approach +- Code snippets showing actual changes +- File paths that will be modified +- Considerations and trade-offs + +**Reference implementations:** When available, use concrete reference implementations from the codebase or open-source projects. Working from a reference produces dramatically better results than designing from scratch. + +**Critical:** After writing the plan, **stop**. Do not implement. Wait for human annotation. + +--- + +## Phase 3 — Annotation cycle + +This is where the human adds the most value. The human opens `plan.md` in their editor and adds inline notes directly into the document. These notes: + +- Correct assumptions +- Reject proposed approaches +- Add constraints or domain knowledge +- Redirect entire sections + +**Examples of real annotations:** + +- *"Use drizzle:generate for migrations, not raw SQL"* — domain knowledge +- *"No — this should be a PATCH, not a PUT"* — correcting wrong assumptions +- *"Remove this section entirely, we don't need caching here"* — rejecting approaches +- *"The queue consumer already handles retries, so this retry logic is redundant. Remove it and just let it fail"* — explaining existing system behavior +- *"This is wrong, the visibility field needs to be on the list itself, not on individual items"* — redirecting design + +**After each annotation round:** Update the plan based on the notes, then **stop again** — do not implement yet. The cycle repeats 1–6 times until the human is satisfied. + +**Before implementation:** Add a granular todo list to the plan with all phases and individual tasks. This serves as a progress tracker. + +> "Add a detailed todo list to the plan, with all the phases and individual tasks necessary to complete the plan — don't implement yet" + +--- + +## Phase 4 — Implementation + +When the human approves the plan, execute everything in one continuous run: + +> implement it all. when you're done with a task or phase, mark it as completed in the plan document. do not stop until all tasks and phases are completed. do not add unnecessary comments or jsdocs, do not use any or unknown types. continuously run typecheck to make sure you're not introducing new issues. + +**What each instruction means:** + +| Instruction | Purpose | +|---|---| +| "Implement it all" | Do everything in the plan, don't cherry-pick | +| "Mark it as completed in the plan document" | The plan is the source of truth for progress | +| "Do not stop until all tasks and phases are completed" | Don't pause for confirmation mid-flow | +| "Do not add unnecessary comments or jsdocs" | Keep the code clean | +| "Do not use any or unknown types" | Maintain strict typing | +| "Continuously run typecheck" | Catch problems early | + +Implementation should be **boring**. All creative decisions were made in the annotation cycles. + +--- + +## Feedback during implementation + +Once implementation is running, the human's role shifts from architect to supervisor. Prompts become short and direct: + +- *"You didn't implement the `deduplicateByTitle` function."* +- *"You built the settings page in the main app when it should be in the admin app, move it."* +- *"Wider"* +- *"Still cropped"* +- *"There's a 2px gap"* + +**Guidelines for feedback:** + +- For visual issues, use screenshots — they communicate faster than descriptions +- Reference existing code: *"This table should look exactly like the users table, same header, same pagination, same row density."* +- When something goes wrong, **revert and re-scope** rather than patching: *"I reverted everything. Now all I want is to make the list view more minimal — nothing else."* + +--- + +## Key rules + +1. **Never implement without an approved plan.** The plan document sits between the agent and the code. +2. **Research first, always.** Understand the existing system before proposing changes. +3. **Write artifacts, not chat.** All research, plans, and progress live in markdown files — not in conversation history. +4. **Respect the annotation cycle.** When told "don't implement yet," stop. Wait for human input. +5. **Stay in a single session.** Context compounds — research informs planning, planning informs implementation. +6. **The plan is the source of truth.** Mark tasks complete in the plan. Point back to it when context is needed. +7. **Keep implementation mechanical.** All decisions are pre-made. Execute the plan faithfully. +8. **Run typechecks continuously.** Don't accumulate errors — catch them as they happen. + +--- + +*Based on [How I Use Claude Code](https://boristane.com/blog/how-i-use-claude-code/) by Boris Tane. Adopted into the ChainSafe Engineering Handbook by Peter Kalambet.* diff --git a/skills/chainsafe-rust-architect/SKILL.md b/skills/chainsafe-rust-architect/SKILL.md new file mode 100644 index 0000000..a70170a --- /dev/null +++ b/skills/chainsafe-rust-architect/SKILL.md @@ -0,0 +1,96 @@ +--- +name: chainsafe-rust-architect +description: Architectural guidance for designing Rust crates and systems at ChainSafe (Forest, Mina-rs, ChainBridge Substrate, PINT, other Rust projects). Use this skill whenever the user is starting a new Rust crate, designing a Rust workspace, choosing an async runtime, picking an error model, deciding `unsafe` usage, structuring a Cargo workspace, deciding `pub` vs `pub(crate)`, picking concurrency primitives, or writing an ADR for Rust work. EVEN IF the user does not explicitly say "architecture" — triggers on "design a Rust crate", "new Rust workspace", "Forest module design", "thiserror or anyhow", "async runtime choice", "Tokio vs async-std", "Arc> or channel", "public API surface", "is unsafe justified here", "ADR for Rust", "non_exhaustive enum", "workspace layout". Defers to .invariants for invariants themselves; covers what Rust changes about applying them. Do NOT use for line-level Rust coding (use chainsafe-rust-developer) or Rust PR review (use chainsafe-rust-reviewer). +metadata: + type: role-workflow + language: rust + role: architect + source: languages/rust/architect.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Rust Architect + +Use this when designing Rust systems at ChainSafe — Forest-shaped work or any Rust crate/library/binary. Full reference: [`languages/rust/architect.md`](../../languages/rust/architect.md). + +## Key Rust-specific decisions + +### Workspace layout + +ChainSafe Rust projects use Cargo workspaces (Forest is the canonical example): + +- Root `Cargo.toml` declares workspace members. +- Crates split by concern (network, storage, binary, protocol modules). +- A `bin/` crate for the executable; a `lib/` crate for the consumable API. +- Workspace-level dependency hoisting where possible. + +### Error model + +- **`thiserror` for library crates.** Typed errors callers can match via `#[derive(thiserror::Error)]`. +- **`anyhow` for binary crates.** Pass-through errors with `.context(...)` for ergonomics. +- **No mixing** within a single crate without reason. +- **`?` for propagation.** No `match` arms on trivial pass-through. + +### Async runtime + +- **Pick one.** Tokio for most ChainSafe work (Forest included). Don't mix tokio and async-std in the same workspace. +- **`#[tokio::main]` only in the binary crate.** Library crates stay runtime-agnostic where possible. +- **Bounded concurrency:** `FuturesUnordered` with limits, `tokio::sync::Semaphore`, `buffer_unordered` on streams. Unbounded futures-spawn is a leak. +- **`Send + Sync + 'static` bounds** — design types so they meet what `tokio::spawn` requires. +- **Bounded Duration:** Every potentially blocking external `.await` boundary (network I/O, database interaction, channel reads across subsystems) must have a strict timeout boundary. Combine bounded concurrency (caps *how many*) with bounded duration (caps *how long*) to prevent task pool exhaustion. + +### Concurrency primitives + +- **`Arc>`** for shared mutable state across tasks. `tokio::sync::Mutex` when locks span `.await`; `std::sync::Mutex` when they don't. +- **Channels:** `mpsc` for many-to-one, `broadcast` for one-to-many, `oneshot` for single-response. +- **No `std::thread::spawn` in async code.** Use `tokio::task::spawn` or `tokio::task::spawn_blocking`. + +### Public API + +- **`pub(crate)` is the default.** `pub` is a versioning commitment. +- **`#[non_exhaustive]`** on enums and structs that may grow. +- **Builder pattern** for complex constructors. +- **No leaking tokio types in library APIs** unless feature-gated. +- **API & storage isolation.** Keep internal domain types separate from external transport layers. Define serde/wire and database DTOs at the boundary and map them explicitly to domain models; don't hang `#[derive(Serialize, Deserialize)]` or storage-schema concerns directly on domain types. External edges only — not between internal modules. + +### Feature-gating and compilation boundaries + +- **Lean defaults.** Keep `default = []` as minimal as possible. Heavy dependencies (tracing subscribers, database drivers, serialization codecs, dev utilities) live behind optional cargo features, not in the default build. +- **Environment isolation.** Abstract environment-specific logic — mocks, test vectors, alternative networking layers — behind descriptive gates like `test-utils` or `mock`. Never leak testing dependencies into production builds. +- **Conditional compilation.** Apply `#[cfg(feature = "...")]` intentionally on modules and public entry points so that turning a feature off fully removes its artifacts and upstream dependencies from the compilation graph. +- **Features are additive.** Cargo unifies feature sets across the workspace, so a feature may only *add* behavior — never remove or swap it. A `mock` gate that replaces real behavior breaks the moment two crates in one build enable different sets; design gates to layer, not to toggle. + +### Unsafe + +- Every `unsafe` block needs a `// SAFETY: ...` comment with the soundness argument. +- Justification beyond "performance." +- `miri` testing path when possible. +- Minimized — wrap the smallest possible code in `unsafe { }`. + +## ADR template for Rust work + +- Public surface — `pub` vs `pub(crate)` vs private. Justify. +- Error type — `thiserror` or `anyhow`. Justify. +- Async commitments — which runtime, where required, how the API is shaped. +- Unsafe — if any, the soundness argument and safety invariants. +- Invariants impacted — deep links into `.invariants`. + +## Anti-patterns at design time + +- `unwrap()` in non-test code without `// SAFETY: ...`. +- `Box` as a function's return type when you could be specific. +- `String` everywhere when `&str` would do. +- Tokio types leaked through public APIs of library crates without feature flags. +- `unsafe` without a soundness comment. + +## Forest-specific + +Forest carries [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) which sets the security-critical posture for AI-assisted work in a Filecoin client. Architectural decisions on Forest follow that policy — review-time the Rust reviewer skill will enforce. + +## Related + +- Full reference: [`languages/rust/architect.md`](../../languages/rust/architect.md) +- Sister roles: `chainsafe-rust-developer`, `chainsafe-rust-reviewer` +- Framework: [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) +- Workflow: `chainsafe-research-plan-implement` +- Upstream: [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) diff --git a/skills/chainsafe-rust-developer/SKILL.md b/skills/chainsafe-rust-developer/SKILL.md new file mode 100644 index 0000000..e7f933a --- /dev/null +++ b/skills/chainsafe-rust-developer/SKILL.md @@ -0,0 +1,131 @@ +--- +name: chainsafe-rust-developer +description: Idiomatic Rust development at ChainSafe — implementation-level guidance for writing Rust in Forest, Mina-rs, ChainBridge Substrate, and other Rust projects. Use this skill whenever the user is writing Rust, asking how to do something in Rust, debugging Rust, picking between Rust patterns, dealing with errors via thiserror/anyhow, async/Tokio patterns, handling unwrap discipline, writing unsafe with SAFETY comments, testing with proptest or miri, or setting up Rust tooling. EVEN IF the user does not explicitly say "Rust" but the file is .rs. Triggers on "write a Rust function", "implement in Rust", "fix this Rust", "how do I X in Rust", "Tokio async", "Result and ?", "thiserror enum", "anyhow context", "unwrap or expect", "Arc", "spawn_blocking vs spawn", "miri test", "proptest", "cargo clippy", "rustfmt", "cargo.toml". Do NOT use for Rust architectural design (use chainsafe-rust-architect) or Rust PR review (use chainsafe-rust-reviewer). +metadata: + type: role-workflow + language: rust + role: developer + source: languages/rust/developer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Rust Developer + +Idiomatic Rust at ChainSafe. Full reference: [`languages/rust/developer.md`](../../languages/rust/developer.md). + +## Tooling baselines + +CI gates that must pass: + +```sh +cargo fmt --all --check +cargo clippy --all-targets -- -D warnings +cargo build --workspace --all-targets +cargo test --workspace +cargo doc --no-deps +cargo audit +``` + +For unsafe-heavy crates: also `cargo miri test`. + +### Toolchain + +Pin with `rust-toolchain.toml`: + +```toml +[toolchain] +channel = "1.79.0" +components = ["rustfmt", "clippy"] +``` + +### Dependencies + +- `Cargo.lock` committed for binaries; not for libraries published to crates.io. +- `cargo audit` in CI. +- `cargo deny` for license/source/version policy. +- Workspace-level dependency declarations to keep versions consistent. +- **Feature-gating.** Keep `default = []` lean — heavy deps (tracing subscribers, DB drivers, codecs, dev utilities) go behind optional features. Put mocks/test vectors behind `test-utils` or `mock` gates; never leak test deps into production builds. Features must be *additive* (Cargo unifies them across the workspace) — a gate may add behavior, never swap it. + +## Error handling + +```rust +use anyhow::{Context, Result}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum StoreError { + #[error("key not found: {0}")] + NotFound(String), + #[error("backend failure")] + Backend(#[from] BackendError), +} + +pub fn fetch(key: &str) -> Result { + let raw = read_backend(key).with_context(|| format!("reading {key}"))?; + parse(&raw).context("parsing value") +} +``` + +- **Library crates:** typed `thiserror` errors. +- **Binary crates:** `anyhow::Result`. +- **`?` propagation.** Match only when transforming. + +## `unwrap` and `expect` + +- **In tests:** fine. +- **In production code:** require a `// SAFETY: ...` comment justifying the invariant. +- **`expect("...")` over `unwrap()`** when you do use it — message helps debugging. + +## Async + +- `#[tokio::main]` only in binaries. +- `async fn` in trait is stable as of 1.75; older crates use `async-trait`. +- `.await` propagates cancellation — hold no critical invariant across an `.await`. +- `spawn` for async; `spawn_blocking` for CPU-bound. Mixing them up starves the runtime. +- `Send + Sync + 'static` bounds on spawned tasks. +- Every external `.await` (network, DB, cross-subsystem channel read) gets an explicit deadline via `tokio::time::timeout`. Bounded concurrency caps *how many*; this caps *how long* — an `.await` with no timeout hangs forever. + +## Unsafe + +Every `unsafe` block: + +- `// SAFETY: ...` comment immediately above, explaining soundness. +- Justification for choosing `unsafe` over safe alternatives. +- `miri` test where possible. + +Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) treats `unsafe` as security-relevant. Expect HARD-FAIL-tier review scrutiny on PRs introducing it. + +## Testing + +- Unit tests in `#[cfg(test)] mod tests { ... }`. +- Integration tests in `tests/`. +- `#[tokio::test]` for async tests; `flavor = "multi_thread"` for parallel. +- `proptest` for parsers, serializers, math, crypto. +- `cargo nextest` for faster CI runs. +- `miri` for unsafe code. + +## Patterns + +- **Type-state when the protocol allows it.** Encode "must call A before B" in the type system. +- **Newtypes for domain types.** `pub struct UserId(u64)`. +- **`From` / `TryFrom`** for conversions over inherent `to_*` methods. +- **`Deref` only for smart pointers** — don't fake inheritance. +- **API & storage isolation.** Keep `#[derive(Serialize, Deserialize)]` and storage-schema concerns off domain types. Define serde/wire and DB DTOs at the boundary and map them explicitly to domain models. External edges only — not between internal modules. + +## Anti-patterns + +- `unwrap()` in production paths without `// SAFETY: ...`. +- `Box` returns when you could be specific. +- `async fn` that doesn't `.await` anything. +- `Arc>` reached for reflexively when a channel would model the problem better. +- `unsafe` without a soundness comment. +- Public API leaking tokio types without a feature flag. + +## Related + +- Full reference: [`languages/rust/developer.md`](../../languages/rust/developer.md) +- Idioms: [`languages/rust/idioms.md`](../../languages/rust/idioms.md) +- Gotchas: [`languages/rust/gotchas.md`](../../languages/rust/gotchas.md) +- Sister roles: `chainsafe-rust-architect`, `chainsafe-rust-reviewer` +- Forest AI policy: https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md +- Upstream: [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) diff --git a/skills/chainsafe-rust-reviewer/SKILL.md b/skills/chainsafe-rust-reviewer/SKILL.md new file mode 100644 index 0000000..b59230e --- /dev/null +++ b/skills/chainsafe-rust-reviewer/SKILL.md @@ -0,0 +1,104 @@ +--- +name: chainsafe-rust-reviewer +description: Language-specific PR review for Rust code at ChainSafe (Forest, Mina-rs, ChainBridge Substrate, other Rust projects). Use this skill whenever the user is reviewing a Rust PR, asking for Rust code review, checking Rust code for common mistakes, verifying a Rust diff against ChainSafe conventions, looking for unwrap misuse, unsafe soundness, async pitfalls (mutex-across-await, missing Send/Sync), error-handling issues, or public-API problems. EVEN IF the user does not explicitly ask for "Rust review" — triggers on "review this Rust PR", "is this Rust correct", "check this Rust function", "look for issues in this Rust", "review the diff", "what's wrong with this Rust", "unsafe review", "Tokio review". Findings emit at SOFT WARNING by default; `unsafe` blocks promote to near-HARD-FAIL scrutiny per Forest's AI_POLICY. Do NOT use for Rust design (use chainsafe-rust-architect) or Rust implementation guidance (use chainsafe-rust-developer). +metadata: + type: role-workflow + language: rust + role: reviewer + severity-tier: SOFT WARNING (unsafe promotes to near-HARD-FAIL) + source: languages/rust/reviewer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Rust Reviewer + +Reviewer skill for Rust PRs. Universal review framework at [`workflows/code-review.md`](../../workflows/code-review.md); full Rust-specific reference at [`languages/rust/reviewer.md`](../../languages/rust/reviewer.md). + +## Severity tier + +**SOFT WARNING by default.** `unsafe` blocks promote to **near-HARD-FAIL** scrutiny per Forest's [`AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md). Refuse to LGTM `unsafe` without a `// SAFETY:` comment. + +## Checklist + +### Errors and panics + +- No `unwrap()` / `expect()` in production paths without `// SAFETY: ...`. Test code exempt. +- Typed errors (`thiserror`) in library crates; `anyhow::Result` in binaries. No mixing without reason. +- `?` propagation; no match-on-trivial-pass-through. +- Errors carry context (`.context(...)`). +- No `unimplemented!()` / `todo!()` / `panic!()` in production paths. + +### Unsafe (near-HARD-FAIL) + +- **Every `unsafe` block has a `// SAFETY: ...` comment.** Missing → refuse to LGTM. +- Justification is real (not just "performance"). +- `miri` testing path exists if the project supports it. +- The unsafe is minimized — smallest possible `unsafe { }` block. + +### Async + +- `async fn` actually awaits something. +- `Send`/`Sync` met for `tokio::spawn` boundaries. +- `.await` doesn't span a critical invariant. +- `spawn` vs `spawn_blocking` — CPU-bound work in `spawn` starves the runtime. +- No unbounded `FuturesUnordered` / `JoinSet`. +- External `.await` (network, DB, cross-subsystem channel read) has an explicit deadline via `tokio::time::timeout`. Bounded concurrency is not bounded duration — flag a timeout-less external await. + +### API design + +- `pub(crate)` is the default; new `pub` items deliberate. +- `#[non_exhaustive]` on enums and structs that may grow. +- No tokio types in public library APIs unless feature-gated. +- Newtypes for domain values. +- Transport/storage leakage — `#[derive(Serialize, Deserialize)]` or DB-schema attributes on domain types. Expect serde/DB DTOs at the boundary mapped explicitly to domain models; flag wire/storage concerns hung directly on domain types. + +### Concurrency primitives + +- `Arc>` reflex — could a channel model this better? +- `std::sync::Mutex` vs `tokio::sync::Mutex` — async paths need the tokio variant. +- No `.lock().unwrap()` chains without a comment on poisoning. + +### Tests + +- Tests exist for the change. +- Mocks are minimal — not "was called" theatre. +- Property tests via `proptest` for code with formal invariants. +- `miri` for unsafe. + +### Lint and formatting + +- `cargo fmt --check` clean. +- `cargo clippy -D warnings` clean. +- No `#[allow(...)]` without a comment. +- `cargo doc --no-deps` builds. + +### Dependencies + +- No unjustified new crates. +- License compatibility (GPL into Apache 2.0 is blocking). +- `cargo audit` clean. +- Lean `default = []` — heavy deps (tracing subscribers, DB drivers, codecs, dev utilities) behind optional features; test deps (`test-utils`/`mock`) not leaking into production builds. Flag features that swap rather than add behavior (Cargo unifies them workspace-wide). + +## Refusal + +The reviewer skill refuses to review and escalates if: + +- Diff contains non-Rust code. +- PR description is empty. +- Diff touches code out of session scope. +- **Diff introduces `unsafe` and the PR description doesn't justify it.** Refuse and escalate to CODEOWNER. + +## Phrasing + +- Lead with concern: "This `unsafe` block transmutes between repr-C and a Rust struct; the SAFETY comment cites layout, but the layout is `repr(Rust)` and not guaranteed." +- Cite Forest's AI_POLICY when relevant. +- `nit:` for taste-level. + +## Related + +- Full reference: [`languages/rust/reviewer.md`](../../languages/rust/reviewer.md) +- Gotchas: [`languages/rust/gotchas.md`](../../languages/rust/gotchas.md) +- Universal review: [`workflows/code-review.md`](../../workflows/code-review.md) +- Sister roles: `chainsafe-rust-architect`, `chainsafe-rust-developer` +- Forest AI policy: https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md +- Upstream: [Effective Rust](https://effective-rust.com/) · [The Rust Book](https://doc.rust-lang.org/book/) diff --git a/skills/chainsafe-solidity-architect/SKILL.md b/skills/chainsafe-solidity-architect/SKILL.md new file mode 100644 index 0000000..1807031 --- /dev/null +++ b/skills/chainsafe-solidity-architect/SKILL.md @@ -0,0 +1,84 @@ +--- +name: chainsafe-solidity-architect +description: Architectural guidance for designing Solidity contracts and EVM systems at ChainSafe (Sygma bridge and broader crypto work). Use whenever the user starts a new contract, designs a contract system, picks an upgrade strategy (immutable / UUPS / Transparent / Diamond), chooses access control (Ownable vs AccessControl, multi-sig, timelocks), designs reentrancy posture, plans a deployment, or writes an ADR for Solidity work. EVEN IF the user does not say "architecture" — triggers on "design a contract", "Sygma bridge architecture", "upgrade strategy", "UUPS or Transparent", "multi-sig setup", "access control design", "reentrancy strategy", "audit plan", "deployment plan", "bridge invariants", "cross-chain replay", "storage layout upgradeable". Every Solidity decision is a security decision. Do NOT use for line-level Solidity (use chainsafe-solidity-developer) or PR review (use chainsafe-solidity-reviewer). +metadata: + type: role-workflow + language: solidity + role: architect + source: languages/solidity/architect.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Solidity Architect + +Use this when designing Solidity systems at ChainSafe — Sygma-shaped work or any contract. **Every decision here is a security decision.** The reviewer skill is HARD FAIL tier. Architecture that doesn't anticipate that will get blocked. Full reference: [`languages/solidity/architect.md`](../../languages/solidity/architect.md). + +## Key Solidity-specific decisions + +### Project layout + +- Foundry preferred for new projects. Hardhat only where entrenched. +- `src/` (Foundry) or `contracts/` (Hardhat), grouped by domain (`bridge/`, `tokens/`, `governance/`). +- `test/` for tests, `script/` for deploy/ops, `lib/` for vendored libraries (OpenZeppelin, Solady, Solmate). +- `foundry.toml` / `hardhat.config.ts` at the root. + +### Upgrade strategy (binding for the contract's life) + +- **Immutable.** No upgrade path. Simplest and safest; locks in mistakes forever. **Default unless you have a concrete reason for upgradeability.** +- **UUPS** (Universal Upgradeable Proxy Standard). Logic contract holds the upgrade method; requires authorization for `upgradeTo`. +- **Transparent proxy.** Admin/user separation in the proxy; familiar from OpenZeppelin tooling. +- **Diamond (EIP-2535).** Multi-facet, modular; more surface to audit. + +Migrating between upgrade strategies is itself a migration risk. Pick once. + +### Access control + +- **OpenZeppelin `AccessControl`** for role-based authorization in most cases. +- **`Ownable` only for genuinely-single-owner cases.** Owner-key compromise is total compromise. +- **Multi-sig (Gnosis Safe)** for any production deployment's privileged operations. Single-key control of production = finding. +- **Timelocks** on upgrades and parameter changes. Gives stakeholders time to react. + +### Reentrancy posture + +- **Checks-Effects-Interactions** pattern, rigid. State changes before external calls. +- **OpenZeppelin `ReentrancyGuard`** on every external function that calls untrusted contracts. +- **Pull over push** for payments where reasonable. + +### External calls + +- Address every call's failure mode (revert, wrong return, reentrancy). +- `.transfer` and `.send` deprecated; use `.call{value:}("")` and check return. +- Approval-then-transfer for ERC-20: be aware of the classic approval race; use `safeIncreaseAllowance` / `safeDecreaseAllowance`. + +### Bridge-specific (Sygma) + +- Consistent state across chains — what invariant is the bridge maintaining? +- Replay protection via nonces, domain separators, or both. +- Failure mode for destination chain — what happens if delivery fails or is censored? +- Slashing / signer-set rotation — how do signer changes propagate? + +## ADR template for Solidity work + +- Upgrade strategy — immutable / UUPS / Transparent / Diamond. Justify. +- Access control model — roles, granting, renouncing, multi-sig vs EOA. +- External-call surface — which functions, reentrancy posture. +- Storage layout — slot map for upgradeable; gap pattern. +- Audit plan — when, by whom, recurring vs pre-deploy. +- Test coverage commitments — unit, fuzz, invariant, formal verification. +- Invariants impacted — deep links into `.invariants`. + +## Anti-patterns at design time + +- Owner key controls production contracts. Use a multi-sig. +- Upgrade path with no timelock. +- State changes after external calls. +- `tx.origin` for authorization. +- Unbounded loops over caller-controlled data (gas griefing). +- Custom math instead of OpenZeppelin / Solady. +- `assembly` blocks without inline justification. + +## Related + +- Full reference: [`languages/solidity/architect.md`](../../languages/solidity/architect.md) +- Sister roles: `chainsafe-solidity-developer`, `chainsafe-solidity-reviewer` (HARD FAIL tier) +- Workflow: `chainsafe-research-plan-implement` diff --git a/skills/chainsafe-solidity-developer/SKILL.md b/skills/chainsafe-solidity-developer/SKILL.md new file mode 100644 index 0000000..2157e91 --- /dev/null +++ b/skills/chainsafe-solidity-developer/SKILL.md @@ -0,0 +1,145 @@ +--- +name: chainsafe-solidity-developer +description: Idiomatic Solidity development at ChainSafe — implementation-level guidance for writing Solidity in Sygma and other smart-contract work. Use this skill whenever the user is writing Solidity, asking how to do something in Solidity, implementing a contract function, dealing with reentrancy, access control, external calls, custom errors, storage packing, deployment scripts, Foundry tests (unit/fuzz/invariant), or setting up Solidity tooling. EVEN IF the user does not explicitly say "Solidity" but the file is .sol. Triggers on "write a contract", "implement in Solidity", "fix this contract", "how do I X in Solidity", "Foundry test", "fuzz test", "invariant test", "reentrancy guard", "AccessControl roles", "SafeERC20", "custom error", "Foundry vs Hardhat", "slither", "deploy script". Solidity reviewer is HARD FAIL tier — this skill teaches you to stay out of HARD-FAIL territory. Do NOT use for Solidity design (use chainsafe-solidity-architect) or PR review (use chainsafe-solidity-reviewer). +metadata: + type: role-workflow + language: solidity + role: developer + source: languages/solidity/developer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Solidity Developer + +Idiomatic Solidity at ChainSafe. Reviewer is **HARD FAIL** tier; this skill teaches you to stay out of HARD-FAIL territory. Full reference: [`languages/solidity/developer.md`](../../languages/solidity/developer.md). + +## Tooling baselines + +- **Foundry preferred** for new projects. `forge`, `cast`, `anvil`. +- **Hardhat** in entrenched projects. +- **Pin pragma:** `pragma solidity 0.8.24;` (not floating `^0.8.0`). +- **OpenZeppelin Contracts** for ERC-20, ERC-721, AccessControl, ReentrancyGuard, Pausable. +- **Solady / Solmate** when gas matters and audit capacity backs gas-tuned code. +- **slither** as a CI baseline. Specific findings muted with `// slither-disable-next-line ... reason: ...` comments. +- **mythril** for symbolic execution on critical contracts. +- **solhint** for style. + +## Imports + +```solidity +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.24; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +``` + +- **Named imports** over wildcard `import "..."`. +- **SPDX identifier** at top of every file. + +## Checks-Effects-Interactions (the canonical pattern) + +```solidity +function withdraw(uint256 amount) external nonReentrant { + // Checks + if (amount == 0) revert ZeroAmount(); + if (balances[msg.sender] < amount) revert Insufficient(amount, balances[msg.sender]); + + // Effects + balances[msg.sender] -= amount; + totalDeposits -= amount; + + // Interactions + (bool ok, ) = msg.sender.call{value: amount}(""); + if (!ok) revert TransferFailed(); +} +``` + +Always in this order. `nonReentrant` on every external function calling untrusted code. + +## Access control + +```solidity +contract Vault is AccessControl, ReentrancyGuard { + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN"); + + function setFee(uint256 newFee) external onlyRole(ADMIN_ROLE) { /* ... */ } +} +``` + +- `AccessControl` over `Ownable` for multi-action contracts. +- Lock down `DEFAULT_ADMIN_ROLE`. +- Multi-sig (Gnosis Safe) holds privileged roles in production. EOA only in dev/test. +- Timelocks on parameter changes. + +## Custom errors (0.8.4+) + +```solidity +error Insufficient(uint256 requested, uint256 available); + +function withdraw(uint256 amount) external { + if (balances[msg.sender] < amount) revert Insufficient(amount, balances[msg.sender]); +} +``` + +Smaller bytecode than `require` strings; structured data for callers. + +## External calls + +- `.call{value: amount}("")` over `.transfer` / `.send` (which break with new gas pricing). +- Check return values. Unchecked = silent bugs. +- Use OpenZeppelin's `SafeERC20.safeTransfer` / `safeTransferFrom` — normalizes broken ERC-20s like USDT. + +## Function visibility + +- `external` default for callable-from-outside (saves gas vs `public` for calldata args). +- `public` only when also called internally. +- `internal` for cross-contract-inheritance helpers. +- `private` rarely. + +## State variables + +- **Pack storage** — group same-size types to share slots. +- `immutable` for constructor-set values. +- `constant` for compile-time-known values. +- Document storage layout for upgradeable contracts; `__gap` reserves slots. + +## Testing (Foundry) + +- **Unit tests** in `test/*.t.sol`. +- **Fuzz tests** by parameterizing function arguments. +- **Invariant tests** declare properties that must always hold; `forge` finds breaking sequences. +- **Differential tests** against a reference implementation. +- **Mainnet fork tests** for integrations with deployed contracts. + +Coverage via `forge coverage`. Security-critical code: 100% line coverage is necessary, not sufficient. Add fuzz + invariant tests. + +## CI baseline + +- `forge build` +- `forge test -vvv` +- `forge coverage` with threshold (typically 95%+ for security-critical) +- `slither .` +- `solhint 'src/**/*.sol'` +- Mainnet fork tests on schedule +- Gas snapshot via `forge snapshot --check` to catch regressions + +## Anti-patterns (most are HARD FAIL findings) + +- `tx.origin` for authorization. +- Floating pragma. +- Unbounded loops over user-controlled data. +- State changes after external calls. +- `.transfer` / `.send` for ETH. +- Custom math reimplementing audited primitives. +- `assembly` without justification. +- Owner-key control of production contracts. + +## Related + +- Full reference: [`languages/solidity/developer.md`](../../languages/solidity/developer.md) +- Idioms: [`languages/solidity/idioms.md`](../../languages/solidity/idioms.md) +- Gotchas: [`languages/solidity/gotchas.md`](../../languages/solidity/gotchas.md) +- Sister roles: `chainsafe-solidity-architect`, `chainsafe-solidity-reviewer` (HARD FAIL tier) diff --git a/skills/chainsafe-solidity-reviewer/SKILL.md b/skills/chainsafe-solidity-reviewer/SKILL.md new file mode 100644 index 0000000..467a70a --- /dev/null +++ b/skills/chainsafe-solidity-reviewer/SKILL.md @@ -0,0 +1,124 @@ +--- +name: chainsafe-solidity-reviewer +description: HARD FAIL tier PR review for Solidity contracts at ChainSafe (Sygma bridge and crypto work). Use whenever the user is reviewing a Solidity PR, asking for contract review, checking for reentrancy / upgrade safety / access control / audit-readiness, or verifying a Solidity diff against ChainSafe conventions. EVEN IF the user does not ask for "Solidity review" — triggers on "review this contract", "is this Solidity correct", "check for reentrancy", "upgrade safety review", "audit-readiness", "security review", "Solidity diff", "Sygma review", "contract PR review". This reviewer emits HARD FAIL on reentrancy, upgrade safety, tx.origin, access-control gaps, unchecked external calls. Operator override is logged in PR with `Override: HARD FAIL for reason `. Do NOT use for Solidity design (use chainsafe-solidity-architect) or implementation (use chainsafe-solidity-developer). +metadata: + type: role-workflow + language: solidity + role: reviewer + severity-tier: HARD FAIL + source: languages/solidity/reviewer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# Solidity Reviewer (HARD FAIL tier) + +Reviewer skill for Solidity PRs. Per [reviewer-severity tier table](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail), emits **HARD FAIL** for security-critical findings. Agent reports; operator decides; bypass is logged in the PR with explicit `Override: HARD FAIL for reason ` per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). + +Full reference: [`languages/solidity/reviewer.md`](../../languages/solidity/reviewer.md). + +## HARD FAIL checks (refuses LGTM until resolved or explicitly overridden) + +### Reentrancy + +- State changes after external calls — any `.call`, `.delegatecall`, ERC-20 transfer, callback to arbitrary address with state mutations after it. +- Missing `nonReentrant` on external functions calling untrusted contracts. +- Cross-function reentrancy — shared state with an external-calling function, without guards. + +### Authorization + +- **`tx.origin` used for authorization.** Always HARD FAIL. +- Privileged function without access control modifier. +- `onlyOwner` on contracts holding non-trivial value without multi-sig path. +- Role-grant power not locked down (`DEFAULT_ADMIN_ROLE` must be held by multi-sig + timelock). + +### Upgrade safety (for upgradeable contracts) + +- **Storage layout changes** between versions — reordering or inserting non-appended variables. +- `initializer` discipline — missing modifier or skipping parent initializer. +- Missing `__gap` reserved slots. +- `UUPSUpgradeable._authorizeUpgrade` must restrict access; missing or weak = total contract control bypass. +- No timelock on upgrade path. + +### External calls + +- Unchecked return values from `.call{value:}` or `IERC20.transfer`. +- `.transfer` / `.send` (hardcoded 2300 gas, breaks with EIP-1884 and similar). +- Unbounded gas forwarding to untrusted contracts. +- `delegatecall` to caller-controlled addresses. + +### Arithmetic + +- `unchecked { }` blocks without inline justification. +- Custom math reimplementing OpenZeppelin / Solady. + +### `assembly` / Yul + +- `assembly` without inline justification (same standard as Rust `unsafe`). +- `assembly` reading from user-controlled storage slots without explicit reasoning. + +### Bridge / cross-chain (Sygma context) + +- Missing nonce / replay protection on cross-chain messages. +- Trust assumptions on signer sets that don't survive rotation. +- No failure mode for messages that can't be delivered on the destination chain. +- Inconsistent state model between source and destination. + +## SOFT WARNING checks (flag, don't block) + +- Style and naming. +- Gas optimizations that don't affect correctness. +- Test coverage gaps in non-critical paths. +- Documentation thinness. +- `solhint` style violations. + +## Audit-readiness checklist + +A merged PR should be audit-ready: + +- [ ] Spec or design doc linked in PR description. +- [ ] Threat model named. +- [ ] Unit + fuzz + invariant tests for changed surface. +- [ ] Slither clean (or muted with `// slither-disable-next-line ... reason: ...`). +- [ ] Coverage threshold met (typically 95%+). +- [ ] Gas snapshot diff intentional. +- [ ] Storage layout diff for upgradeable contracts. +- [ ] Deployment script if deployable from this PR. + +## Refusal + +The reviewer skill refuses to review and escalates if: + +- Non-Solidity code in diff. +- PR description doesn't name the threat model. +- PR introduces privileged function without access control modifiers. +- PR changes storage layout of upgradeable contract without a layout diff in description. +- PR makes a deployment-affecting change without a deployment script. + +Escalate to a Solidity CODEOWNER and the curator. + +## Override mechanics + +Per [agent-era invariant §7](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings): + +1. Reviewer skill emits finding with unique identifier. +2. Operator (CODEOWNER) reviews and decides to override. +3. PR description gets `Override: HARD FAIL for reason ` line. +4. Separate audit-log entry (CHANGELOG) records the override. +5. Override reviewed in post-merge cycle. + +The agent does not override on the operator's behalf. The operator types the override line themselves. + +## Phrasing + +- Lead with concern and severity: "**HARD FAIL — reentrancy.** This function transfers ETH via `.call{value:}` and then updates `balances`. CEI requires balance update first." +- Cite the rule: "Per [Solidity reviewer §reentrancy](../../languages/solidity/reviewer.md#hard-fail-checks-reviewer-refuses-lgtm-until-resolved-or-explicitly-overridden)." +- Reference the auditor's perspective. + +## Related + +- Full reference: [`languages/solidity/reviewer.md`](../../languages/solidity/reviewer.md) +- Gotchas (most are HARD FAIL findings): [`languages/solidity/gotchas.md`](../../languages/solidity/gotchas.md) +- Universal review: [`workflows/code-review.md`](../../workflows/code-review.md) +- HARD FAIL gate: [`operating-model/gates-and-escalation.md`](../../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) +- Invariant: [`invariants/agent-era-invariants.md`](../../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings) +- Sister roles: `chainsafe-solidity-architect`, `chainsafe-solidity-developer` diff --git a/skills/chainsafe-typescript-architect/SKILL.md b/skills/chainsafe-typescript-architect/SKILL.md new file mode 100644 index 0000000..e089111 --- /dev/null +++ b/skills/chainsafe-typescript-architect/SKILL.md @@ -0,0 +1,91 @@ +--- +name: chainsafe-typescript-architect +description: Architectural guidance for designing TypeScript projects at ChainSafe (Lodestar, web3.js 4.x, ssz, bls, filsnap, other TS projects). Use this skill whenever the user is starting a new TypeScript project, designing a TS package, structuring a Yarn 3 monorepo workspace, picking ESM vs CJS, deciding on type strictness baseline, designing public APIs with branded types, choosing testing frameworks, or writing an ADR for TS work. EVEN IF the user does not explicitly say "architecture" — triggers on "design a TS package", "new TS project", "Lodestar architecture", "monorepo setup", "Yarn workspaces", "ESM or CJS", "branded types", "public API design", "ADR for TypeScript", "tsconfig strict baseline", "type-level tests". Defers to .invariants for invariants themselves. Do NOT use for line-level TS coding (use chainsafe-typescript-developer) or TS PR review (use chainsafe-typescript-reviewer). +metadata: + type: role-workflow + language: typescript + role: architect + source: languages/typescript/architect.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# TypeScript Architect + +Use this when designing TypeScript systems at ChainSafe — Lodestar-shaped work or any TS package/library/app. Full reference: [`languages/typescript/architect.md`](../../languages/typescript/architect.md). + +## Key TypeScript-specific decisions + +### Project layout + +- **Monorepo:** Yarn 3 workspaces. (`lerna` is deprecated at ChainSafe.) +- **Root `package.json`** with `"packageManager": "yarn@3.x"` and `"workspaces": ["packages/*"]`. +- Each package: own `package.json`, `src/`, `test/`, `tsconfig.json`. +- Shared dev tooling (ESLint, Prettier, base tsconfig) at root; extended per-package. +- TypeScript build via `tsc -b` (composite projects) or bundler. + +### Type strictness baseline + +- **`"strict": true`** — non-negotiable floor. +- **`"noUncheckedIndexedAccess": true`** — array indexing returns `T | undefined`. +- **`"exactOptionalPropertyTypes": true`** when the project can take it. +- **`"isolatedModules": true`** for bundler compatibility. + +### Module system + +- **ESM by default** for new projects. `"type": "module"` in `package.json`, `.js` extensions in import paths. +- **CJS only** where downstream consumers require it. +- **Dual-publish** (`main` + `module` + `exports`) for libraries needing both. + +### Branded types + +```ts +type UserId = string & { readonly __brand: "UserId" }; +type OrderId = string & { readonly __brand: "OrderId" }; +``` + +Domain identifiers must not be interchangeable. Branded types enforce at the type level with zero runtime cost. + +### Error model + +- Throw `Error` subclasses (not plain `Error`) so callers can `instanceof` discriminate. +- `Result` types for libraries where error-as-value semantics fit; throw for binary entrypoints. +- `AggregateError` for `Promise.allSettled` multi-error cases. +- Never throw strings or non-`Error` objects. + +### Async + +- `async`/`await` over raw promises for readability. +- `Promise.all` for parallel independent work. +- `Promise.allSettled` when partial failure is acceptable. +- No floating promises. ESLint's `no-floating-promises` catches. +- `AbortSignal` for cancellation propagation. + +### Public API + +- Type-level tests (`tsd`, `expect-type`) for libraries publishing types. +- Re-exports through a single `index.ts` per package. +- `@internal` JSDoc tag for tooling-exported items not in public API. + +## ADR template for TypeScript work + +- Public surface — what's exported. Type-level tests covering it. +- Async commitments — where cancellation propagates; where parallelism is exploited. +- Error contract — thrown types vs returned types. +- Build target — Node version, browser support, ESM/CJS, bundler. +- Invariants impacted — deep links into `.invariants`. + +## Anti-patterns at design time + +- `any` in committed code. +- `as` type assertions without runtime checks. +- Unbounded `Promise.all` over a large input calling a rate-limited API. +- Default exports. +- `enum` when a const object + `as const` produces better types. +- `tsc --noEmit` not in CI. + +## Related + +- Full reference: [`languages/typescript/architect.md`](../../languages/typescript/architect.md) +- Sister roles: `chainsafe-typescript-developer`, `chainsafe-typescript-reviewer` +- Framework: [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) +- Workflow: `chainsafe-research-plan-implement` diff --git a/skills/chainsafe-typescript-developer/SKILL.md b/skills/chainsafe-typescript-developer/SKILL.md new file mode 100644 index 0000000..6617f8e --- /dev/null +++ b/skills/chainsafe-typescript-developer/SKILL.md @@ -0,0 +1,123 @@ +--- +name: chainsafe-typescript-developer +description: Idiomatic TypeScript development at ChainSafe — implementation-level guidance for writing TS in Lodestar, web3.js, ssz, bls, filsnap, and other TS projects. Use this skill whenever the user is writing TypeScript, asking how to do something in TS, debugging TS, picking between TS patterns, handling type narrowing, working with async/promises, configuring tsconfig or ESLint, setting up Yarn 3 workspaces, writing tests, or publishing npm packages. EVEN IF the user does not explicitly say "TypeScript" but the file is .ts or .tsx. Triggers on "write a TS function", "implement in TypeScript", "fix this TS", "how do I X in TS", "tsconfig strict", "ESLint config", "Yarn workspaces", "discriminated union", "branded type", "narrow this type", "type guard", "async pattern", "Promise.all", "AbortSignal", "Vitest", "publish to npm". Do NOT use for TypeScript architectural design (use chainsafe-typescript-architect) or TS PR review (use chainsafe-typescript-reviewer). +metadata: + type: role-workflow + language: typescript + role: developer + source: languages/typescript/developer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# TypeScript Developer + +Idiomatic TypeScript at ChainSafe. Full reference: [`languages/typescript/developer.md`](../../languages/typescript/developer.md). + +## Tooling baselines + +- **Linter:** ESLint with `@chainsafe/eslint-config`. Run `yarn lint`. +- **Formatter:** Prettier (included transitively via the shared config). `yarn prettier --check` in CI. +- **TypeScript:** `"strict": true` floor; `"noUncheckedIndexedAccess": true` for new projects. +- **Monorepo:** Yarn 3 workspaces. `corepack enable`; `"packageManager": "yarn@3.x"`. +- **Testing:** Vitest for new projects; Mocha+Chai in entrenched Lodestar; Jest where set up. + +## tsconfig baseline + +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "dist" + } +} +``` + +Tighten per project; `strict: true` is the floor. + +## Type discipline + +- **No `any` in committed code.** `unknown` for genuinely-typeless values; narrow before use. +- **`as` casts only with a guard.** Use `typeof`, `instanceof`, or a schema validator (`zod`, `io-ts`). +- **`unknown` over `any` for caught errors:** `catch (err: unknown)`. +- **Discriminated unions** for state machines. +- **`readonly`** on properties that don't mutate; `as const` for literal narrowing. +- **Branded types** for domain values that shouldn't mix. + +## Async + +- `async`/`await` for readability. +- `Promise.all` for parallel; `Promise.allSettled` for partial-failure. +- No floating promises. ESLint catches. +- `AbortSignal` for cancellation: functions that can take time should accept optional `signal: AbortSignal`. +- `for await ... of` for sequential async iteration. + +## Error handling + +```ts +class FetchError extends Error { + constructor(public readonly url: string, public readonly status: number) { + super(`fetch ${url} failed: ${status}`); + this.name = "FetchError"; + } +} +``` + +- Throw `Error` subclasses, never strings. +- Distinguish recoverable from non-recoverable by error class, not by message text. + +## Monorepo setup (Yarn 3 workspaces) + +1. Enable corepack: `corepack enable` (Node 16+). +2. Root `package.json`: `"packageManager": "yarn@3.4.1"`, `"workspaces": ["packages/*"]`. +3. Per-package `package.json` with its own deps and scripts. +4. TypeScript project references (`tsconfig.json` with `references: [...]`) for cross-package types. + +Template: https://github.com/ChainSafe/yarn-workspaces-typescript-template. + +## CI baseline + +- `yarn lint` +- `yarn prettier --check '**/*.{ts,json,md}'` +- `yarn tsc --noEmit` +- `yarn build` +- `yarn test --coverage` +- `yarn audit` +- Type-surface check (`tsd`/`expect-type`) for libraries publishing types. + +## Patterns + +- **`unknown` then narrow** over `any`. +- **Discriminated unions** for state. +- **`readonly` arrays and tuples** for immutable data. +- **`Pick`, `Omit`, `Partial`, `Required`** for type composition. +- **Type predicates** (`value is Foo`) for custom guards. +- **`satisfies`** for type-checking literal values without widening. + +## Anti-patterns + +- `any` or `as Foo` in committed code. +- Floating promises. +- `default export` when named would do. +- `enum` when const object + `as const` produces better types. +- `@ts-ignore` without comment + issue link. +- Untyped network responses — validate at the boundary. + +## Related + +- Full reference: [`languages/typescript/developer.md`](../../languages/typescript/developer.md) +- Idioms: [`languages/typescript/idioms.md`](../../languages/typescript/idioms.md) +- Gotchas: [`languages/typescript/gotchas.md`](../../languages/typescript/gotchas.md) +- Sister roles: `chainsafe-typescript-architect`, `chainsafe-typescript-reviewer` +- Shared ESLint config: https://github.com/ChainSafe/eslint-config diff --git a/skills/chainsafe-typescript-reviewer/SKILL.md b/skills/chainsafe-typescript-reviewer/SKILL.md new file mode 100644 index 0000000..f3e6516 --- /dev/null +++ b/skills/chainsafe-typescript-reviewer/SKILL.md @@ -0,0 +1,100 @@ +--- +name: chainsafe-typescript-reviewer +description: Language-specific PR review for TypeScript code at ChainSafe (Lodestar, web3.js 4.x, ssz, bls, filsnap, other TS projects). Use this skill whenever the user is reviewing a TypeScript PR, asking for TS code review, checking TS code for common mistakes, looking for `any`/`as` misuse, floating promises, `@ts-ignore` abuse, error-handling issues, or public-API problems. EVEN IF the user does not explicitly ask for "TS review" — triggers on "review this TS PR", "is this TypeScript correct", "check this TS function", "look for issues in this .ts", "review the diff", "what's wrong with this TS", "type review", "any check", "promise review". Findings emit at SOFT WARNING severity (agent reports; operator decides on merge); agent never blocks. Do NOT use for TS design (use chainsafe-typescript-architect) or TS implementation guidance (use chainsafe-typescript-developer). +metadata: + type: role-workflow + language: typescript + role: reviewer + severity-tier: SOFT WARNING + source: languages/typescript/reviewer.md + authored-via: anthropic-skills:skill-creator (2026-05-27) +--- + +# TypeScript Reviewer + +Reviewer skill for TypeScript PRs. Universal review framework at [`workflows/code-review.md`](../../workflows/code-review.md); full reference at [`languages/typescript/reviewer.md`](../../languages/typescript/reviewer.md). + +## Severity tier + +**SOFT WARNING.** Agent flags; operator decides on merge. + +## Checklist + +### Type discipline + +- `any` in committed code → flag. `unknown` with narrowing is the alternative. +- `as` type assertions → require an accompanying type guard or schema check. +- `@ts-ignore` / `@ts-expect-error` → require comment with reason and ideally an issue link. +- `!` non-null assertion → flag. Prefer explicit narrowing. +- Index access without bounds check → verify `noUncheckedIndexedAccess: true` is on. +- `Function` and `Object` types → too wide. Use specific signatures. + +### Module hygiene + +- Default exports → ask if named would do. +- Circular imports → flag; tend to produce undefined-at-load-time bugs. +- Implementation imports of internals across package boundaries → API surface violation. + +### Async + +- Floating promises → `.catch(...)` or `await` required. +- `Promise.all` over rate-limited APIs unbounded → use `p-limit`. +- Missing `await` before Promise-returning expressions (especially in conditionals). +- `async` functions that don't await anything → probably sync. +- No `AbortSignal` on long-running operations. + +### Error handling + +- Thrown non-`Error` values → always throw an `Error` subclass. +- `catch (err)` without typing as `unknown` and narrowing. +- `try`/`catch` swallowing errors → at minimum log; usually re-throw or wrap. + +### Tests + +- Type-level tests for libraries publishing types. +- Tests touch behavior, not implementation. +- `describe`/`it` names are sentences. +- Coverage threshold enforced in CI. + +### Build and config + +- `strict: true` in tsconfig. +- `noUncheckedIndexedAccess` on for new projects. +- `tsc --noEmit` as its own CI step. +- Lint and format pass before commit. +- No `node_modules` or `dist` in diff. + +### Dependencies + +- No `latest` or floating versions. +- `yarn audit` clean. +- License-compatible. +- No new deps without justification. + +### Public API (for libraries) + +- New `export`s are deliberate. +- `@internal` JSDoc on tooling-exported items. +- CHANGELOG entry in the same PR as breaking changes. + +## Refusal + +The reviewer skill refuses to review and escalates if: + +- Non-TypeScript code in diff. +- Empty PR description. +- Out-of-session-scope code. +- **No `strict: true` in tsconfig** — refuse and escalate. Type discipline is the foundation. + +## Phrasing + +- Lead with concern: "This function takes `data: any` and forwards it to the network layer. What's the actual shape?" +- Cite the rule. +- `nit:` for taste. + +## Related + +- Full reference: [`languages/typescript/reviewer.md`](../../languages/typescript/reviewer.md) +- Gotchas: [`languages/typescript/gotchas.md`](../../languages/typescript/gotchas.md) +- Universal review: [`workflows/code-review.md`](../../workflows/code-review.md) +- Sister roles: `chainsafe-typescript-architect`, `chainsafe-typescript-developer` diff --git a/skills/chainsafe-zig-architect/SKILL.md b/skills/chainsafe-zig-architect/SKILL.md new file mode 100644 index 0000000..c41ddaa --- /dev/null +++ b/skills/chainsafe-zig-architect/SKILL.md @@ -0,0 +1,75 @@ +--- +name: chainsafe-zig-architect +description: Architectural guidance for designing Zig modules and libraries at ChainSafe (lodestar-z — Zig consensus libraries for Lodestar: SSZ, Merkleization, hashing, persistent Merkle trees, consensus types). Use this skill whenever the user is starting a new Zig module, designing a build.zig layout, deciding allocator ownership or strategy, choosing a build mode (ReleaseSafe vs ReleaseFast) and safety posture, designing an error set, shaping a comptime/generic API, designing a C-ABI/FFI surface for bindings, pinning a Zig version, or writing an ADR for Zig work. EVEN IF the user does not explicitly say "architecture" — triggers on "design a Zig module", "new Zig library", "build.zig layout", "allocator strategy", "arena vs gpa", "who owns this allocation", "ReleaseSafe or ReleaseFast", "Zig error set", "comptime generic", "export to C ABI", "lodestar-z module", "SSZ type design", "ADR for Zig", "minimum_zig_version". Defers to .invariants for invariants themselves; covers what Zig changes about applying them. Do NOT use for line-level Zig coding (use chainsafe-zig-developer) or Zig PR review (use chainsafe-zig-reviewer). +metadata: + type: role-workflow + language: zig + role: architect + source: languages/zig/architect.md + authored-via: anthropic-skills:skill-creator (2026-06-01) +--- + +# Zig Architect + +Use this when designing Zig modules at ChainSafe — lodestar-z-shaped work (consensus libraries consumed by Lodestar across a C ABI) or any Zig library. Full reference: [`languages/zig/architect.md`](../../languages/zig/architect.md). + +## When Zig (and when not) + +Zig earns its place where the realistic alternative is C: small, performance-critical, memory-controlled libraries consumed across an FFI boundary — hashing, SSZ encode/decode, Merkleization. It is **not** the default for services or tooling (those are TypeScript/Go/Rust/Solidity/Python). Introducing Zig outside that niche is an org-level decision — raise it with the curator and capture the rationale in an ADR first. + +## Key Zig-specific decisions + +### Project layout + +- `build.zig` + `build.zig.zon` at the root; `build.zig.zon` pins dependencies and `minimum_zig_version`. +- Public modules declared in `build.zig` via `b.addModule` — the module list *is* the public surface (lodestar-z exposes `ssz`, `hashing`, `persistent_merkle_tree`, `consensus_types`). +- `src/` (root.zig / main.zig), `test/`, `bench/`, `bindings/`. Files are structs; one primary type per file. + +### Allocator strategy (the central decision) + +- **Inject, never capture.** Every allocating function/type takes an `std.mem.Allocator`; none reaches for a global. This is what makes code testable, leak-checkable, and FFI-usable. +- **Match the allocator to the lifetime** — arena for operation-scoped bulk frees, fixed-buffer for bounded hot paths, leak-detecting GPA in tests/debug. +- **Ownership is explicit** across returns and the C ABI. Pair every acquire with `defer` / `errdefer`. + +### Error model + +- Explicit error sets at public boundaries so callers `switch` exhaustively; inference (`!T`) for internal helpers. +- `try` to propagate, `errdefer` to unwind partial construction. +- `catch unreachable` only where success is a proven invariant — never on fallible I/O (UB in unsafe builds). + +### Build mode and safety posture + +- **ReleaseSafe is the default** for anything where a wrong answer matters (all of lodestar-z). Runtime safety stays on. +- **ReleaseFast only on measured hot paths**, with `@setRuntimeSafety(false)` scoped tightly and justified. Overflow and bounds checks become UB there — never assume them for correctness. + +### Comptime over macros + +Generics are functions returning `type` (`fn UintType(comptime bits: u16) type`). Keep comptime surfaces small and documented; comptime that could be runtime costs compile time and readability. + +### The C ABI is a contract + +Bindings cross a C ABI (`export fn`, `callconv(.C)`, `extern` layout). Treat the exported surface as a versioned public API with explicit cross-boundary memory ownership — breaking it breaks a downstream client in another language. + +### Pre-1.0 reality + +Zig is pre-1.0; pin `minimum_zig_version` and the CI compiler, wrap heavily-used std APIs, and budget for migration on upgrades. + +## ADR shape for Zig modules + +Allocator ownership · error set · build-mode/safety posture · comptime surface · exported C ABI + memory ownership · Zig version floor · invariants impacted (`.invariants`). + +## Anti-patterns at design time + +- A hidden/global allocator. +- ReleaseFast for correctness-critical code without a measured, scoped justification. +- Comptime where runtime would do. +- Leaking allocator ownership across the C ABI without a documented contract. +- `catch unreachable` on fallible operations. + +## Related + +- Full reference: [`languages/zig/architect.md`](../../languages/zig/architect.md) +- Sister roles: `chainsafe-zig-developer`, `chainsafe-zig-reviewer` +- Framework: [`invariants/invariants-framework.md`](../../invariants/invariants-framework.md) +- Workflow: `chainsafe-research-plan-implement` +- Upstream: [Zig Language Reference](https://ziglang.org/documentation/master/), [Learn Zig](https://ziglang.org/learn/) diff --git a/skills/chainsafe-zig-developer/SKILL.md b/skills/chainsafe-zig-developer/SKILL.md new file mode 100644 index 0000000..c0c53c8 --- /dev/null +++ b/skills/chainsafe-zig-developer/SKILL.md @@ -0,0 +1,94 @@ +--- +name: chainsafe-zig-developer +description: Idiomatic Zig development at ChainSafe — implementation-level guidance for writing Zig in lodestar-z (SSZ, Merkleization, hashing, consensus types) and other Zig libraries. Use this skill whenever the user is writing Zig, asking how to do something in Zig, debugging Zig, picking between Zig patterns, passing allocators, using defer/errdefer, handling error unions with try/catch, writing comptime generics, dealing with integer overflow or undefined behavior, using the build system (build.zig / build.zig.zon), writing tests with std.testing, fuzzing, or building C-ABI bindings. EVEN IF the user does not explicitly say "Zig" but the file is .zig. Triggers on "write a Zig function", "implement in Zig", "fix this Zig", "how do I X in Zig", "allocator parameter", "defer vs errdefer", "try and catch", "error set", "comptime", "optional ?T", "tagged union", "zig build test", "build.zig.zon", "std.testing.allocator", "zig fmt", "export fn callconv(.C)", "@cImport", "integer overflow", "@setRuntimeSafety". Do NOT use for Zig architectural design (use chainsafe-zig-architect) or Zig PR review (use chainsafe-zig-reviewer). +metadata: + type: role-workflow + language: zig + role: developer + source: languages/zig/developer.md + authored-via: anthropic-skills:skill-creator (2026-06-01) +--- + +# Zig Developer + +Idiomatic Zig at ChainSafe. Full reference: [`languages/zig/developer.md`](../../languages/zig/developer.md). + +## Tooling baselines + +```sh +zig fmt --check . # canonical, unconfigurable formatter — gate in CI +zig build # build.zig + build.zig.zon drive everything +zig build test # run test blocks +zig build -Doptimize=ReleaseSafe # choose the build mode on purpose +``` + +- **Pin the Zig version.** Set `minimum_zig_version` in `build.zig.zon` and pin the exact compiler in CI — Zig is pre-1.0 and an unpinned toolchain makes CI non-deterministic. +- Add dependencies with `zig fetch --save` so hashes are pinned. Projects expose their own steps (lodestar-z: `zig build test:static_spec_tests -Dpreset=mainnet`). + +## Memory and allocators + +```zig +fn loadRoots(allocator: std.mem.Allocator, count: usize) ![]Root { + const roots = try allocator.alloc(Root, count); + errdefer allocator.free(roots); // freed only if a later step fails + try fill(roots); + return roots; // ownership transfers to the caller +} +``` + +- Inject the allocator; never reach for a global. +- `defer` for unconditional cleanup, `errdefer` for the error-only path — placed at the acquire. +- Arena for bulk/operation-scoped, fixed-buffer for bounded hot paths. In tests use `std.testing.allocator` (fails on leak). + +## Error handling + +- Explicit error sets at public boundaries, inferred (`!T`) internally. +- `try` to propagate, `catch` to handle, `switch` on the error for exhaustiveness. +- `catch unreachable` only where success is a proven invariant — never on real I/O. + +## Safety and integer math + +- **Integer overflow is illegal behavior** (both signed and unsigned): compile error at comptime, panic in safe builds, UB in ReleaseFast. Use `+%` (wrapping), `+|` (saturating), or `@addWithOverflow` when wraparound is intended. +- `@setRuntimeSafety(false)` only on a measured, scoped, commented hot path. +- Reading `undefined` memory is UB — initialize before reading. + +## Comptime + +Generics are `fn(comptime T: type) type`; `@typeInfo` + `inline for` give compile-time reflection. Keep comptime surfaces small — it costs compile time and readability when overused. + +## Testing + +```zig +test "round-trips" { + const a = std.testing.allocator; + var v = try decode(a, input); + defer v.deinit(a); + try std.testing.expectEqualSlices(u8, input, try encode(a, v)); +} +``` + +- Test blocks live next to the code; `std.testing.allocator` catches leaks. +- **Spec/conformance tests** for SSZ/Merkleization/consensus types (byte-for-byte determinism). **Fuzz** serializers (`zig build --fuzz`; lodestar-z also runs AFL++). **Bench** the hot paths Zig was chosen for. + +## C interop and bindings + +- `@cImport(@cInclude("..."))` imports C headers directly; `export fn` + `callconv(.C)` + `extern` define the surface other languages call. +- Memory ownership across the boundary must be explicit. `zig cc` is a drop-in C cross-compiler. + +## CI baseline + +`zig fmt --check` · `zig build` in ReleaseSafe · `zig build test` · spec/conformance suites · fuzz smoke · pinned Zig version. + +## Anti-patterns + +- A global allocator instead of an injected one. +- Swallowing an error union, or `catch unreachable` on fallible operations. +- Assuming ReleaseFast semantics for correctness. +- Comptime bloat; unused variables/imports (Zig rejects them — discard with `_ = x;` deliberately). + +## Related + +- Full reference: [`languages/zig/developer.md`](../../languages/zig/developer.md) +- Idioms: [`languages/zig/idioms.md`](../../languages/zig/idioms.md) · Gotchas: [`languages/zig/gotchas.md`](../../languages/zig/gotchas.md) +- Sister roles: `chainsafe-zig-architect`, `chainsafe-zig-reviewer` +- Upstream: [Zig Build System](https://ziglang.org/learn/build-system/), [Zig Language Reference](https://ziglang.org/documentation/master/) diff --git a/skills/chainsafe-zig-reviewer/SKILL.md b/skills/chainsafe-zig-reviewer/SKILL.md new file mode 100644 index 0000000..f678a60 --- /dev/null +++ b/skills/chainsafe-zig-reviewer/SKILL.md @@ -0,0 +1,80 @@ +--- +name: chainsafe-zig-reviewer +description: Language-specific PR review for Zig code at ChainSafe (lodestar-z — consensus-critical Zig: SSZ, hashTreeRoot, Merkleization, hashing). Use this skill whenever the user is reviewing a Zig PR, asking for Zig code review, checking Zig for common mistakes, verifying a Zig diff against ChainSafe conventions, looking for allocator/leak issues, missing defer/errdefer, swallowed errors, undefined behavior, unjustified @setRuntimeSafety(false) or @ptrCast, integer-overflow bugs, or consensus-correctness gaps. EVEN IF the user does not explicitly ask for "Zig review" — triggers on "review this Zig PR", "is this Zig correct", "check this Zig function", "look for issues in this Zig", "review the diff", "memory leak review", "undefined behavior check", "SSZ correctness", "alignment cast review", "allocator review". Findings emit at SOFT WARNING by default; memory-safety/UB and consensus-correctness paths promote to near-HARD-FAIL scrutiny. Do NOT use for Zig design (use chainsafe-zig-architect) or Zig implementation guidance (use chainsafe-zig-developer). +metadata: + type: role-workflow + language: zig + role: reviewer + severity-tier: SOFT WARNING (memory-safety + consensus paths promote to near-HARD-FAIL) + source: languages/zig/reviewer.md + authored-via: anthropic-skills:skill-creator (2026-06-01) +--- + +# Zig Reviewer + +Reviewer skill for Zig PRs. Universal review framework at [`workflows/code-review.md`](../../workflows/code-review.md); full Zig-specific reference at [`languages/zig/reviewer.md`](../../languages/zig/reviewer.md). + +## Severity tier + +**SOFT WARNING by default.** Two surfaces **promote to near-HARD-FAIL** — the reviewer stops and a human must engage: + +1. **Memory-safety / undefined-behavior surface** — `@setRuntimeSafety(false)`, `@ptrCast` / `@alignCast`, raw many-item pointer arithmetic, `catch unreachable` on fallible ops, reliance on ReleaseFast semantics. +2. **Consensus-correctness surface** — SSZ encode/decode, `hashTreeRoot`, Merkleization. A byte wrong here is a fork, not a bug. + +Mirrors how Rust's `unsafe` is treated: the language allows it, the reviewer demands justification. + +## Checklist + +### Memory and allocators + +- Every allocation has a paired `defer` / `errdefer` free at the acquire. +- Allocator is injected, not global. Ownership across returns and the C ABI is clear. +- No leaks — `std.testing.allocator` stays green. Allocator choice fits the lifetime. + +### Errors + +- No swallowed error unions — every `!T` is `try`-propagated, `catch`-handled, or exhaustively `switch`ed. +- `errdefer` unwinds partial construction correctly. +- `catch unreachable` only where success is a real invariant (near-HARD on fallible I/O). + +### Undefined behavior and safety + +- `@setRuntimeSafety(false)` justified and scoped (unscoped/unexplained → near-HARD). +- Integer-overflow intent explicit (`+%` / `+|` / `@addWithOverflow`); otherwise overflow impossible or handled. +- `@ptrCast` / `@alignCast` sound — alignment honored, target layout guaranteed. No reading `undefined`; no reliance on ReleaseFast eliding checks. + +### Comptime · C ABI + +- Comptime surfaces minimal and documented; no comptime where runtime fits. +- Exported surface stable; cross-boundary memory ownership documented; null/optional handled at the boundary. + +### Consensus correctness (lodestar-z and similar) + +- Spec-test coverage for SSZ / Merkleization / hashing changes, against the Ethereum consensus spec. +- Fuzz coverage for serializers; determinism (endianness explicit, no floats on consensus paths). + +### Tests, lint, format + +- Test blocks exist; `std.testing.allocator` used so leaks fail. `zig fmt --check` clean. + +## Refusal + +The reviewer skill refuses to review and escalates if: + +- The diff contains non-Zig code. +- The PR description is empty. +- The diff touches code out of session scope. +- **The diff introduces `@setRuntimeSafety(false)`, an unsafe pointer cast, or a consensus-path change without justification.** Refuse and escalate to the CODEOWNER. + +## Phrasing + +- Lead with the concern: "This `@ptrCast` reinterprets `[]u8` as `[]u32`; the SAFETY note cites length but not alignment — what guarantees 4-byte alignment?" +- Cite the spec for consensus findings. +- `nit:` for taste-level. + +## Related + +- Full reference: [`languages/zig/reviewer.md`](../../languages/zig/reviewer.md) +- Gotchas: [`languages/zig/gotchas.md`](../../languages/zig/gotchas.md) +- Universal review: [`workflows/code-review.md`](../../workflows/code-review.md) +- Sister roles: `chainsafe-zig-architect`, `chainsafe-zig-developer` diff --git a/src/components/EngLadderGraph.tsx b/src/components/EngLadderGraph.tsx deleted file mode 100644 index 7f2faa1..0000000 --- a/src/components/EngLadderGraph.tsx +++ /dev/null @@ -1,290 +0,0 @@ -import React, { useState, type ChangeEventHandler, useEffect } from 'react' -import Highcharts from 'highcharts' -import HC_more from 'highcharts/highcharts-more' -import HighchartsReact from 'highcharts-react-official' -import BrowserOnly from '@docusaurus/BrowserOnly' - - -import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; -import { themes } from 'prism-react-renderer' - -if (ExecutionEnvironment.canUseDOM) { - HC_more(Highcharts) -} - -type Role = { - name: string, - data: [number, number, number, number, number] -} - -//['Technical Expertise', 'System', 'People', 'Process', 'Impact'], -const engineeringRoles: Record = { - e1: { - name: 'Associate Engineer', - data: [1, 1, 1, 1, 1], - }, - e2: { - name: 'Engineer', - data: [2, 2, 2, 2, 2], - }, - e3: { - name: 'Senior Engineer', - data: [3, 3, 3, 3, 2], - }, - e4: { - name: 'Principal Engineer', - data: [4, 4, 3, 4, 3], - }, - e5: { - name: 'Distinguished Engineer', - data: [5, 5, 4, 5, 4], - } -} - - - -//['Technical Expertise', 'System', 'People', 'Process', 'Impact'], -const engineeringMgmtRoles: Record = { - em3: { - name: 'Engineering Manager', - data: [3, 3, 5, 2, 3], - }, - em4: { - name: 'Senior Engineering Manager', - data: [3, 4, 5, 4, 3], - }, - em5: { - name: 'Engineering Head', - data: [3, 4, 5, 5, 4], - } -} -//['Technical Expertise', 'Research Metodology', 'People', 'Process', 'Impact'], -const researchRoles: Record = { - er1: { - name: 'Associate Engineer in Research', - data: [1, 1, 1, 1, 1], - }, - er2: { - name: 'Engineer in Research', - data: [2, 2, 2, 2, 2], - }, - er3: { - name: 'Senior Engineer in Research', - data: [3, 3, 3, 3, 2], - }, - e4: { - name: 'Principal Engineer in Research', - data: [4, 4, 3, 4, 3], - }, - e5: { - name: 'Distinguished Engineer in Research', - data: [5, 5, 4, 5, 4], - } -} - -const engineerLabels = { - "Technical Expertise": ['', 'Adopts', 'Specializes', 'Evangelizes', 'Masters', 'Creates'], - "System": ['', 'Enhances', 'Designs', 'Owns', 'Evolves', 'Leads'], - "People": ['', 'Learns', 'Supports', 'Mentors', 'Coordinates', 'Manages'], - "Process": ['', 'Follows', 'Enforces', 'Challenges', 'Adjusts', 'Defines'], - "Impact": ['', 'Component', 'Stream', 'Program', 'Multiple Programs', 'Company'] -}; - -const researcherLabels = { - "Technical Expertise": ['', 'Adopts', 'Specializes', 'Evangelizes', 'Masters', 'Creates'], - "Research Methodology": ['', 'Executes', 'Analyzes', 'Proposes', 'Leads', 'Expands'], - "People": ['', 'Learns', 'Supports', 'Mentors', 'Coordinates', 'Manages'], - "Process": ['', 'Follows', 'Enforces', 'Challenges', 'Adjusts', 'Defines'], - "Impact": ['', 'Component', 'Stream', 'Program', 'Multiple Programs', 'Company'] -}; - -enum LadderType { - ENG = "engineer", - ENG_MGMT = "engineer_management", - RESEARCHER = "researcher" -} - -const EngLadderGraph = function ({ type }: { type: LadderType }) { - - const backgroundColor = themes.dracula.plain.backgroundColor; - const color = themes.dracula.plain.color; - - const labelArray: Record = type === LadderType.RESEARCHER ? researcherLabels : engineerLabels; - - let roles: Record = {} - - if (type === LadderType.RESEARCHER) { - roles = researchRoles - } - if (type === LadderType.ENG) { - roles = engineeringRoles - } - if (type === LadderType.ENG_MGMT) { - roles = engineeringMgmtRoles - } - const [role, setRole] = useState(Object.keys(roles)[0]); - const [result, setResult] = useState<[number, number, number, number, number]>([1,1,1,1,1]); - - const defaultSeries = []; - const categories = Object.keys(labelArray); - for (var i = 0; i <= 5; i++) { - defaultSeries.push({ - name: 'dummy series #' + i + ' for label placement', - data: [ - { name: labelArray[categories[0]][i], y: i }, - { name: labelArray[categories[1]][i], y: i }, - { name: labelArray[categories[2]][i], y: i }, - { name: labelArray[categories[3]][i], y: i }, - { name: labelArray[categories[4]][i], y: i } - ], - dataLabels: { - enabled: true, padding: 0, y: 0, - formatter: function () { - return '' + this.point.name + ''; - } - }, - pointPlacement: 'on', - lineWidth: 0, - color: 'transparent', - showInLegend: false, - enableMouseTracking: false - }); - } - - const options: Highcharts.Options = { - chart: { - polar: true, - type: 'line', - spacingLeft: 30, // Adjust left spacing as needed - spacingRight: 30, // Adjust right spacing as needed - marginRight: 30, - backgroundColor, - }, - title: undefined, - pane: { - size: '80%' - }, - xAxis: { - categories: Object.keys(labelArray), - tickmarkPlacement: 'on', - lineWidth: 0, - labels: { - distance: 40, - style: { - color, - fontSize: '1.2rem' - } - } - }, - yAxis: { - gridLineInterpolation: 'polygon', - lineWidth: 0, - labels: { - enabled: false, - }, - min: 0, max: 6, - tickInterval: 1, - alignTicks: true, - }, - tooltip: { - enabled: true, - shared: true - }, - legend: { - align: 'right', - verticalAlign: 'top', - y: 70, - layout: 'vertical', - itemStyle: { - color, - } - }, - series: [ - ...defaultSeries, - { - id: "selectedRole", - name: roles[role].name, - data: [...roles[role].data], - pointPlacement: 'on', - }, - { - id: "customResult", - name: 'Your Path', - data: result, - pointPlacement: 'on' - }, - ] - } - - const onRoleSelect: ChangeEventHandler = function (event) { - setRole(event.target.value) - } - - const onCompareAtributeSelect: ChangeEventHandler = function (event) { - result[Number.parseInt(event.target.id)] = Number.parseInt(event.target.options[event.target.options.selectedIndex].value) - setResult([...result]); - } - - return ( - Loading...}> - { - () => { - return ( -
- -
-
- - -
- -
- Your results: -

- { - categories.map((category, categoryIndex) => { - return ( -
- - -
- ) - }) - } -
-
-
- -
-
- ) - } - } -
- ); -} - -export default EngLadderGraph; \ No newline at end of file diff --git a/src/css/index.css b/src/css/index.css deleted file mode 100644 index 7ac4bd7..0000000 --- a/src/css/index.css +++ /dev/null @@ -1,96 +0,0 @@ -.menu__link--active { - color: #FFEC3D; -} -:root { - --ifm-color-primary-dark: #FFEC3D; - --ifm-color-primary: #FFEC3D; - --ifm-menu-color-active: #FFEC3D; - --aa-primary-color-rgb: #FFEC3D !important; - --aa-text-color-rgb: #FFEC3D !important; - --aa-text-color-rgb: #FFEC3D !important; -} - - -a { - color: #FFEC3D; -} - -a:hover { - color: #FFEC3D; -} - -.breadcrumbs__item--active .breadcrumbs__link { - color: #FFEC3D; -} - -.aa-DetachedSearchButton { - color: #FFEC3D !important; -} -.aa-DetachedSearchButtonIcon { - color: #FFEC3D !important; -} - -.join-us{ - margin-top: 1rem !important; -} - -.join-us > .menu__link { - color: #FFEC3D !important; -} - -.page-caption { - color: #8c8c8c; - font-size: 1.2rem; - font-style: italic; -} - -.level { - background: #FFEC3D; - border-radius: 4px; - color: #333; - padding: 0.2rem; -} - -.axis { - background: #fff; - border-radius: 4px; - color: #333; - padding: 0.2rem; -} - -.dashboard select { - height: 1.5rem; -} - -.dashboard label { - width: 12rem; - display: inline-block; - margin-right: 1.5rem; -} - -.dashboard > .compareRole > label { - font-weight: bold; -} - -.dashboard .compareRole { - margin-bottom: 2rem; -} - -.dashboard .compare { - margin-bottom: 2rem; -} - -.dashboard > .compare label{ - display: inline-block; - width: 12rem; - margin-bottom: 0.5rem; -} - -.dashboard > .compare select{ - width: 10rem; -} - -.dashboard > .compare > span { - margin-bottom: 2rem; - font-weight: bold; -} \ No newline at end of file diff --git a/src/pages/assets/sync-with-github.png b/src/pages/assets/sync-with-github.png deleted file mode 100644 index 04a3979..0000000 Binary files a/src/pages/assets/sync-with-github.png and /dev/null differ diff --git a/src/pages/gitbook-migration.md b/src/pages/gitbook-migration.md deleted file mode 100644 index 9d9a920..0000000 --- a/src/pages/gitbook-migration.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: gitbook -title: GitBook migration -hide_table_of_contents: false ---- - -# GitBook migration - -This guide describes the process of converting GitBook docs into Docusarus. -Luckily, they are both using Markdown to render content, which makes the process a bit easier. - - -## 1. Setup Docusaurus Repository - -Start by selecting "Import repository" option in GitHub and put the URL of the starter repository (https://github.com/ChainSafe/documentation-starter). Update `docusaurus.config.js` and `package.json` configs with proper naming and urls. - -## 2. Export GitBook Docs to Markdown - -You can do this by syncing the GitBook site with GitHub. -Choose the 3 dots icon in the top-right corner of your GitBook site and choose the "Synchronize with GitHub" option. -Connect your GitHub account if you haven't already and select a GitHub repository where you want your GitBook site to export. **Make sure there are no branch protection rules in place and that priority is selected "GitBook to GitHub".** - -![./assets/sync-with-github.png](./assets/sync-with-github.png) - -## 3. Migrate content - -Copy all `.md` files from exported GitHub repository into your new Docusarus repository into `/docs` directory. -Delete `SUMMARY.md` file because in Docusaurus it is automatically generated (Read more how to modify sidebar: https://docusaurus.io/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). - -If you ran `yarn start` in the new repository you should see your documentation homepage. There will probably be some unsupported markdown features. - -## 4. Fix unsupported Markdown features - -### Embedded Video or Playlist links - -| GitBook | Docusaurus | -| --- | --- | -| `{% embed url="" %}` | Go to the source (YouTube, Vimeo), choose to share embedded and paste raw html code in markdown | - -### Change anchor names - -| GitBook | Docusaurus | -| --- | --- | -| `# Heading ` | `# Heading {#heading2}` | - -### Description sections to call-outs - -| GitBook | Docusaurus | -| --- | --- | -| ---
description: >-
---
| :::info

:::
| - -### Syntax highlight for non-default languages - -Docusaurus by default supports only [this set of language highlights](https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/vendor/prism/includeLangs.js). In order to add highlight support for other popular languages `docusaurus.conf.js` needs to be extended with the desired languages list: - -```js -themeConfig: - ... - prism: { - ... - additionalLanguages: ['csharp'], - } - ... -``` - -More information can be found [here](https://docusaurus.io/docs/markdown-features/code-blocks#supported-languages). -### Code blocks line numbering - -| GitBook | Docusaurus | -| --- | --- | -| \{\% code lineNumbers="true" \%\} | showLineNumbers | diff --git a/src/pages/oneflow.md b/src/pages/oneflow.md deleted file mode 100644 index e866129..0000000 --- a/src/pages/oneflow.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: oneflow -title: Description of OneFlow approach -hide_table_of_contents: false ---- - - -## Overview -There are multiple ways to deal with branching and CI. The most famous ones are probably [GitFlow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow), [GitHub Flow](https://docs.github.com/en/get-started/quickstart/github-flow) and [Gitlab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html). However they are pretty branch heavy and that in it turn brings a lot of back and forth on CI, merging, commit tracking and back-merging. - -The approach described below is not ideal and far from being a sliver bullet but its minimalistic design have some advantages, especially in CI/CD-first development cycle. - -## Branches -There is a pretty good description of branching rules and naming convention in the [Development](/development/development-flow/development) section of this handbook and we will not repeat it here but just encourage to follow it. - -![oneflow_assets/oneflow-3.png](oneflow_assets/oneflow-3.png) - -## The branch -The whole OneFlow approach is built around just one branch. In our case `main`. Every other branch is circumstantial and suppose to live only till it got merged to `main`. OneFlow relaying heavily on tags and the fact that tags are global and not related to branch. Plus support for tags in modern CI/CD systems is pretty widespread and full featured. - -## Deployments -Multi-environment setup of development process usually assumes 3 general environments: development, staging, production. Markers of staging and production deployments are tags and development is always a `main` branch `HEAD`. - -* Development environment - `HEAD` -* Staging - `tag stage-*` -* Production - `tag v.*.*` - -On this illustration branches are underlined and tags put into boxes. - -![oneflow_assets/oneflow-1.png](oneflow_assets/oneflow-1.png) - -All that approach states nothing about PR-preview deployments or any other additional deployments that are needed for development cycle. Those are established on "on-need" basis. - -GitHub also has a feature that allows [tags protection](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/configuring-tag-protection-rules) which means that only users with write access to the repository can creates tags that follows selected patterns and only admins can delete such tags. Configuring protection rules considered as a best security practices and should be enabled by the repository admin if the development happening on a GitHub. - -## Hot fixes of tagged deployments -There are situations when a hot fix is needed. For that purpose a `hotfix/*` branch can be made. This branch will use broken production tag as a parent commit and as soon as all changes are ready and tested a new `v.*.*` tags can be made which will be picked up by CD to deploy a new version. -The `hotfix/*` branch should be merged to the `main` branch, tested and go through the staging environment before the next release tag. - -![oneflow_assets/oneflow-2.png](oneflow_assets/oneflow-2.png) \ No newline at end of file diff --git a/src/pages/oneflow_assets/oneflow-1.png b/src/pages/oneflow_assets/oneflow-1.png deleted file mode 100644 index 1ed17a3..0000000 Binary files a/src/pages/oneflow_assets/oneflow-1.png and /dev/null differ diff --git a/src/pages/oneflow_assets/oneflow-2.png b/src/pages/oneflow_assets/oneflow-2.png deleted file mode 100644 index 4dcbc49..0000000 Binary files a/src/pages/oneflow_assets/oneflow-2.png and /dev/null differ diff --git a/src/pages/oneflow_assets/oneflow-3.png b/src/pages/oneflow_assets/oneflow-3.png deleted file mode 100644 index 8f4a8ef..0000000 Binary files a/src/pages/oneflow_assets/oneflow-3.png and /dev/null differ diff --git a/static/.nojekyll b/static/.nojekyll deleted file mode 100644 index e69de29..0000000 diff --git a/static/img/favicon.ico b/static/img/favicon.ico deleted file mode 100644 index c01d54b..0000000 Binary files a/static/img/favicon.ico and /dev/null differ diff --git a/static/img/logo.png b/static/img/logo.png deleted file mode 100644 index eee4cbc..0000000 Binary files a/static/img/logo.png and /dev/null differ diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 44f6107..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - // This file is not used in compilation. It is here just for a nice editor experience. - "extends": "@tsconfig/docusaurus/tsconfig.json", - "compilerOptions": { - "baseUrl": ".", - "skipLibCheck": true - } -} diff --git a/workflows/code-review.md b/workflows/code-review.md new file mode 100644 index 0000000..6a03032 --- /dev/null +++ b/workflows/code-review.md @@ -0,0 +1,114 @@ +# Code Review + +Two modes — review of an agent's output by a human operator, and review of a PR (human-authored or agent-authored) by an agent. The principles overlap; the failure modes do not. + +> **In one line:** Code review is the last reliable gate before the work becomes everyone's problem. Both reviewer modes exist to keep that gate honest. + +## Universal principles + +These apply to either reviewer mode. + +- **Approve when the change improves overall code health.** "Perfect" isn't the bar. Forward progress against current quality is. +- **Technical facts and data overrule opinions and personal preferences.** If two designs are equally valid, respect the author's choice. +- **Authority ladder:** style guide > current codebase conventions > author preference. When the current codebase conflicts with the style guide, defer to the team's documented strategy. +- **Prefix nits.** Comments that are preference, taste, or teaching get prefixed `nit:` so the author knows they can ignore them. +- **Note the good things.** Reviews skewed toward only-mistakes train authors to be defensive. Call out what worked, with why. + +What to look for, on either mode: + +- **Design.** Do the pieces fit? Does this change belong here, or in a library? Readability beats DRY. +- **Functionality.** Does the code do what the author intended? Is what was intended actually good for end-users *and* future developers reading this code? +- **Complexity.** Especially over-engineering. The right code solves the problem you have now, not the problem you might have in two years. +- **Naming.** Long enough to communicate, short enough to read. +- **Comments.** Explain *why*, not *what*. Exceptions: regex, hard-to-understand algorithms — *what* is desirable there. +- **Every line.** Look at every human-written line you've been assigned. Skim is not review. +- **Context.** Sometimes pulling the branch and reading it in place beats scrolling the GitHub diff. + +## Speed of review + +Speed matters. A slow review means: + +- The author starts something else, loses context. +- Feedback arrives mid-other-task; context-switch tax for both sides. +- The reviewer's own context decays. + +Default service level: **review within one business day** of being requested. If you can't, say so and propose when you can. If you're on a critical path the author is blocked on, drop other work for it. + +This applies to agent reviewers too — agents that "review eventually" defeat the purpose. + +## Mode (a) — Operator reviewing an agent's output + +Most ChainSafe PRs in the v2 era have an agent in the author chair. The operator is reviewing a diff drafted by an AI under their own (or another operator's) supervision. This mode has its own failure surface. + +### What to verify + +- **The plan matches the diff.** If the PR links a `plan.md`, the diff should be that plan and nothing more. Drift between plan and code is the most common quiet failure. +- **Fabrication.** Imports that don't exist, functions called with wrong signatures, references to handbook pages that aren't there. Agents fabricate plausibly; verify the references. +- **Silent scope creep.** Files in the diff that weren't in the original plan. The PR description should name each one with a reason. Missing reason → ask. +- **Over-eager refactor.** Agents like to "improve while passing through." Each unrelated improvement is its own PR. +- **Generic comments.** Comments that restate what the code does instead of why. Agents add these by default; cut them. +- **Test theatre.** Tests that exercise the code without actually checking behavior — e.g., asserting that a function was called rather than asserting on its effect. Read the test bodies, not just the test names. +- **Type laxity.** `any`, `unknown`, untyped returns, missing error handling. The agent may have taken shortcuts the operator didn't authorize. +- **Undeclared operational contract.** A diff that adds or changes env vars, config keys, secrets, schema/migrations, ports, or a public signature without a matching **Operational impact** declaration. This is the change that becomes Infra's problem later — [Engineering Invariant 8](../invariants/engineering-invariants.md#8-a-change-carries-its-operational-contract). + +### When to demand a re-plan vs. accept + +- **Re-plan.** If the diff drifted materially from the linked plan; if the agent made design choices the operator hadn't approved; if the diff includes unrelated changes; if fabrication is present. Don't patch — go back to the plan. +- **Accept with notes.** Minor issues that don't change the shape of the change. The author updates and you approve. +- **Reject entirely.** The change is in the wrong direction. Close the PR; reopen with a fresh plan once the direction is right. + +### What you (the operator) cannot delegate + +- The decision to merge. +- The judgment call on whether HARD FAIL findings from reviewer skills are properly addressed. +- The sign-off that the audit trail is sufficient — that someone reading this PR in six months can reconstruct what was decided and why. + +## Mode (b) — Agent reviewing a PR + +Agents can be effective code reviewers when configured well. The shape: + +### Checklist + +- Run lint/type-check/test against the branch; report failures. +- Diff against the linked plan or spec; flag deviations. +- Apply the relevant language reviewer skill (when one exists in [`../languages//reviewer.md`](../languages/)). +- Check for the PR-description completeness (what changed, why, acceptance criteria, **operational impact**, AI declaration if applicable, scope drift flags). Flag env-var / config / schema / public-signature changes that aren't declared. +- Verify references are real (no fabricated imports, function names, or handbook links). +- Flag missing or thin commit messages. + +### What to flag vs. what to fix in place + +- **Flag, do not fix:** design choices, complexity concerns, naming, anything subjective. The author owns the change; the reviewer flags concerns. +- **Suggest, with a code suggestion attached:** trivial nits (typos, lint, formatting). Use GitHub's suggestion feature so the author can apply with one click. +- **Never fix and push to the author's branch** without explicit operator authorization. The agent is reviewing, not co-authoring. + +### How to phrase comments + +- Lead with the concern, not the fix. "This function loads N+1 queries when iterating users." Then optional: "Consider preloading via JOIN." +- Cite the rule when there is one. "Per `agent-era-invariants.md` §1, the diff should not touch `auth/middleware.ts`. Was this scope-extended?" +- Use `nit:` for taste-level comments so the author can ignore them. +- Avoid "you" framing for design comments; use "this function" / "this approach." Keeps the focus on the code. + +### When the agent refuses to review + +The agent escalates rather than reviewing if: + +- The diff contains HARD FAIL findings the agent can't evaluate (a Solidity reviewer skill HARD FAIL on a Daml PR would be a mismatched tool, etc.). +- The PR description is missing entirely — there is nothing to review against. +- The diff touches code the agent has been told not to operate on for this session (out-of-scope repo, sensitive file path). + +In each case the agent surfaces the reason and asks the operator to either expand scope, get a human reviewer, or close the PR. + +## When reviews go wrong + +- **Stale review** (author hasn't responded in >3 business days, reviewer hasn't followed up): reviewer pings author once; if no response, defer to CODEOWNER for unblocking. +- **Heated thread**: take it off the PR. A 5-minute call or thread DM beats a 30-comment GitHub argument. +- **Disagreement on design**: not the reviewer's call to overrule. Escalate to CODEOWNER or curator. Do not approve under protest; do not block indefinitely. +- **Author requests merge despite open comments**: reviewer pushes back; if pushed past, CODEOWNER decides. The reviewer is not the merge gate alone — the merge process is. + +## Related + +- [`pr-authoring.md`](./pr-authoring.md) — the author's counterpart to this page. +- [`../invariants/agent-era-invariants.md`](../invariants/agent-era-invariants.md) — §1 (scope), §2 (no fabrication), §7 (HARD FAIL), §8 (audit trail) all show up in review. +- [`../operating-model/gates-and-escalation.md`](../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) — HARD FAIL handling. +- [`../languages/`](../languages/) — language-specific reviewer skills extend this with language-aware checks. diff --git a/workflows/incident-response.md b/workflows/incident-response.md new file mode 100644 index 0000000..d7564c0 --- /dev/null +++ b/workflows/incident-response.md @@ -0,0 +1,100 @@ +# Incident Response + +This handbook holds only the **operator decision policy** layer for incidents. The *how-to* — the actual runbooks, paging procedures, escalation chains, and recovery steps — lives in [`ChainSafe/infrastructure-general/docs/runbooks/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/runbooks). + +> **In one line:** When to page, when to roll back, who approves a recovery action. The *how* defers to the runbooks. + +> **Status note.** The operator-decision-policy section below is complete. The [runbook deep-link map](#runbook-deep-link-map) is confirmed at file level; heading anchors *within* the runbooks are pending [@joshdougall](https://github.com/joshdougall)'s confirmation. Per the deep-link convention, where the upstream lacks an anchor we need for clean linking, the convention is to add the anchor upstream rather than work around it here. + +## Operator decision policy + +These are the calls a human makes during an incident. The runbooks tell you the mechanics; this page tells you the decisions. + +### When to page + +Page the on-call (and yourself) when any of these are true: + +- A user-facing service is degraded or down. +- A validator or signer is missing duties or producing invalid attestations. +- A monitoring alert fires that the [`infrastructure-alerts`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/infrastructure-alerts.md) runbook classifies as page-worthy. +- Funds, assets, or signing keys are at risk. +- A security event is suspected (suspicious access, leaked credential, exploited vulnerability). +- The chain you're operating against is in a degraded state and the runbook for that chain (Polkadot, Ethereum, Filecoin, etc.) calls for it. + +Do not page for transient blips that auto-recover within the runbook's threshold. The runbooks define those thresholds; defer to them. + +### When to roll back + +Roll back when: + +- A deploy correlates with a regression and the regression is user-visible or affects validator duties. +- A configuration change has produced unexpected behavior in production and the change is reversible. +- An ongoing degradation is worsening, not stabilizing, and the next escalation step is "roll forward and find out." + +Do **not** roll back when: + +- The degradation is unrelated to a recent change (rolling back won't fix it, and may add complexity). +- The rollback itself is irreversible at this point (e.g., schema changes already applied — see [`gates-and-escalation.md` §3](../operating-model/gates-and-escalation.md#3-irreversible-writes)). +- The runbook for this specific failure mode calls for roll-forward. + +Rollback decisions are owned by the on-call operator in consultation with the change author (if reachable) and the relevant CODEOWNER. Agents do not execute rollbacks autonomously — the [protected-branch and irreversible-writes gates](../operating-model/gates-and-escalation.md#3-irreversible-writes) require explicit operator approval. + +### Who approves what + +| Action | Approves | +|---|---| +| Acknowledging a page | The on-call (immediately) | +| Initiating roll-back | The on-call, with a CODEOWNER for the affected service | +| Bypassing a HARD FAIL during incident recovery | The on-call **and** the CODEOWNER; override is logged in the post-incident review | +| Comms to external stakeholders (status page, customers, validators) | Per the [external-comms gate](../operating-model/gates-and-escalation.md#4-external-communication); on-call coordinates with the comms / leadership chain | +| Closing the incident | The on-call, after the runbook's exit criteria are met | +| Calling for a post-incident review | Always — every page-worthy incident gets one | + +## Runbook deep-link map + +### By chain / product + +| Scenario | Runbook | +|---|---| +| General infrastructure alerts (cross-product) | [`infrastructure-alerts.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/infrastructure-alerts.md) | +| Ethereum / Lodestar alerts | [`lodestar-alerts.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/lodestar-alerts.md) | +| Filecoin alerts | [`filecoin-alerts.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/filecoin-alerts.md) | +| Forest upgrade procedures | [`forest-upgrade-procedures.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/forest-upgrade-procedures.md) | +| Polkadot alerts | [`polkadot-alerts.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/polkadot-alerts.md) | +| Optimism alerts | [`optimism-alerts.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/optimism-alerts.md) | +| Lido validator operations | [`lido-validator-operations.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/lido-validator-operations.md) | +| Rocketpool node operations | [`rocketpool-node-operations.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/rocketpool-node-operations.md) | +| IPFS gateway operations | [`ipfs-gateway-operations.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/ipfs-gateway-operations.md) | +| Canton unclaimed rewards | [`canton-unclaimed-rewards.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/runbooks/canton-unclaimed-rewards.md) | + +If your scenario isn't listed: the runbook may not exist yet. Surface the gap to [@joshdougall](https://github.com/joshdougall) and the on-call; do not improvise from this page. + +## Agent role during an incident + +Agents are useful for support tasks during an incident; they are not on-call: + +- **Useful:** searching logs, summarizing metrics, generating draft status updates for human approval, cross-referencing similar past incidents, drafting the post-incident review document. +- **Not useful:** making the rollback decision, posting to status pages, paging humans, running recovery commands against production without explicit per-command operator approval. + +During an active incident, the [secrets gate](../operating-model/gates-and-escalation.md#2-secrets-and-credentials), [external-communication gate](../operating-model/gates-and-escalation.md#4-external-communication), and [protected-branch gate](../operating-model/gates-and-escalation.md#5-version-control-state) tighten, not loosen. Time pressure is the textbook way for these gates to be silently violated; agents should be more cautious during incidents, not less. + +## Post-incident review + +Every page-worthy incident gets a written post-incident review. The format follows blameless-postmortem conventions: + +- What happened, in order. +- What we expected vs. what happened. +- Why the gap. +- What went well during the response. +- What we'd change about the response itself. +- Concrete action items, owned, with dates. + +Agents can draft the document from chat logs, runbook executions, and PR history. The operator reviews, edits, and owns the conclusions. The document lives in `infrastructure-general` (location per Josh's convention) and is linked from the original incident ticket. + +## Related + +- [`infrastructure-and-devops.md`](./infrastructure-and-devops.md) — the broader infra deep-link map; this page is incident-specific. +- [`release-and-deploy.md`](./release-and-deploy.md) — release decisions whose backstop is this page when they go wrong. +- [`../operating-model/gates-and-escalation.md`](../operating-model/gates-and-escalation.md) — the gates incidents put under stress. +- [`../operating-model/collaborator-statement.md`](../operating-model/collaborator-statement.md) — operator-first applies under time pressure too. +- Upstream: [`ChainSafe/infrastructure-general/docs/runbooks/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/runbooks) — the runbooks themselves. diff --git a/workflows/infrastructure-and-devops.md b/workflows/infrastructure-and-devops.md new file mode 100644 index 0000000..f4041f2 --- /dev/null +++ b/workflows/infrastructure-and-devops.md @@ -0,0 +1,80 @@ +# Infrastructure and DevOps + +For all infrastructure, IaC, deployment topology, observability, on-call, and DevOps practice, the canonical source is **[`ChainSafe/infrastructure-general`](https://github.com/ChainSafe/infrastructure-general)**. This handbook does not duplicate it. + +> **In one line:** This page is a navigation surface, not a tutorial. Deep links by intent into the canonical repo; no "see also" gestures. + +> **Status note.** File-level deep-link targets on this page are confirmed against the current state of `infrastructure-general/docs/`. Heading anchors *within* those files are pending [@joshdougall](https://github.com/joshdougall)'s confirmation. Where the upstream lacks an anchor we need for clean linking, the convention is to add the anchor upstream rather than work around it here. + +## Why we defer here + +`infrastructure-general` is the authoritative artifact for ChainSafe infrastructure. It already ships its own [`AGENTS.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/AGENTS.md) and [`CLAUDE.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/CLAUDE.md), confirming the agent-native posture. The handbook treats it as canonical for any question whose answer involves how production systems are built, run, observed, or recovered. + +Maintained by [@joshdougall](https://github.com/joshdougall) (Head of Infra). Coordination point for anything below. + +## Deep-link map + +### By intent + +| If you are asking… | Go to (upstream) | +|---|---| +| What infrastructure runs at ChainSafe? Service catalog. | [`docs/service-catalog.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/service-catalog.md) | +| What's our tech stack across infra? | [`docs/tech-stack.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/tech-stack.md) | +| I'm joining the infra team / picking up infra work. Where do I start? | [`docs/onboarding.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/onboarding.md) | +| What's on the infra roadmap? | [`docs/endgame-roadmap.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/endgame-roadmap.md) | +| How do we triage infra backlog? | [`docs/backlog-triage.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/backlog-triage.md) | +| What's our monitoring footprint? | [`docs/observability/monitoring-inventory.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/observability/monitoring-inventory.md) | +| How do we profile production services? | [`docs/observability/profiling.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/observability/profiling.md) | + +### By configuration domain + +| Need to change… | Go to (upstream) | +|---|---| +| Ansible roles / config management | [`ansible/`](https://github.com/ChainSafe/infrastructure-general/tree/main/ansible) — 9 execution directories (Ethereum, Filecoin, Forest, Gossamer, IPFS, OP, Polkadot, zkVerify, general) | +| Terraform / cloud provisioning | [`terraform/`](https://github.com/ChainSafe/infrastructure-general/tree/main/terraform) — Auth0, data-analytics, Forest, Gossamer, Grafana Cloud, infra-dev, infra-prod, k8s, Sygma | +| Docker images we build | [`images/`](https://github.com/ChainSafe/infrastructure-general/tree/main/images) — filecoin-bootnode-monitor, grafana-alloy, nebula, polkadot-crunch, snapshot-service | +| Internal tooling and scripts | [`tools/`](https://github.com/ChainSafe/infrastructure-general/tree/main/tools) | + +### By product + +For product-specific infra (deployment patterns, service architecture, environment topology), the `docs/projects/` tree is the canonical home: + +| Product area | Upstream path | +|---|---| +| Canton | [`docs/projects/canton/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/canton) — developer guide, k8s deployment, SV rewards, scan reports | +| Filecoin / Forest | [`docs/projects/filecoin/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/filecoin) — staging env, faucet ops, snapshot service, bootnodes, archival nodes | +| Ethereum / Lodestar | [`docs/projects/ethereum/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/ethereum) — Lodestar public services, production operations, SSV analysis, Lido validator ejector | +| SSV operators | [`docs/projects/ssv/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/ssv) — onboarding, operator registration, metadata updates, Hoodi testnet | +| IPFS | [`docs/projects/ipfs.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/ipfs.md) | +| Drand | [`docs/projects/drand/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/drand) | +| WalletConnect | [`docs/projects/walletconnect/`](https://github.com/ChainSafe/infrastructure-general/tree/main/docs/projects/walletconnect) | + +## How to use this page + +- **As an agent:** before any task touching infrastructure, IaC, deploy, observability, or production systems, consult the intent table above. Read the upstream `AGENTS.md` for that repo's entrypoints. Do not paraphrase upstream content — fetch the actual file. +- **As an operator:** when reviewing an infra-adjacent PR, use this map to find the canonical reference. If a PR touches infra without referencing the relevant upstream doc, ask why. +- **As a contributor:** if you find yourself wanting to add infra content to this handbook, add it to `infrastructure-general` instead and update the deep-link here. + +## What stays in this handbook vs. defers upstream + +This handbook keeps the **operator decision policy** layer: + +- When to deploy vs. when to wait (see [`release-and-deploy.md`](./release-and-deploy.md)). +- When to page vs. when to investigate quietly (see [`incident-response.md`](./incident-response.md)). +- Who approves what. + +Everything else — *how* to deploy, *how* to page, *how* to investigate — defers to `infrastructure-general`. The split is intentional: policy in the handbook, execution in the infra repo. + +## Coordination + +[@joshdougall](https://github.com/joshdougall) is the upstream maintainer and the CODEOWNER for this pointer page (see [`../.github/CODEOWNERS`](../.github/CODEOWNERS)). Any change to the deep-link map goes through him. + +When the upstream repo restructures, this page updates. The agreement is: the pointer page is the handbook's contract with `infrastructure-general`; broken links here are a bug. + +## Related + +- [`incident-response.md`](./incident-response.md) — incident workflow; deep-links into `infrastructure-general/docs/runbooks/`. +- [`release-and-deploy.md`](./release-and-deploy.md) — release/deploy workflow; deep-links into the same. +- [`repo-and-ci-setup.md`](./repo-and-ci-setup.md) — per-repo hygiene that sits *under* the infra layer. +- [`../references/sources.md`](../references/sources.md) — full catalog of external canonical sources. + diff --git a/workflows/oneflow.md b/workflows/oneflow.md new file mode 100644 index 0000000..9ef181b --- /dev/null +++ b/workflows/oneflow.md @@ -0,0 +1,134 @@ +# OneFlow + +ChainSafe's branching and release model. Trunk-based, minimalist, tag-driven. Built around a single long-lived branch (`main`) with tags as the deployment markers — everything else is circumstantial and short-lived. + +> **In one line:** One branch. Feature branches off it, merged back. Tags drive deployments. No long-lived release branches, no back-merging. + +## Why OneFlow + +The well-known git workflows — GitFlow, GitHub Flow, GitLab Flow — are branch-heavy. They produce a lot of back-and-forth on CI, merging, commit tracking, and back-merging. That cost compounds in CI/CD-first development cycles, where deployments are frequent and most "what shipped where" answers need to be obvious from the repo state alone. + +OneFlow is not a silver bullet. Its strength is its minimalism: one branch, tags for deployments, short-lived everything-else. The trade-off is that some scenarios (long-running parallel release lines, multi-version maintenance) require additional discipline OneFlow doesn't prescribe — but those scenarios are rare at ChainSafe. + +This document is the ChainSafe variant of the OneFlow concept (the broader pattern is described by Adam Ruka at [endoflineblog.com](https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow); our variant uses specific tag conventions for environments). + +## Branches + +There is exactly one long-lived branch: **`main`**. Every other branch is short-lived and exists only until merged back into `main`. + +### Branch naming + +| Pattern | Purpose | +|---|---| +| `/` (e.g. `alex/add-rate-limiter`, `sam/fix-nonce-bug`) | Personal feature branches. Use your GitHub handle or a consistent identifier as the prefix. Git stores branches with `/` as a directory delimiter (see `.git/refs/heads/`), so this gives every contributor their own namespace. | +| `hotfix/` (e.g. `hotfix/auth-leak`) | Branches off a broken production tag to ship an emergency fix. See [Hot fixes](#hot-fixes-of-tagged-deployments). | +| `release/` (e.g. `release/v0.23.1-rc`) | Used only for back-porting an earlier release. Most ChainSafe work does not need release branches because tags do the job. | + +### Branch diagram + +```mermaid +gitGraph + commit + commit + branch user/feature-one + commit + commit + checkout main + commit + branch user/feature-two + commit + checkout main + merge user/feature-one + merge user/feature-two + commit +``` + +Two feature branches off `main`, both merged back. No long-lived parallel branches. + +## Tags as deployment markers + +OneFlow leans on tags, not branches, to mark what's deployed where. Tags are global, branch-independent, and well-supported in modern CI/CD systems. + +| Environment | Marker | +|---|---| +| **Development** | `HEAD` of `main` | +| **Staging** | `stage-*` tags (e.g., `stage-2026-05-27`, `stage-rc`) | +| **Production** | `v.*.*` semantic-version tags (e.g., `v1.4.0`, `v2.0.0-rc.1`) | + +Tag-driven CD pipelines watch for these patterns and deploy automatically. Operators control deployments by *tagging*, not by *merging*. + +### Deployment diagram + +```mermaid +gitGraph + commit + commit tag: "stage-1" + commit + commit tag: "v1.0.0" + commit + commit tag: "stage-2" + commit + commit tag: "v1.1.0" +``` + +`main` advances; tags accumulate. The production line is the sequence of `v.*.*` tags. The staging line is the sequence of `stage-*` tags. Development is wherever `HEAD` is right now. + +### Preview deployments + +PR-preview deployments and other on-demand environments are layered on top as needed — OneFlow doesn't prescribe their shape. Establish them on an on-need basis per project. + +### Tag protection + +GitHub supports [tag protection rules](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/configuring-tag-protection-rules) — only users with write access can create tags matching protected patterns, and only admins can delete them. Configure these for `v.*.*` and `stage-*` patterns as a security baseline; the tag *is* the deployment authority, so unauthorized tag creation is unauthorized deployment. + +See [`repo-and-ci-setup.md` §7](./repo-and-ci-setup.md#7-security-baseline) for the broader security baseline. + +## Hot fixes of tagged deployments + +When a production tag breaks, you ship a hot fix without waiting for the next planned release: + +1. Create a `hotfix/` branch off the broken production tag (not off `main` — the broken tag is the parent because that's the state you're patching). +2. Land the fix on the hotfix branch. Test it. +3. Tag a new `v.*.*` (typically a patch bump, e.g., `v1.4.0` → `v1.4.1`). CD picks it up and deploys. +4. **Merge the `hotfix/*` branch back into `main`**, then let it flow through the staging environment before the next planned release tag. This is non-negotiable — leaving the fix unmerged means the next release reintroduces the bug. + +### Hot-fix diagram + +```mermaid +gitGraph + commit + commit tag: "v1.4.0" + commit + commit + branch hotfix/auth-leak + checkout hotfix/auth-leak + commit + commit tag: "v1.4.1" + checkout main + merge hotfix/auth-leak + commit +``` + +The hot fix is tagged `v1.4.1` directly on the `hotfix/*` branch (it ships from there). After deployment, the branch merges back into `main` so the fix is in trunk for the next release. + +## When OneFlow doesn't fit + +OneFlow assumes: + +- One production line at a time (or, equivalently, the team is willing to handle parallel production lines manually with `release/*` branches). +- Tags are protected and tag-creation is the deployment trigger. +- CI/CD watches the trunk and the tag patterns; there's no separate "release branch CD" pipeline. + +When those assumptions break — long-lived parallel release lines (e.g., maintaining v1 and v2 of a public library simultaneously), regulated environments requiring branch-based release artifacts — extend with `release/` branches and treat them as additional trunks. Document the deviation per-project; OneFlow remains the default. + +## Relationship to other workflow pages + +- [`pr-authoring.md`](./pr-authoring.md) — how to open and ship the feature branches that OneFlow assumes. +- [`code-review.md`](./code-review.md) — how those PRs get reviewed before merging to `main`. +- [`release-and-deploy.md`](./release-and-deploy.md) — the operator decisions wrapped around the actual tag-create-and-deploy step. +- [`repo-and-ci-setup.md`](./repo-and-ci-setup.md) — branch protection on `main`, tag protection for `v.*.*` and `stage-*`, CI baseline that watches the tags. + +## Related + +- Adam Ruka's original ["OneFlow — a Git branching model and workflow"](https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow) — the broader concept this page adapts. +- [`../invariants/engineering-invariants.md`](../invariants/engineering-invariants.md) — the "standards are enforced, not suggested" invariant that branch protection and tag protection make real. diff --git a/workflows/pr-authoring.md b/workflows/pr-authoring.md new file mode 100644 index 0000000..b030589 --- /dev/null +++ b/workflows/pr-authoring.md @@ -0,0 +1,91 @@ +# PR Authoring + +How to open and shepherd a pull request — written for the agent era, where many PRs are drafted by an agent under operator supervision and reviewed by humans, agents, or both. + +> **In one line:** Small, focused, audit-able. The PR is the operator's review surface; the author makes that surface tractable. + +## Branching + +Branch naming follows [OneFlow](./oneflow.md): personal feature branches are `/` (e.g., `alex/add-rate-limiter`). The `/` is meaningful — git uses it as a directory delimiter in `.git/refs/heads/`, so each contributor's branches share a namespace. PRs target `main` unless your CODEOWNERS designate otherwise. Hot fixes go on `hotfix/` and follow the [hot-fix flow](./oneflow.md#hot-fixes-of-tagged-deployments). + +## The default workflow + +For any non-trivial code change, the canonical workflow is the [`chainsafe-research-plan-implement`](../skills/chainsafe-research-plan-implement/SKILL.md) skill: **research → plan → annotate (1–6 rounds) → implement**. The skill enforces a human-approved plan as a gate on any code change. + +This page does not re-derive the workflow. When the PR author is an agent, the skill is loaded and followed. When the PR author is a human, the same shape applies — write a research artifact when context is non-obvious, write a plan when the work touches more than one file, accept annotation as you go, and only then commit code. + +## Small, focused, self-contained + +These practices draw on Google's engineering review best practices and ChainSafe's established conventions: + +- **One PR, one self-contained change.** The PR addresses one thing plus its tests. It can be reviewed in a single ~10-minute pass. +- **Separate refactors from features and fixes.** A refactor is its own PR. The exception is a small refactor (<~50 lines) genuinely entangled with the feature. +- **Renames, deletions, and generated-code PRs may be large** because they trade scope-width for shallow review depth. +- **Stack PRs when work is sequential.** When a feature naturally splits into ordered pieces, ship them as a stack of small PRs rather than one big PR. + +The right question: *is this change related to the PR's stated goal, or can it live on its own?* If the latter, separate PR. + +## What goes in the PR description + +Every non-trivial PR opens with a description that lets a reviewer decide whether to engage in 30 seconds and finish the review in 10 minutes. + +Required: + +- **What changed.** Two or three sentences, in plain language. Not a file-by-file walkthrough. +- **Why it changed.** Link to the issue, ADR, or spec. If there isn't one, write the why inline. +- **Acceptance criteria or test plan.** What "done" looks like; how the reviewer can verify. +- **Out-of-scope notes.** Anything the reader might expect to see in the diff but didn't, with a one-line reason. +- **Operational impact.** The change's operational contract: env vars, secrets, config keys, schema/migrations, or ports added or changed; backwards-compatibility impact; and anything the team that runs the service (Infra or the owning team) must do. "None" is a valid answer — but answer it. This is [Engineering Invariant 8](../invariants/engineering-invariants.md#8-a-change-carries-its-operational-contract); contract-altering changes also trip the [operational-contract gate](../operating-model/gates-and-escalation.md#9-operational-contract-changes). + +Agent-era additions: + +- **AI-generated declaration.** If an agent drafted any substantive portion of the change, say so. A line like "Drafted by Claude Code following the `chainsafe-research-plan-implement` skill; reviewed by @author" is sufficient. +- **Link to the plan artifact.** If the work followed research/plan/implement, link the `plan.md` (or paste the relevant section). Reviewers should be able to see what the operator approved. +- **Assumption surfacing.** Any non-obvious assumption the agent made that the operator did not explicitly confirm, called out so reviewers can challenge it. +- **Scope drift flags.** If the diff touches files that weren't in the original ticket scope, name each one with a one-line reason. This is the [scope-discipline invariant](../invariants/agent-era-invariants.md#1-no-silent-edits-outside-the-operator-named-scope) made visible. + +## Commits + +- **Commit messages describe intent, not just diff.** "Renamed X to Y" is what the diff already says; the message adds "because the legacy name conflicted with the new domain term." +- **Responses to reviewer comments land as new commits**, not as edits to existing ones. The history of the review is part of the PR. +- **Squash on merge** if your repo's convention is squash; otherwise let the commit train through. CODEOWNERS hold the line on the convention; defer to them. + +## Reviewer requests + +- For repos with CODEOWNERS configured, GitHub auto-requests the right reviewers — do not override unless adding to that list. +- For repos without CODEOWNERS, the two-team pattern applies: a `-admins` team for senior approvals, a `` team for peer review. (See [`repo-and-ci-setup.md`](./repo-and-ci-setup.md).) +- If you are blocked on review for >1 business day, ping the reviewer in the team channel. Speed matters; see the [reviewer guide on speed](./code-review.md). + +## Handling reviewer comments + +- **Address every comment.** Not necessarily by changing the code — a reply explaining why you made the choice you did is a valid response. +- **Do not self-resolve threads** unless the change is trivial (typo, lint). The reviewer resolves their own comments after the response satisfies them. +- **Disagreements escalate.** If you and the reviewer disagree on a substantive point, get a third opinion from the CODEOWNER or curator. Do not merge through a disagreement. +- **For agents:** when an operator review surfaces a misunderstanding of the original plan, do not just patch the diff. Update the `plan.md` to record what changed and why, then re-implement the affected slice. This keeps the plan as the source of truth. + +## What goes in a "walkthrough" + +For changes that genuinely warrant explanation beyond what fits in a PR description — substantial new modules, architectural shifts, security-sensitive code — write a walkthrough. Options: + +- An inline section in the PR description. +- A linked ADR in the repo. +- A short Loom or recorded session linked in the PR. + +The threshold: if a reviewer's first comment is going to be "can we hop on a call to go through this," the walkthrough already needed to exist. + +## Anti-patterns + +- **The mega-PR.** "It's all related" — usually it isn't. +- **The drive-by refactor.** Renaming variables across the codebase in the same PR as a bugfix. Split it. +- **The silent re-scope.** Adding files to the diff without naming them in the PR description. +- **The agent ghost-author.** A PR drafted by an agent without an AI-generated declaration. The convention exists to make review better, not as a confession. +- **The "fixed it" reply.** Responding to a reviewer comment with "done" and no detail. If the fix is non-trivial, link the commit and explain in one line. + +## Related + +- [`code-review.md`](./code-review.md) — the reviewer's counterpart to this page. +- [`oneflow.md`](./oneflow.md) — ChainSafe's branching and release model; defines branch naming, the trunk-based flow, and the tag patterns that drive deployments. +- [`../skills/chainsafe-research-plan-implement/SKILL.md`](../skills/chainsafe-research-plan-implement/SKILL.md) — the workflow this page assumes for non-trivial PRs. +- [`../invariants/agent-era-invariants.md`](../invariants/agent-era-invariants.md) — scope discipline (§1), no-fabrication (§2), audit-trail (§8). +- [`../operating-model/collaborator-statement.md`](../operating-model/collaborator-statement.md) — operator and agent responsibilities the PR makes concrete. +- [`repo-and-ci-setup.md`](./repo-and-ci-setup.md) — branch protection and CODEOWNERS conventions PRs land against. diff --git a/workflows/release-and-deploy.md b/workflows/release-and-deploy.md new file mode 100644 index 0000000..6b47ac0 --- /dev/null +++ b/workflows/release-and-deploy.md @@ -0,0 +1,103 @@ +# Release and Deploy + +This handbook holds the **operator decision policy** for shipping work. The underlying branching and tag-driven flow is [OneFlow](./oneflow.md) — trunk-based, with `v.*.*` tags marking production deployments and `stage-*` tags marking staging. The *how-to* for any specific deploy — commands, environment-specific scripts, rollback mechanics — lives in [`ChainSafe/infrastructure-general`](https://github.com/ChainSafe/infrastructure-general). + +> **In one line:** When to ship, who approves, what counts as ready. The flow is [OneFlow](./oneflow.md); the operator decisions live here; the *how* defers to the infra repo. + +## Operator decision policy + +These are the calls a human makes before, during, and after a deploy. The infra repo's runbooks tell you what to run; this page tells you whether to run it. + +### Deploy readiness — pre-flight + +Before any deploy to a non-dev environment, the operator confirms: + +- **CI is green** on the release commit. Required checks from [`repo-and-ci-setup.md` §3](./repo-and-ci-setup.md#3-branch-protection) pass. +- **Acceptance criteria are met** for every change in the release (see [Engineering Invariant §3](../invariants/engineering-invariants.md#3-quality-is-defined-before-the-build-not-after)). +- **HARD FAIL findings are resolved** — or, in the explicit-override case, the override is logged in the PR per [agent-era invariant §7](../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). +- **The runbook for this product exists** and the deploy procedure is mapped. If the runbook is missing, the deploy is blocked until one is written or the missing-section gap is escalated. +- **Rollback path is known** before the deploy starts. "How do we undo this if it goes wrong" is not a question to figure out mid-incident. +- **No active release freeze.** Mobile or infrastructure-wide freezes (announced in advance) preempt individual deploys. + +If any of these fails, the operator does not deploy. The agent does not push past the gate. + +### Approval matrix + +| Deploy target | Who approves | +|---|---| +| Local / dev environment | The author | +| Staging / test environment | The author + a CODEOWNER for the affected product | +| Canary / a subset of production | A CODEOWNER + the on-call for the affected product | +| Full production | A CODEOWNER + the on-call + (for security-critical or breaking changes) the curator or a Head of Engineering | +| Hot-fix during an incident | The on-call may proceed with a single CODEOWNER's approval; post-hoc review is mandatory | + +Per the [version-control gate](../operating-model/gates-and-escalation.md#5-version-control-state), agents never push to protected branches or execute merges. The operator merges; the operator (or the deploy tooling under the operator's supervision) deploys. + +### During the deploy + +- **Watch the relevant dashboards** through the deploy. Inventory is in [`infrastructure-general/docs/observability/monitoring-inventory.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/observability/monitoring-inventory.md); the runbook for the specific product names which dashboards to follow. +- **Don't multitask** during the watch window. Production deploys are a "your hands are on the wheel" task. +- **Have the rollback command ready** — typed but not executed — for the duration of the watch window. + +### Post-deploy + +- **Confirm the change took effect.** The deploy succeeded ≠ the change is doing what was intended. Verify against the acceptance criteria from §1. +- **Update the relevant status surface** if the deploy was announced (status page, internal channel, customer-facing release notes). +- **Note any anomalies** in the deploy log, even if they resolved on their own. They will help when something similar happens next time. + +### Release freezes + +Release freezes are announced in advance and noted in the relevant project tracker. The handbook does not maintain a freeze calendar — that's product-specific. When a freeze is active for a given product, deploys for that product require explicit lift-the-freeze approval from the Head of Engineering or the product lead. + +If you are an agent helping with deploys and you have not been told whether a freeze is active, ask before proceeding. + +## Deploy procedure deep links + +Deploy procedures are product-specific and live in `infrastructure-general`: + +| Product / area | Procedure location | +|---|---| +| Canton (k8s) | [`docs/projects/canton/canton-k8s-deployment.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/canton/canton-k8s-deployment.md), [`canton-deploy-new-app.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/canton/canton-deploy-new-app.md) | +| Forest staging environment | [`docs/projects/filecoin/forest-staging-environment.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/filecoin/forest-staging-environment.md) | +| Lodestar production operations | [`docs/projects/ethereum/lodestar-production-operations.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/ethereum/lodestar-production-operations.md) | +| Lodestar public services | [`docs/projects/ethereum/lodestar-public-services.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/ethereum/lodestar-public-services.md) | +| SSV operator onboarding | [`docs/projects/ssv/onboarding-validator.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/ssv/onboarding-validator.md), [`operator-registration.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/ssv/operator-registration.md) | +| Faucet operations | [`docs/projects/filecoin/faucet-operations.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/filecoin/faucet-operations.md) | +| Snapshot service | [`docs/projects/filecoin/snapshot-service.md`](https://github.com/ChainSafe/infrastructure-general/blob/main/docs/projects/filecoin/snapshot-service.md) | +| IaC / Terraform changes | [`terraform/`](https://github.com/ChainSafe/infrastructure-general/tree/main/terraform) — each subdirectory has its own README | +| Ansible-driven deploys | [`ansible/`](https://github.com/ChainSafe/infrastructure-general/tree/main/ansible) | + +If a procedure isn't listed: it may not exist yet. Surface to [@joshdougall](https://github.com/joshdougall) before improvising. + +## Agent role in releases and deploys + +Useful: + +- Drafting the release notes from the PRs in the release. +- Generating the deploy plan (steps, commands, expected outputs) from the runbook for operator approval. +- Watching dashboards alongside the operator, summarizing anomalies in plain language. +- Running pre-flight verification (CI status, acceptance-criteria check against PRs). + +Not useful: + +- Executing the deploy commands without explicit per-step operator approval. Production deploy is an [§1 gate](../operating-model/gates-and-escalation.md#1-production-and-deployment); see the standard stop pattern. +- Approving HARD FAIL overrides on the operator's behalf. +- Authorizing a rollback. Rollbacks are the operator's call; the agent prepares the command, the operator runs it. + +## Anti-patterns + +- **"Deploy then verify."** Verification is part of the deploy, not after it. +- **Friday afternoon deploys.** Avoid unless the deploy is the fix to a Friday incident. The cost of a regression discovered Saturday is asymmetric. +- **Skipping the rollback path.** If you can't say how you'd undo this, you aren't ready to do it. +- **Multi-deploy parallelism.** Two deploys at once means you can't tell which one broke the dashboard. Sequential by default. +- **Agent auto-deploy on green CI.** Green CI is necessary, not sufficient. The operator makes the call. + +## Related + +- [`oneflow.md`](./oneflow.md) — the branching and tag-driven release model this page wraps. Defines `v.*.*` and `stage-*` tag conventions and the hot-fix flow. +- [`infrastructure-and-devops.md`](./infrastructure-and-devops.md) — broader infra deep-link map. +- [`incident-response.md`](./incident-response.md) — what to do when a deploy goes wrong. +- [`repo-and-ci-setup.md`](./repo-and-ci-setup.md) — CI baseline the pre-flight readiness check assumes. +- [`pr-authoring.md`](./pr-authoring.md) — where acceptance criteria come from. +- [`../operating-model/gates-and-escalation.md`](../operating-model/gates-and-escalation.md) — §1 (production / deployment) and §5 (version-control state). +- Upstream: [`ChainSafe/infrastructure-general`](https://github.com/ChainSafe/infrastructure-general) — every actual procedure. diff --git a/workflows/repo-and-ci-setup.md b/workflows/repo-and-ci-setup.md new file mode 100644 index 0000000..d2af735 --- /dev/null +++ b/workflows/repo-and-ci-setup.md @@ -0,0 +1,152 @@ +# Repo and CI Setup + +The per-repo hygiene checklist for a new (or newly-audited) repository at ChainSafe, structured as an agent-runnable runbook. The operator approves the plan; the agent executes; each step has a rollback path. + +> **In one line:** Branch protection, CODEOWNERS, CI, security baseline. Anything cluster-, account-, or env-level defers to [`ChainSafe/infrastructure-general`](https://github.com/ChainSafe/infrastructure-general). + +## How to use this page + +This is a checklist, not a tutorial. Each item names what gets configured, why, and how the agent verifies success. When run by an agent under operator supervision, every step gets: + +1. A plan (what the agent will change, in concrete terms). +2. Operator approval. +3. Execution. +4. Verification. +5. A rollback note if the step did anything destructive. + +Per the [repo-boundaries gate](../operating-model/gates-and-escalation.md#6-repository-and-account-boundaries), the agent operates only on the repo the operator names. + +## 1. Project creation + +- **Action.** Create the repo under the `ChainSafe` GitHub organization. +- **Defaults.** Public, with a `README.md` and a `LICENSE`. License is Apache 2.0 unless the project has a documented reason otherwise (see [`../README.md` License section](../README.md#license)). +- **If permission is missing,** reach out to an org owner (e.g., a Head of Engineering). +- **Rollback.** Delete the repo if no commits beyond the initial scaffolding have landed. + +## 2. Team permissions + +- **Create or reuse two GitHub teams:** `-admins` for senior/admin staff, `` for the working group. +- **Grant `` Write permission**; grant `-admins` Admin. +- **Add the org-wide `ChainSafe` team with Read** unless the project is sensitive (private repo, audit-restricted code). If so, omit and note the reason in the repo README. +- **Verification.** Org-level audit log shows the team additions. +- **Rollback.** Remove team permissions; no data loss. + +## 3. Branch protection + +Configure `Settings → Branches → Add Rule` (or edit existing) for `main` (and any other long-lived branch like `develop` or `release`). + +Baseline rule set: + +- **Require pull request before merging.** Always. +- **Required approving reviews:** 1 for small teams, 2 for security-critical or high-traffic repos. +- **Dismiss stale approvals when new commits are pushed.** On. +- **Require review from CODEOWNERS.** On (after [§5](#5-codeowners) below). +- **Require status checks to pass before merging.** On. Listed checks come from [§6](#6-ci) below. +- **Require branches to be up to date before merging.** On. +- **Require linear history.** Optional; depends on whether the repo's convention is squash or merge commits. +- **Require signed commits.** On for security-critical repos; consider for all. +- **Restrict who can push to matching branches.** Disable direct push for everyone (force PR flow). +- **Allow force pushes / Allow deletions.** Off. + +Verification: open a PR against `main` with no reviewers; confirm merge is blocked. + +Rollback: branch protection settings are version-history'd in GitHub's audit log; you can revert to a prior state. Not destructive. + +## 4. Merge button settings + +`Settings → General → Pull Requests`: + +- **Allow squash merging.** On (default). +- **Allow merge commits.** Off unless the repo has a reason (release branches, etc.). +- **Allow rebase merging.** Off by default; enable per-project if the team uses it. +- **Always suggest updating PR branches.** On. +- **Automatically delete head branches.** On. + +Disable merge commits and rebase by default; squash keeps `main` history clean. + +## 5. CODEOWNERS + +- **Create `.github/CODEOWNERS`** with the structure: + - Catch-all owner at the top (a team or set of individuals). + - Section-specific overrides below, ordered from general to specific. +- **For the handbook repo specifically,** the v2 model uses [@kalambet](https://github.com/kalambet) as the catch-all curator with overrides for `invariants/invariants-framework.md` (@boorich), `workflows/*` infra pointer pages (@joshdougall), etc. See [`../.github/CODEOWNERS`](../.github/CODEOWNERS). +- **Verify by opening a test PR** touching the catch-all area and confirming the right reviewer is auto-requested. +- **Rollback.** Revert the `.github/CODEOWNERS` file via PR. + +## 6. CI + +The CI baseline for ChainSafe repos: + +- **Lint.** Run the language-appropriate linter (ESLint/TypeScript, golangci-lint, clippy, etc.). +- **Format check.** Run formatter in check-mode (prettier, gofmt, rustfmt, etc.). Fail the build if formatting is off. +- **Type check.** For typed languages, run the typechecker as a separate step (avoids "tests pass but types break" outcomes). +- **Tests.** Unit, integration, end-to-end as the project warrants. See [`testing-and-qa.md`](./testing-and-qa.md). +- **Build.** Confirm the artifact actually builds. +- **License-checker.** Verify no GPL or otherwise incompatible licenses entered dependencies (especially for products meant to be Apache 2.0–licensed downstream). + +Each becomes a required check in branch protection (§3 above). + +## 7. Security baseline + +- **Secret scanning.** GitHub native secret scanning enabled (`Settings → Code security and analysis`). +- **Dependency review.** GitHub's dependency review action on PRs, configured to fail on critical/high vulnerabilities. +- **SBOM generation.** As part of release artifacts where applicable. CycloneDX or SPDX format. +- **Dependabot or Renovate.** For automated dependency updates with security-patch auto-merge gated by a human review. +- **Signed commits.** Strongly recommended; required for security-critical repos. +- **CodeQL or equivalent SAST.** For repos producing user-facing or smart-contract code. + +## 8. Labels + +A consistent label taxonomy makes triage and reporting tractable. ChainSafe baseline: + +- **Status:** `triage`, `accepted`, `in-progress`, `blocked`, `wontfix`. +- **Type:** `bug`, `feature`, `chore`, `docs`, `security`, `refactor`. +- **Priority:** `p0` (critical), `p1` (high), `p2` (medium), `p3` (low). +- **Special:** `good-first-issue`, `help-wanted`, `breaking-change`. + +Apply via the `labels` API or a labels-config tool (e.g., `github-label-sync`) so the set is reproducible across repos. + +## 9. CLA bot + +For public repos accepting external contributions, install the [CLA Assistant](https://github.com/cla-assistant/cla-assistant) (or equivalent). External contributors sign the ChainSafe CLA before their PR can merge. + +Internal-only repos can skip this step. + +## 10. Notifications and integrations + +- **Slack notifications.** Wire the relevant team channel for PR opens, reviews, and merges. Volume: opt for "all events" on small repos, "review requested + merged" on large ones. +- **Scheduled reminders.** A weekly bot ping for stale PRs (>3 business days without review). +- **Linear / Jira integration.** If the project tracks work outside GitHub, wire the integration so PRs link issues and vice versa. + +## What this page does NOT cover + +Anything cluster-, account-, or env-level defers to [`infrastructure-general`](https://github.com/ChainSafe/infrastructure-general): + +- Cluster setup (EKS, Hetzner k8s). +- IaC provisioning (Terraform). +- Configuration management (Ansible). +- Observability (Grafana, Prometheus, alerting). +- Deploy pipelines and release tooling. +- On-call rotations. + +See [`infrastructure-and-devops.md`](./infrastructure-and-devops.md) for the pointer. + +## Verification: end-to-end smoke test + +After running through the checklist, the agent (or operator) verifies the setup with one PR: + +1. Open a PR with a trivial change. +2. Confirm CI runs all required checks. +3. Confirm CODEOWNERS auto-requested the right reviewer. +4. Confirm merge is blocked until checks pass and review approves. +5. Approve and merge; confirm the head branch is auto-deleted. + +If any of those don't happen, fix the misconfiguration before considering the repo "set up." + +## Related + +- [`pr-authoring.md`](./pr-authoring.md) — how PRs against this repo get authored. +- [`code-review.md`](./code-review.md) — how PRs get reviewed. +- [`testing-and-qa.md`](./testing-and-qa.md) — the testing baseline CI enforces. +- [`infrastructure-and-devops.md`](./infrastructure-and-devops.md) — anything beyond per-repo hygiene. +- [`../operating-model/gates-and-escalation.md`](../operating-model/gates-and-escalation.md) — the gates relevant when running this checklist as an agent. diff --git a/workflows/skill-description-tuning.md b/workflows/skill-description-tuning.md new file mode 100644 index 0000000..249892b --- /dev/null +++ b/workflows/skill-description-tuning.md @@ -0,0 +1,171 @@ +# Skill Description Tuning + +A runbook for running Anthropic's `skill-creator` description-optimization loop on one of the skills in [`skills/`](../skills/). The loop iteratively sharpens a SKILL.md's `description` field for better triggering accuracy. + +> **In one line:** Opt-in, local-only, ~30–45 min wall-clock, Opus by default. Run when you have a reason to; not on a schedule, not in CI. + +## Policy + +The handbook's policy for this loop, in four points: + +- **Opt-in.** No skill in this repo is *required* to go through the loop. The lightweight "draft + self-check" approach is the floor for any skill; the loop is sharpening, not enforcement. +- **Local-only.** The loop calls `claude -p` (real Anthropic API spend) and takes ~30–45 minutes per skill. It runs on the operator's machine, on demand. CI does not invoke it. PRs touching a SKILL.md description are not gated by it. +- **Opus by default.** When you do run the loop, default to the most capable tier (`--model claude-opus-4-6` or current Opus generation). The per-skill quality gain is worth the extra cost on an opt-in run. Sonnet/Haiku overrides are available for cheaper iteration. +- **Non-deterministic, so re-run if outputs look off.** The optimizer is an LLM; the same input can produce different best-descriptions across runs. A single run is a draft, not an oracle. + +The rest of this page is the *how*. + +## When to run + +Three legitimate triggers: + +1. **A new skill is being added** and you want its description tuned before first commit. +2. **Engineers report triggering issues** — the skill keeps firing when it shouldn't, or never fires when it should. The complaint is your eval-set raw material. +3. **Periodic hygiene pass** before a release or every quarter — re-check that descriptions still match actual triggering needs. + +If none of those apply, don't run it. The lightweight "draft + self-check" floor is sufficient. + +## Prerequisites + +- **Claude Code installed** on your local machine with `claude -p` working (the loop calls it as a subprocess). +- **An active Anthropic API key** or whatever auth your Claude Code uses — the loop will consume real tokens. +- **Local clone of `engineering-handbook` on the branch you want to update** (typically `main`, or the working branch your team designates). +- **The skill-creator package available.** It's bundled with Claude Code; the script path is typically: + ``` + ~/.claude/skills/skill-creator/scripts/run_loop.py + ``` + Confirm with `find ~/.claude -name run_loop.py 2>/dev/null` if uncertain. +- **A defined skill to tune.** This runbook assumes a skill already exists in `skills/chainsafe-/SKILL.md`. + +## The flow + +### Step 1: Draft the eval set + +The eval set is ~20 realistic prompts split between *should-trigger* (the skill ought to fire) and *should-not-trigger* (near-misses that share keywords but actually need something else). Quality of the eval set determines quality of the tuned description. + +**What makes a good eval query:** + +- Concrete. Mention specific files, products, error messages, or refactor scopes. +- Realistic. Phrased the way an engineer would actually type it in chat — including casual phrasing, abbreviations, sometimes typos. +- ChainSafe-flavored where helpful. Reference Lodestar, Forest, Gossamer, Sygma, Canton — the product context an internal user would carry. +- Mixed-length. Some short queries, some with full backstory. +- Edge cases over clear-cut ones. The boundary cases teach the optimizer where the boundary actually is. + +**Bad eval queries** to avoid: + +- *"Format this data"* — too vague, not specific enough to test triggering. +- *"Write a Fibonacci function"* — too generic, doesn't test anything domain-specific. +- *"Write code for X"* — won't actually trigger any complex skill since simple coding tasks are handled directly. + +**Start from the committed template + a worked example.** Don't start from a blank file — copy [`skill-description-tuning/eval-set.template.json`](./skill-description-tuning/eval-set.template.json) and read a gold-standard set like [`chainsafe-research-plan-implement.eval-set.json`](./skill-description-tuning/chainsafe-research-plan-implement.eval-set.json) to see the should-trigger / should-not-trigger split in practice. Curated eval sets live in [`skill-description-tuning/`](./skill-description-tuning/) and are committed; the loop's scratch outputs are not (see that directory's README for the distinction). + +**Save as JSON:** + +```json +[ + {"query": "the user's prompt text", "should_trigger": true}, + {"query": "another prompt", "should_trigger": false}, + ... +] +``` + +Default file location: `-eval-workspace/eval-set.json` outside the handbook repo (or inside it under `.gitignore`d scratch space — the eval workspace is not committed). + +**Review the eval set carefully before running** — the loop will treat the labels as ground truth. A mis-labeled query gives a mis-tuned description. + +### Step 2: Run the loop + +**The on-ramp:** [`scripts/tune-skill-description.sh`](../scripts/tune-skill-description.sh) wraps the loop with the ChainSafe conventions baked in — Opus by default, sane flags, scratch outputs written outside the repo, and skill-name → path resolution. From the repo root: + +```bash +# preview the exact command without spending anything: +bash scripts/tune-skill-description.sh chainsafe-research-plan-implement --dry-run + +# run it for real (opt-in, local-only, ~30-45 min on Opus): +bash scripts/tune-skill-description.sh chainsafe-research-plan-implement +``` + +It resolves the eval set from `workflows/skill-description-tuning/.eval-set.json` by default; override with `--eval-set `. `--help` lists every flag plus the `TUNE_MODEL` / `TUNE_RESULTS_DIR` / `SKILL_CREATOR_DIR` env overrides. + +**What it runs under the hood** — the raw skill-creator invocation, if you'd rather drive it yourself: + +```bash +cd ~/.claude/skills/skill-creator # so `python -m scripts.run_loop` resolves +python -m scripts.run_loop \ + --eval-set \ + --skill-path /skills/chainsafe- \ + --model claude-opus-4-6 \ + --max-iterations 5 \ + --verbose +``` + +(Replace `claude-opus-4-6` with the current Opus generation if it's been bumped — `claude-opus-4-7`, etc.) + +**Override flags worth knowing:** + +| Flag | Purpose | Default | +|---|---|---| +| `--model` | Which Claude model to use as the optimizer + triggering tester | `claude-opus-4-6` (ChainSafe default — Opus is the recommended tier when running the loop) | +| `--max-iterations` | How many improve-and-re-evaluate cycles | 5 (good default) | +| `--verbose` | Print iteration progress to stdout | recommended on | + +**Cheaper iteration:** for experimental skills or rapid prototyping, override with `--model claude-sonnet-4-6` or `--model claude-haiku-4-5`. The quality of the resulting description will likely be worse, but the run is faster and cheaper. Document the model used in the PR that lands the resulting `best_description`. + +**Wall-clock expectation:** ~30–45 minutes on Opus, ~15–25 minutes on Sonnet, ~10 minutes on Haiku. The loop runs each query 3× per iteration for stable trigger-rate measurement, which is most of the time. + +### Step 3: Review the report + +The loop produces an HTML report — typically `report.html` in the workspace directory. Open it in your browser. It shows: + +- **Per-iteration triggering scores** (train + held-out test). +- **The `best_description`** (selected by *test* score, not train, to guard against overfitting). +- **Per-query diagnostics** — which queries triggered, which didn't, and how the trigger rate changed across iterations. + +The non-deterministic note: re-running the loop on the same eval set gives slightly different `best_description` outputs. The test score is what determines the winner across the iteration set; that's the number to compare. + +### Step 4: Apply the result + +Take `best_description` from the report (or from the JSON output the script also writes), and update the skill's SKILL.md frontmatter: + +```yaml +--- +name: chainsafe- +description: +metadata: + ... + description-tuned: (run_loop on ) +--- +``` + +The `description-tuned` metadata field is optional but worth adding — it records when the description was last optimized and on what model, so future hygiene passes know when it's time for another run. + +### Step 5: Ship as a normal PR + +A SKILL.md description change is just another PR. + +- Target branch is `main` (or the working branch your team designates). +- PR description includes the before/after description plus the test-score delta from the report. +- Standard review — see [`pr-authoring.md`](./pr-authoring.md) and [`code-review.md`](./code-review.md). +- The skills-sync CI check ([`scripts/check-skills-sync.sh`](../scripts/check-skills-sync.sh)) keeps the index honest; if you didn't change `llms.txt`, no update needed (descriptions are inlined in `llms.txt`'s skill entries — see if your one-line description in `llms.txt` should be refreshed alongside). + +## Common pitfalls + +- **Eval set too generic.** Generic queries don't trigger any skill cleanly; the loop has nothing to optimize against. Be specific. +- **Eval set too narrow.** All should-trigger queries phrased the same way → the optimizer over-fits to that phrasing → real users phrasing things differently still don't trigger. Mix phrasings. +- **Mis-labeled near-misses.** A *should-not-trigger* query that's actually a legitimate use of the skill confuses the loop into making the description narrower than it should be. Review labels carefully. +- **Running on Haiku for production-grade output.** Haiku's `best_description` is often weaker than the original. Use it only for experimentation; default is Opus for a reason. +- **Skipping the test-score check.** The loop selects `best_description` by held-out test score; spot-check that the test score is materially better than the original's test score. If it's not, the optimization didn't help — keep the original. + +## Anti-patterns + +- **Running the loop in CI.** Don't. Per the policy at the top of this page: the loop is opt-in and local-only. +- **Running the loop on every skill in one batch.** It's a per-skill exercise; batching introduces context-switching that doesn't pay off. +- **Letting the loop run without an eval set review pass.** The eval set is the contract; treat it as load-bearing. +- **Committing the eval workspace.** The workspace is scratch space — `report.html`, intermediate JSON, partial logs. None of it belongs in the repo. Add a `.gitignore` entry if you're keeping the workspace inside the clone. + +## Related + +- [`scripts/tune-skill-description.sh`](../scripts/tune-skill-description.sh) — the on-ramp wrapper this runbook drives. +- [`skill-description-tuning/`](./skill-description-tuning/) — committed eval-set template + worked examples (and the inputs-vs-scratch distinction). +- [`pr-authoring.md`](./pr-authoring.md) — how the resulting description change gets shipped. +- Upstream: [`anthropic-skills:skill-creator`](https://github.com/anthropics/skills) — the canonical playbook the runbook implements. diff --git a/workflows/skill-description-tuning/README.md b/workflows/skill-description-tuning/README.md new file mode 100644 index 0000000..6b6c182 --- /dev/null +++ b/workflows/skill-description-tuning/README.md @@ -0,0 +1,52 @@ +# Eval-set assets for description tuning + +Curated, **committed** inputs for the description-tuning loop documented in +[`../skill-description-tuning.md`](../skill-description-tuning.md). + +Two kinds of file live here: + +- **`eval-set.template.json`** — a fill-in-the-blank starting point. Copy it, + rename it for your skill, and replace the placeholder queries. +- **`.eval-set.json`** — a gold-standard eval set for a specific + skill (e.g. [`chainsafe-research-plan-implement.eval-set.json`](./chainsafe-research-plan-implement.eval-set.json)). + These are the worked examples — read one before drafting your own. + +## Committed inputs vs. scratch outputs + +These eval sets are **inputs**: hand-curated, reviewed, version-controlled, and +treated as load-bearing (a mislabeled query produces a mis-tuned description). + +The loop's **outputs** — `report.html`, `results.json`, `log.txt`, partial +logs — are scratch. They do **not** belong in the repo. The wrapper writes them +to a timestamped directory outside the working tree by default, and `.gitignore` +catches the `*-eval-workspace/` pattern as a backstop. Never commit a run's +workspace. + +## Format + +A JSON array of `{ "query", "should_trigger" }` objects: + +```json +[ + { "query": "the prompt an engineer would actually type", "should_trigger": true }, + { "query": "a near-miss that shares keywords but needs something else", "should_trigger": false } +] +``` + +Aim for ~20 queries, mixed between should-trigger and should-not-trigger. +The should-not-trigger near-misses matter most — they teach the optimizer where +the skill's boundary actually is. See the parent runbook's "Draft the eval set" +step for what makes a good vs. bad query. + +## Using one + +```bash +# default path resolution (this directory, named after the skill): +bash scripts/tune-skill-description.sh chainsafe-research-plan-implement --dry-run + +# or point at any eval set explicitly: +bash scripts/tune-skill-description.sh chainsafe-go-reviewer \ + --eval-set workflows/skill-description-tuning/chainsafe-go-reviewer.eval-set.json --dry-run +``` + +Drop `--dry-run` to run for real (opt-in, local-only, ~30–45 min on Opus). diff --git a/workflows/skill-description-tuning/chainsafe-research-plan-implement.eval-set.json b/workflows/skill-description-tuning/chainsafe-research-plan-implement.eval-set.json new file mode 100644 index 0000000..ef6f810 --- /dev/null +++ b/workflows/skill-description-tuning/chainsafe-research-plan-implement.eval-set.json @@ -0,0 +1,22 @@ +[ + { "query": "implement EIP-7594 PeerDAS column custody in Lodestar's network layer", "should_trigger": true }, + { "query": "refactor Forest's snapshot import so it streams CAR chunks instead of loading the whole file into memory", "should_trigger": true }, + { "query": "there's a bug in Gossamer's GRANDPA vote tracking that only shows up under reorgs — track it down and fix it across the finality gadget", "should_trigger": true }, + { "query": "add a REST endpoint to the Lodestar beacon-node API for validator liveness tracking", "should_trigger": true }, + { "query": "migrate Sygma's relayer off the old fee oracle onto the new dynamic fee module", "should_trigger": true }, + { "query": "wire up Forest's RPC layer to the new ChainStore so eth_getBlockByNumber returns post-FVM receipts", "should_trigger": true }, + { "query": "rewrite the SSZ list hashing in lodestar-z to reuse the persistent merkle tree instead of recomputing roots each time", "should_trigger": true }, + { "query": "extend the Canton Super Validator app to record featured-app activity rewards in a new Daml contract", "should_trigger": true }, + { "query": "change how Lodestar's attestation pool dedupes aggregates — it's keeping duplicates across slots", "should_trigger": true }, + { "query": "build out a backfill job for Gossamer that re-indexes historical blocks into the new state trie format", "should_trigger": true }, + { "query": "integrate a circuit breaker into Sygma's bridge executor so one stuck deposit doesn't block the whole queue", "should_trigger": true }, + { "query": "restructure Forest's CLI so the daemon and the wallet commands live in separate crates", "should_trigger": true }, + { "query": "fix the typo in the Lodestar README — 'concensus' should be 'consensus'", "should_trigger": false }, + { "query": "run prettier on packages/beacon-node", "should_trigger": false }, + { "query": "bump the eslint version in Lodestar and fix the single lint warning it surfaces", "should_trigger": false }, + { "query": "what's the difference between GRANDPA and BABE in Gossamer?", "should_trigger": false }, + { "query": "explain how Forest's StateManager caches tipset state", "should_trigger": false }, + { "query": "rename the local variable `tmp` to `peerScore` in this one function", "should_trigger": false }, + { "query": "add a missing semicolon in sygma-core/src/executor.ts", "should_trigger": false }, + { "query": "what model should we default the skill-tuning loop to?", "should_trigger": false } +] diff --git a/workflows/skill-description-tuning/eval-set.template.json b/workflows/skill-description-tuning/eval-set.template.json new file mode 100644 index 0000000..900bf2f --- /dev/null +++ b/workflows/skill-description-tuning/eval-set.template.json @@ -0,0 +1,8 @@ +[ + { "query": "REPLACE — a realistic should-trigger prompt, phrased the way an engineer actually types it in chat (name a product, file, or error)", "should_trigger": true }, + { "query": "REPLACE — another should-trigger prompt, different phrasing and length than the first", "should_trigger": true }, + { "query": "REPLACE — an edge-case should-trigger prompt that sits near the skill's boundary", "should_trigger": true }, + { "query": "REPLACE — a near-miss that shares keywords with the skill but should NOT trigger it", "should_trigger": false }, + { "query": "REPLACE — another should-not-trigger near-miss (e.g. a conceptual question, or a trivial edit)", "should_trigger": false }, + { "query": "REPLACE — a should-not-trigger prompt that a careless description would wrongly catch", "should_trigger": false } +] diff --git a/workflows/testing-and-qa.md b/workflows/testing-and-qa.md new file mode 100644 index 0000000..11a4acd --- /dev/null +++ b/workflows/testing-and-qa.md @@ -0,0 +1,209 @@ +# Testing and QA + +How quality is built into the work — what agents generate, what operators own, where the boundary is, and how Forest's AI policy (carried from Ghostty) shapes the agent-era posture. + +> **In one line:** Agents generate the verification artifacts; operators own the verification *judgment*. Both are required; neither substitutes for the other. + +## Principles + +The core QA principles, sharpened for the agent era: + +- **Quality is everyone's responsibility.** Not "the QA team's"; not "the senior reviewer's." Authors, reviewers, operators, and the agents working under them are all on the hook. +- **Plan to succeed.** A definition of "done" before implementation, not after. See [Engineering Invariant §3 — Quality is defined before the build](../invariants/engineering-invariants.md#3-quality-is-defined-before-the-build-not-after). +- **Prevention beats reaction.** Catching a defect in a PR is cheap; catching it in production is expensive; catching it after it costs users is incomparable. Test early and thoroughly on every PR. +- **Be exploratory.** Test across scenarios users actually hit — devices, networks, wallet extensions, edge timing. Lab-only testing misses the field. + +## What agents generate + +Agents are good at producing verification *surface*. The default expectation when an agent drafts a change: + +- **Unit tests** for the new or changed functions, covering the happy path and the obvious edge cases. +- **Property-based tests** where the input space is large or the invariants are formal (cryptographic code, parsing, serialization). Quickcheck/proptest/fast-check style. +- **Fuzz inputs** for code that accepts untrusted input — protocol parsers, RPC handlers, anything taking bytes from the network. +- **Integration scaffolding** — test fixtures, mock servers, recorded traces — that make the operator's own verification cheaper. +- **A test plan in the PR description** stating what was tested, what wasn't, and why. + +Agents do these by default because they are easy to generate and hard to skip without losing review-time. If the agent's PR doesn't include any of the above and the change warrants it, the reviewer pushes back. + +## What operators own + +Some verification cannot be delegated to an agent without losing the point of the verification: + +- **Acceptance criteria.** What "shipped" means is an operator decision. If the agent invents the criteria, the criteria match what the agent built — not what was needed. +- **Manual exploratory testing.** "Click around and see if anything feels off" is not an agent task. It's a human pattern-matching against tacit knowledge of how the product should feel. Operators do this for any user-facing change. +- **Security-sensitive paths.** Code that gates authorization, handles secrets, signs transactions, validates user input that hits a privileged path — the operator reviews these by hand, regardless of what the agent's tests claim. See also [agent-era invariant §7 (HARD FAIL bypass)](../invariants/agent-era-invariants.md#7-no-bypass-of-reviewer-skill-hard-fail-findings). +- **The decision that tests are sufficient.** An agent can produce 50 tests; whether those 50 tests cover the change is an operator's judgment. Coverage as a number is not the same as coverage as a property. +- **The integration tests that touch real systems.** Anything that exercises a real network, a real database, a real signer — gated by the operator. Agents draft them; operators decide when to run them. + +## The Forest / Ghostty pattern + +Forest's `AI_POLICY.md` (in [`ChainSafe/forest`](https://github.com/ChainSafe/forest), originally adapted from the [Ghostty](https://github.com/ghostty-org/ghostty) project; attribution preserved in `forest/AI_POLICY.md` and in this repo's [`../NOTICE`](../NOTICE)) sets out a sharp version of the operator-first posture for AI-assisted work in a Filecoin client. The key takeaways carried into this handbook: + +- **AI may draft; humans must verify.** Agents may produce tests, but a passing test suite is not a substitute for review. The human reviewer reads what the test actually checks, not just that it passes. +- **AI may not be the sole reviewer of security-critical code.** A reviewer skill HARD FAIL on a security path stops the PR; a human must engage. This is the [HARD FAIL gate](../operating-model/gates-and-escalation.md#8-reviewer-skill-hard-fail) generalized. +- **AI-authored tests need the same scrutiny as AI-authored code.** A test that asserts "the function was called" rather than "the function did the right thing" is theatre. Operators read test bodies; reviewer skills flag asserting-mock patterns where they can. +- **Documentation, attribution, and provenance are part of quality.** A PR without an AI-generated declaration is a PR with a gap in its audit trail. Quality includes knowing who (or what) wrote what. + +Forest extends these into Filecoin-specific norms. The same shape applies across products at ChainSafe — Lodestar, Gossamer, Sygma, Canton — with each product's reviewer skill filling in the language-specific specifics. + +## The test plan, as a section of `plan.md` + +In the agentic-first model, there is no standalone "test plan document" filled out once per project. The test plan is a **section of the agent's [`plan.md`](../skills/chainsafe-research-plan-implement/SKILL.md)**, prepared as part of the research-plan-implement workflow before any code lands. The operator reviews it as part of approving the plan. Trying to write a test plan after the implementation is already done is the same anti-pattern as writing acceptance criteria after the build — the plan becomes a description of what was built rather than a check on whether it was right. + +The agent answers the following questions explicitly in the plan's test section. The operator's review verifies each is answered substantively, not just listed: + +- **What is in scope to test?** A concrete list of the behaviors, units, paths, and edge cases this change introduces or touches. Generic "unit tests for the new function" doesn't count. +- **What level of the test pyramid?** Unit / property-based / integration / end-to-end / fuzz / mainnet-fork. Most changes touch multiple levels; the plan states which and why. +- **What is automated vs manual?** Default: automate everything that can be automated. Anything left to manual testing needs a reason (security-sensitive UX flow, multi-device behavior, hardware-wallet path, etc.) and a manual test case prepared per the next section. +- **What test data is required?** Fixtures, seed data, mainnet snapshots, signer keys, etc. For sensitive data: how it's handled and torn down. For multi-environment work: which data lives where. +- **What test environment runs this?** CI pipeline, local dev, mainnet fork, staging — explicit per test type. If any test requires a non-default environment, the plan names it and links the setup runbook. +- **What are the known risks the tests aren't catching?** This is the most-skipped section and the most useful. Tests cover what the author can imagine; the gap between "what's tested" and "what could go wrong" is where production breaks. Naming the gap explicitly is honest; pretending the test suite is exhaustive is theatre. + +When the change is trivial (a typo fix, a one-line lint adjustment), the test plan section can be one line: "no new tests; existing suite covers." That's a valid answer. The point isn't a long plan — it's a deliberate one. + +The reviewer skills check that PRs touching non-trivial code paths include this section. PRs without it draw a SOFT WARNING by default and a HARD FAIL for security-critical languages. + +## Manual test cases (when automation isn't sufficient) + +**Most tests are automated.** Automation is the default — it runs on every PR, costs nothing per execution after authoring, and gives the operator the verification surface they need to review agent-authored code at speed. A manual test case is the exception, not the norm. + +A manual test case exists when the test plan (above) identifies a check that can't reasonably be automated. Common reasons: + +- A **hardware path** — hardware wallet signing, USB device behavior, multi-device handoff. +- A **privileged action** that can't safely run in CI — mainnet signing, irreversible writes to shared infrastructure, deploys to systems whose state matters. +- A **user-facing flow** where the assertion is "does this feel right" or "does the UI degrade gracefully" — perception-level judgments a script can't make. +- A **multi-system orchestration** whose setup cost outweighs the value of automating — typically one-off integration validations. + +If the manual case doesn't fit one of those, it's probably an automation gap, not a manual test. Ask "can this be automated within the next sprint?" before writing it as manual. + +### The hard rule + +**A manual test case always has step-by-step instructions.** No exceptions. A manual test without explicit steps is a test that won't run — the person running it three months from now (and that person might be future-you, or an on-call engineer at 3am) will not remember what you intended. + +The agent never produces a manual test case that lacks steps and assertions. The operator reviewing one without them rejects it and asks for the steps. + +### Required structure + +Every manual test case has: + +| Field | Required? | What it is | +|---|---|---| +| **Title** | Yes | One sentence stating the test's purpose, ending in a verifiable claim. *"User can successfully mint a test ERC-20 on Sepolia from the staging faucet UI"* — not *"Test the faucet"*. | +| **Component** | Yes | Which part of the system: UI, smart contract, validator, CLI, SDK, etc. | +| **Feature** | Yes | The named feature this case verifies. | +| **Environment** | Yes | Where this runs: staging, local, mainnet-fork, devnet, etc. | +| **Why manual?** | Yes | A one-line reason this isn't automated. Forces the question to be answered explicitly; defends against drift. | +| **Steps** | Yes — load-bearing | Numbered, single-action steps. Each one a click, a command, a wait. No collapsing multiple actions into one bullet. | +| **Assertions** | Yes — load-bearing | Numbered, specific success conditions. "Looks right" is not an assertion — name the property: a balance change, a UI element appearing, a log line written, an event emitted. | +| **Test Data** | When applicable | Specific addresses, fixtures, account states, network parameters. | +| **Prerequisites** | When applicable | Setup that must be complete before steps begin: contracts deployed, signer funded, environment provisioned. | +| **Priority** | Optional | If multiple test suites exist, mark which is critical-path vs. nice-to-have. | +| **Notes** | Optional | Tear-down, known flakiness, related tickets — anything not load-bearing for execution. | + +### Step granularity + +A step is **one action**. Not "go through the wallet flow" — that's a scenario, not a step. The granularity is: + +- *Click the "Connect Wallet" button.* +- *Select MetaMask from the wallet list.* +- *Approve the connection in the MetaMask popup.* +- *Wait for the page to display the connected address.* + +If a step contains "and then" or "also," split it. + +### Assertion specificity + +An assertion names **what changed** and **how to verify it**. Each assertion is independently checkable. + +- ✗ *"The mint works."* — vague, not verifiable. +- ✓ *"Confirm a transaction-complete confirmation appears on the page within 30s."* — specific event, bounded time. +- ✓ *"Confirm the destination account's balance increased by exactly the minted amount (verify via block explorer)."* — specific quantity, named verification source. + +If the test passes, every assertion fires. If any one fails, the test fails. There is no "pass with caveats" — caveats get written up as a new issue. + +### When manual becomes automated + +A manual test case is a candidate for automation as soon as the conditions that made it manual change. Examples: + +- Hardware-wallet flow: when a CI-friendly hardware-wallet emulator is wired in. +- Mainnet-only signing: when a mainnet-fork environment with test signers becomes available. +- UI feel: when a screenshot-diff or visual-regression suite is set up. + +The agent (or the operator) periodically reviews the manual-test-case set against these conditions. The reviewer skill flags manual cases that could now plausibly be automated. + +### Worked example + +```markdown +**Title:** Staging faucet UI can mint a test ERC-20 on Sepolia, end-to-end via MetaMask +**Component:** UI (web), Sepolia ERC-20 faucet contract +**Feature:** Faucet — token mint +**Environment:** Staging (faucet.staging.chainsafe.tech), Sepolia testnet +**Why manual?** Wallet popup interaction can't be CI-automated reliably with our current tooling +**Priority:** Critical (every release) + +**Prerequisites:** +- Test ERC-20 contract deployed to Sepolia at the staging-faucet address +- MetaMask installed in the test browser profile, with a test account funded with at least 0.01 Sepolia ETH for gas + +**Test Data:** +- Test destination account: 0xdc23f52868... (do not reuse for other tests) + +**Steps:** +1. Navigate to https://faucet.staging.chainsafe.tech in the test browser. +2. Click "Connect Wallet". +3. Select MetaMask from the wallet list. +4. Approve the connection in the MetaMask popup. +5. Wait for the page to display the connected address. +6. From the network dropdown, select "Sepolia". +7. From the token dropdown, select "ERC20Tst". +8. Paste the test destination account address into the "Destination" field. +9. Click "Mint". +10. Approve the transaction in the MetaMask popup. +11. Wait for the page's status indicator to change from "Pending" to "Complete" (typical: ≤30s). + +**Assertions:** +1. Confirm the page shows a transaction-complete confirmation, including the tx hash. +2. Confirm, via Sepolia block explorer, the tx hash is mined and shows a Transfer event for the configured amount. +3. Confirm the destination account's ERC20Tst balance increased by exactly the configured amount. +4. Confirm the connected account's Sepolia ETH balance decreased by approximately the displayed gas fee. + +**Notes:** Tear-down: the test ERC-20 contract has a public `burn` method — reset the destination account's balance after the test run to keep results comparable across runs. +``` + +The example is what good looks like: every step is one action, every assertion names a specific verifiable property, the "Why manual?" line defends against future drift toward automation forgetfulness. + +## Test types and when to use which + +- **Unit tests.** Default. Every non-trivial function, every changed function. Fast, isolated, deterministic. +- **Property-based tests.** When you can state an invariant: "for all valid inputs, this property holds." Strong for parsers, serializers, math, cryptography. +- **Integration tests.** When the unit boundary doesn't catch the bug class. Wire two real components together; mock the rest. +- **End-to-end tests.** For user-facing flows, when a regression there would be visible to users. Run on a schedule, not on every PR (too slow). +- **Fuzz tests.** For attack surfaces. Run continuously in CI for security-critical code. +- **Snapshot tests.** Useful for UI and structured output; brittle if overused. Use when the *shape* is the property you care about; not for everything. +- **Manual exploratory.** Operator-owned (see above). +- **Test plans / manual test cases.** Documented, repeatable, for hard-to-automate scenarios (multi-device, hardware-wallet flows, etc.). + +## What "covered" means + +Not 100% line coverage. Not a metric. Instead: + +- **Every change is covered to the depth its risk warrants.** A renaming pass needs no new tests. A new authorization check needs unit + integration + a security review. +- **The PR description states what was tested, what wasn't, and why.** If the answer is "I trusted the type system to catch this class of bug," say so explicitly — the reviewer can then agree or push back. +- **Reviewer skills check for thin tests** — assert-counts vs. behavior assertions, mock-heavy tests, etc. See [`code-review.md` mode (b)](./code-review.md#mode-b--agent-reviewing-a-pr). + +## Anti-patterns + +- **Tests written after the code, to match the code.** Tests need to assert what the code *should* do; if they were written to match what the code *does*, they aren't tests, they're documentation. The plan-first workflow ([`../skills/chainsafe-research-plan-implement/SKILL.md`](../skills/chainsafe-research-plan-implement/SKILL.md)) catches this when followed. +- **Mock-heavy unit tests** that assert which functions were called rather than what changed. Cheap to write, expensive to maintain, low confidence. +- **"It works on my machine" CI bypass.** The CI baseline ([`repo-and-ci-setup.md` §6](./repo-and-ci-setup.md#6-ci)) is the floor. Bypassing it for "small fix" PRs is how the floor gets quiet holes. +- **Operator approves blindly because the tests pass.** This is the failure mode this entire page exists to prevent. Tests are necessary, not sufficient. + +## Related + +- [`../invariants/engineering-invariants.md`](../invariants/engineering-invariants.md#3-quality-is-defined-before-the-build-not-after) — quality definition before the build. +- [`../invariants/agent-era-invariants.md`](../invariants/agent-era-invariants.md) — particularly §7 (HARD FAIL) and §8 (audit trail). +- [`pr-authoring.md`](./pr-authoring.md) — what the test plan looks like in a PR description. +- [`code-review.md`](./code-review.md) — how the reviewer evaluates test quality. +- [`repo-and-ci-setup.md`](./repo-and-ci-setup.md) — CI baseline that runs the tests. +- Upstream: [Forest `AI_POLICY.md`](https://github.com/ChainSafe/forest/blob/main/AI_POLICY.md) — the Filecoin-specific extension of this page's posture. +- [`../references/sources.md`](../references/sources.md) — catalog of the canonical sources this page draws on (Forest, Ghostty lineage). diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 8a5b91d..0000000 --- a/yarn.lock +++ /dev/null @@ -1,11390 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@algolia/autocomplete-core@1.17.0": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.0.tgz#b9e62d9677dc0ee818bb59d917ff58908356a9a0" - integrity sha512-6E4sVb5+fGtSQs9mULlxUH84OWFUVZPMapa5dMCtUc7KyDRLY6+X/dA8xbDA8CX5phdBn1plLUET1B6NZnrZuw== - dependencies: - "@algolia/autocomplete-plugin-algolia-insights" "1.17.0" - "@algolia/autocomplete-shared" "1.17.0" - -"@algolia/autocomplete-core@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7" - integrity sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw== - dependencies: - "@algolia/autocomplete-plugin-algolia-insights" "1.9.3" - "@algolia/autocomplete-shared" "1.9.3" - -"@algolia/autocomplete-js@^1.8.2": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-js/-/autocomplete-js-1.17.0.tgz#91f0ef2232646316a26c79dadbeb2e7791de623c" - integrity sha512-RbD98hXtZOl6VohSAo7kMOFWQHR1x4wWaJFadJradFQ1TAA9hFEyirSIM+yT96UpKkdi08V2EBI+YwZ3/VETvw== - dependencies: - "@algolia/autocomplete-core" "1.17.0" - "@algolia/autocomplete-preset-algolia" "1.17.0" - "@algolia/autocomplete-shared" "1.17.0" - htm "^3.1.1" - preact "^10.13.2" - -"@algolia/autocomplete-plugin-algolia-insights@1.17.0": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.0.tgz#dcec9b03a47375860a9f927816a1275d885ebdff" - integrity sha512-zbWImu+VxBDzUQONEhQXq3OzlipHLEtWbL4Nf/VOb1p1qHG/f96jCegOzzEZVPiQvZpRJnmhCUmsYNHlIBxKWw== - dependencies: - "@algolia/autocomplete-shared" "1.17.0" - -"@algolia/autocomplete-plugin-algolia-insights@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz#9b7f8641052c8ead6d66c1623d444cbe19dde587" - integrity sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg== - dependencies: - "@algolia/autocomplete-shared" "1.9.3" - -"@algolia/autocomplete-preset-algolia@1.17.0": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.0.tgz#9d7d9673a922d75dfbedd3119e7ffa76f4c118c6" - integrity sha512-DhTkMs/9BzThhTU2nSTpQxVxHLzaRDZLid4Tf56D8s9IhEGfmzbNuLRmJNzgAOPv1smHtUErndmC+S9QNMDEJA== - dependencies: - "@algolia/autocomplete-shared" "1.17.0" - -"@algolia/autocomplete-preset-algolia@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz#64cca4a4304cfcad2cf730e83067e0c1b2f485da" - integrity sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== - dependencies: - "@algolia/autocomplete-shared" "1.9.3" - -"@algolia/autocomplete-shared@1.17.0": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.0.tgz#7d0a8e504fe555c48df7ae6854d3d6633b0b32f5" - integrity sha512-7su4KH/2q2Fhud2VujUNhCMbIh7yp6wqWR3UuVje5P3kDRhTotPRmg3iRQi48YRYkk9o+airsrLl+rxJ/9FWng== - -"@algolia/autocomplete-shared@1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa" - integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== - -"@algolia/autocomplete-theme-classic@^1.8.2": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.17.0.tgz#bbd79df8f5240b3ddd3f9cdc9b8273753f15cd25" - integrity sha512-FsW/J/mG1YIPv93/QQ7KxMVNXAiVi9accGgoK2y3zDz58WpVgUug97SUoQzP4I9EMZAZAHQo0QbWXxpqTWkcOA== - -"@algolia/cache-browser-local-storage@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz#14b6dc9abc9e3a304a5fffb063d15f30af1032d1" - integrity sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g== - dependencies: - "@algolia/cache-common" "4.22.1" - -"@algolia/cache-browser-local-storage@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.2.tgz#060d15e89588fcac18e73643201fce0f4f7d5ca0" - integrity sha512-PvRQdCmtiU22dw9ZcTJkrVKgNBVAxKgD0/cfiqyxhA5+PHzA2WDt6jOmZ9QASkeM2BpyzClJb/Wr1yt2/t78Kw== - dependencies: - "@algolia/cache-common" "4.23.2" - -"@algolia/cache-common@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.22.1.tgz#c625dff4bc2a74e79f9aed67b4e053b0ef1b3ec1" - integrity sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA== - -"@algolia/cache-common@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.23.2.tgz#c68706ce34b18377e56e71ac13cce2dd5662dcee" - integrity sha512-OUK/6mqr6CQWxzl/QY0/mwhlGvS6fMtvEPyn/7AHUx96NjqDA4X4+Ju7aXFQKh+m3jW9VPB0B9xvEQgyAnRPNw== - -"@algolia/cache-in-memory@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz#858a3d887f521362e87d04f3943e2810226a0d71" - integrity sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw== - dependencies: - "@algolia/cache-common" "4.22.1" - -"@algolia/cache-in-memory@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.23.2.tgz#94cd828275d7a12186959bf1b95a13247e103b23" - integrity sha512-rfbi/SnhEa3MmlqQvgYz/9NNJ156NkU6xFxjbxBtLWnHbpj+qnlMoKd+amoiacHRITpajg6zYbLM9dnaD3Bczw== - dependencies: - "@algolia/cache-common" "4.23.2" - -"@algolia/client-account@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.22.1.tgz#a7fb8b66b9a4f0a428e1426b2561144267d76d43" - integrity sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw== - dependencies: - "@algolia/client-common" "4.22.1" - "@algolia/client-search" "4.22.1" - "@algolia/transporter" "4.22.1" - -"@algolia/client-account@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.23.2.tgz#b53cb14e730fd8e0a0a227cf650b287b570a08bc" - integrity sha512-VbrOCLIN/5I7iIdskSoSw3uOUPF516k4SjDD4Qz3BFwa3of7D9A0lzBMAvQEJJEPHWdVraBJlGgdJq/ttmquJQ== - dependencies: - "@algolia/client-common" "4.23.2" - "@algolia/client-search" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/client-analytics@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.22.1.tgz#506558740b4d49b1b1e3393861f729a8ce921851" - integrity sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg== - dependencies: - "@algolia/client-common" "4.22.1" - "@algolia/client-search" "4.22.1" - "@algolia/requester-common" "4.22.1" - "@algolia/transporter" "4.22.1" - -"@algolia/client-analytics@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.23.2.tgz#7fdcf1cb27f0ae93e5da6beb4e612fc06a880b0c" - integrity sha512-lLj7irsAztGhMoEx/SwKd1cwLY6Daf1Q5f2AOsZacpppSvuFvuBrmkzT7pap1OD/OePjLKxicJS8wNA0+zKtuw== - dependencies: - "@algolia/client-common" "4.23.2" - "@algolia/client-search" "4.23.2" - "@algolia/requester-common" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/client-common@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.22.1.tgz#042b19c1b6157c485fa1b551349ab313944d2b05" - integrity sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ== - dependencies: - "@algolia/requester-common" "4.22.1" - "@algolia/transporter" "4.22.1" - -"@algolia/client-common@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.23.2.tgz#e5f86fc2de707eb6bf9f1109b70187dae179c72c" - integrity sha512-Q2K1FRJBern8kIfZ0EqPvUr3V29ICxCm/q42zInV+VJRjldAD9oTsMGwqUQ26GFMdFYmqkEfCbY4VGAiQhh22g== - dependencies: - "@algolia/requester-common" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/client-personalization@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.22.1.tgz#ff088d797648224fb582e9fe5828f8087835fa3d" - integrity sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ== - dependencies: - "@algolia/client-common" "4.22.1" - "@algolia/requester-common" "4.22.1" - "@algolia/transporter" "4.22.1" - -"@algolia/client-personalization@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.23.2.tgz#0472d9c207402eefcc9c98f7ffba5d26fe8e2fd0" - integrity sha512-vwPsgnCGhUcHhhQG5IM27z8q7dWrN9itjdvgA6uKf2e9r7vB+WXt4OocK0CeoYQt3OGEAExryzsB8DWqdMK5wg== - dependencies: - "@algolia/client-common" "4.23.2" - "@algolia/requester-common" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/client-search@4.22.1", "@algolia/client-search@^4.12.0": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.22.1.tgz#508cc6ab3d1f4e9c02735a630d4dff6fbb8514a2" - integrity sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA== - dependencies: - "@algolia/client-common" "4.22.1" - "@algolia/requester-common" "4.22.1" - "@algolia/transporter" "4.22.1" - -"@algolia/client-search@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.23.2.tgz#9b2741f0a209596459f06a44583118207ea287f7" - integrity sha512-CxSB29OVGSE7l/iyoHvamMonzq7Ev8lnk/OkzleODZ1iBcCs3JC/XgTIKzN/4RSTrJ9QybsnlrN/bYCGufo7qw== - dependencies: - "@algolia/client-common" "4.23.2" - "@algolia/requester-common" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/events@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" - integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== - -"@algolia/logger-common@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.22.1.tgz#79cf4cd295de0377a94582c6aaac59b1ded731d9" - integrity sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg== - -"@algolia/logger-common@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.23.2.tgz#5441a828f0fad1ceaae3a27caec7b663d40dd27f" - integrity sha512-jGM49Q7626cXZ7qRAWXn0jDlzvoA1FvN4rKTi1g0hxKsTTSReyYk0i1ADWjChDPl3Q+nSDhJuosM2bBUAay7xw== - -"@algolia/logger-console@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.22.1.tgz#0355345f6940f67aaa78ae9b81c06e44e49f2336" - integrity sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA== - dependencies: - "@algolia/logger-common" "4.22.1" - -"@algolia/logger-console@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.23.2.tgz#fda4252bb02df7c52a92c63f1e357bf7370cc8db" - integrity sha512-oo+lnxxEmlhTBTFZ3fGz1O8PJ+G+8FiAoMY2Qo3Q4w23xocQev6KqDTA1JQAGPDxAewNA2VBwWOsVXeXFjrI/Q== - dependencies: - "@algolia/logger-common" "4.23.2" - -"@algolia/recommend@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-4.23.2.tgz#02bf57f836ced2c850633239d493a0414be76a7f" - integrity sha512-Q75CjnzRCDzgIlgWfPnkLtrfF4t82JCirhalXkSSwe/c1GH5pWh4xUyDOR3KTMo+YxxX3zTlrL/FjHmUJEWEcg== - dependencies: - "@algolia/cache-browser-local-storage" "4.23.2" - "@algolia/cache-common" "4.23.2" - "@algolia/cache-in-memory" "4.23.2" - "@algolia/client-common" "4.23.2" - "@algolia/client-search" "4.23.2" - "@algolia/logger-common" "4.23.2" - "@algolia/logger-console" "4.23.2" - "@algolia/requester-browser-xhr" "4.23.2" - "@algolia/requester-common" "4.23.2" - "@algolia/requester-node-http" "4.23.2" - "@algolia/transporter" "4.23.2" - -"@algolia/requester-browser-xhr@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz#f04df6fe9690a071b267c77d26b83a3be9280361" - integrity sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw== - dependencies: - "@algolia/requester-common" "4.22.1" - -"@algolia/requester-browser-xhr@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.2.tgz#2d0a6b642e2a2bbfb2e2ff3d1e82158e3e143def" - integrity sha512-TO9wLlp8+rvW9LnIfyHsu8mNAMYrqNdQ0oLF6eTWFxXfxG3k8F/Bh7nFYGk2rFAYty4Fw4XUtrv/YjeNDtM5og== - dependencies: - "@algolia/requester-common" "4.23.2" - -"@algolia/requester-common@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.22.1.tgz#27be35f3718aafcb6b388ff9c3aa2defabd559ff" - integrity sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg== - -"@algolia/requester-common@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.23.2.tgz#9c2e5da4dc15e65f9b9bbe5bedb419cf23092ef1" - integrity sha512-3EfpBS0Hri0lGDB5H/BocLt7Vkop0bTTLVUBB844HH6tVycwShmsV6bDR7yXbQvFP1uNpgePRD3cdBCjeHmk6Q== - -"@algolia/requester-node-http@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz#589a6fa828ad0f325e727a6fcaf4e1a2343cc62b" - integrity sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA== - dependencies: - "@algolia/requester-common" "4.22.1" - -"@algolia/requester-node-http@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.23.2.tgz#718ae71f58949eab3b5fcfc440be42af41bd640f" - integrity sha512-SVzgkZM/malo+2SB0NWDXpnT7nO5IZwuDTaaH6SjLeOHcya1o56LSWXk+3F3rNLz2GVH+I/rpYKiqmHhSOjerw== - dependencies: - "@algolia/requester-common" "4.23.2" - -"@algolia/transporter@4.22.1": - version "4.22.1" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.22.1.tgz#8843841b857dc021668f31647aa557ff19cd9cb1" - integrity sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ== - dependencies: - "@algolia/cache-common" "4.22.1" - "@algolia/logger-common" "4.22.1" - "@algolia/requester-common" "4.22.1" - -"@algolia/transporter@4.23.2": - version "4.23.2" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.23.2.tgz#61e7b9288d4f561b2015ddde689ba31e08c21644" - integrity sha512-GY3aGKBy+8AK4vZh8sfkatDciDVKad5rTY2S10Aefyjh7e7UGBP4zigf42qVXwU8VOPwi7l/L7OACGMOFcjB0Q== - dependencies: - "@algolia/cache-common" "4.23.2" - "@algolia/logger-common" "4.23.2" - "@algolia/requester-common" "4.23.2" - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.8.3": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== - dependencies: - "@babel/highlight" "^7.24.2" - picocolors "^1.0.0" - -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== - -"@babel/compat-data@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" - integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== - -"@babel/core@^7.19.6": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" - integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.7" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/core@^7.23.3": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717" - integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.4" - "@babel/parser" "^7.24.4" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.23.3", "@babel/generator@^7.24.1", "@babel/generator@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.4.tgz#1fc55532b88adf952025d5d2d1e71f946cb1c498" - integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== - dependencies: - "@babel/types" "^7.24.0" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/generator@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" - integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz#b2e6826e0e20d337143655198b79d58fdc9bd43d" - integrity sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz#c806f73788a6800a5cfbbc04d2df7ee4d927cce3" - integrity sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - semver "^6.3.1" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" - integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - regexpu-core "^5.3.1" - semver "^6.3.1" - -"@babel/helper-define-polyfill-provider@^0.4.4": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz#64df615451cb30e94b59a9696022cffac9a10088" - integrity sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-define-polyfill-provider@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b" - integrity sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-define-polyfill-provider@^0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" - integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== - dependencies: - "@babel/types" "^7.23.0" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" - integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== - dependencies: - "@babel/types" "^7.24.0" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-plugin-utils@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" - integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== - -"@babel/helper-remap-async-to-generator@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" - integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-wrap-function" "^7.22.20" - -"@babel/helper-replace-supers@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" - integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.22.15" - "@babel/helper-optimise-call-expression" "^7.22.5" - -"@babel/helper-replace-supers@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" - integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.23.0" - "@babel/helper-optimise-call-expression" "^7.22.5" - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helper-wrap-function@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" - integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== - dependencies: - "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.15" - "@babel/types" "^7.22.19" - -"@babel/helpers@^7.23.7": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.8.tgz#fc6b2d65b16847fd50adddbd4232c76378959e34" - integrity sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - -"@babel/helpers@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.4.tgz#dc00907fd0d95da74563c142ef4cd21f2cb856b6" - integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== - dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/highlight@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== - -"@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" - integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1" - integrity sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" - integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz#b645d9ba8c2bc5b7af50f0fe949f9edbeb07c8cf" - integrity sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" - integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.23.3" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz#da8261f2697f0f41b0855b91d3a20a1fbfd271d3" - integrity sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.24.1" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" - integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz#1181d9685984c91d657b8ddf14f0487a6bab2988" - integrity sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - version "7.21.0-placeholder-for-preset-env.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" - integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-import-assertions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" - integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-import-assertions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971" - integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-import-attributes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" - integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-import-attributes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz#c66b966c63b714c4eec508fcf5763b1f2d381093" - integrity sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-jsx@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" - integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-typescript@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" - integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" - integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-arrow-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" - integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-arrow-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" - integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-async-generator-functions@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz#3aa0b4f2fa3788b5226ef9346cf6d16ec61f99cd" - integrity sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-remap-async-to-generator" "^7.22.20" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-transform-async-generator-functions@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz#8fa7ae481b100768cc9842c8617808c5352b8b89" - integrity sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-transform-async-to-generator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" - integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== - dependencies: - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-remap-async-to-generator" "^7.22.20" - -"@babel/plugin-transform-async-to-generator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" - integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== - dependencies: - "@babel/helper-module-imports" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" - -"@babel/plugin-transform-block-scoped-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" - integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-block-scoped-functions@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz#1c94799e20fcd5c4d4589523bbc57b7692979380" - integrity sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-block-scoping@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" - integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-block-scoping@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz#28f5c010b66fbb8ccdeef853bef1935c434d7012" - integrity sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-class-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" - integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-class-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz#bcbf1aef6ba6085cfddec9fc8d58871cf011fc29" - integrity sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-class-static-block@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" - integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-transform-class-static-block@^7.24.4": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz#1a4653c0cf8ac46441ec406dece6e9bc590356a4" - integrity sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.4" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-transform-classes@^7.23.8": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" - integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - "@babel/helper-split-export-declaration" "^7.22.6" - globals "^11.1.0" - -"@babel/plugin-transform-classes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz#5bc8fc160ed96378184bc10042af47f50884dcb1" - integrity sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" - "@babel/helper-split-export-declaration" "^7.22.6" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" - integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/template" "^7.22.15" - -"@babel/plugin-transform-computed-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz#bc7e787f8e021eccfb677af5f13c29a9934ed8a7" - integrity sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/template" "^7.24.0" - -"@babel/plugin-transform-destructuring@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" - integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-destructuring@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz#b1e8243af4a0206841973786292b8c8dd8447345" - integrity sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-dotall-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" - integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-dotall-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz#d56913d2f12795cc9930801b84c6f8c47513ac13" - integrity sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-duplicate-keys@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" - integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-duplicate-keys@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz#5347a797fe82b8d09749d10e9f5b83665adbca88" - integrity sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-dynamic-import@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" - integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-transform-dynamic-import@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz#2a5a49959201970dd09a5fca856cb651e44439dd" - integrity sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" - integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-exponentiation-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz#6650ebeb5bd5c012d5f5f90a26613a08162e8ba4" - integrity sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-export-namespace-from@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" - integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-transform-export-namespace-from@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz#f033541fc036e3efb2dcb58eedafd4f6b8078acd" - integrity sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" - integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - -"@babel/plugin-transform-for-of@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd" - integrity sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - -"@babel/plugin-transform-function-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" - integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== - dependencies: - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-function-name@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz#8cba6f7730626cc4dfe4ca2fa516215a0592b361" - integrity sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA== - dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-json-strings@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" - integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-transform-json-strings@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz#08e6369b62ab3e8a7b61089151b161180c8299f7" - integrity sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-transform-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" - integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz#0a1982297af83e6b3c94972686067df588c5c096" - integrity sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-logical-assignment-operators@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" - integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-transform-logical-assignment-operators@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz#719d8aded1aa94b8fb34e3a785ae8518e24cfa40" - integrity sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-transform-member-expression-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" - integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-member-expression-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz#896d23601c92f437af8b01371ad34beb75df4489" - integrity sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-modules-amd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" - integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-modules-amd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz#b6d829ed15258536977e9c7cc6437814871ffa39" - integrity sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-modules-commonjs@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" - integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-simple-access" "^7.22.5" - -"@babel/plugin-transform-modules-commonjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" - integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-simple-access" "^7.22.5" - -"@babel/plugin-transform-modules-systemjs@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz#fa7e62248931cb15b9404f8052581c302dd9de81" - integrity sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ== - dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/plugin-transform-modules-systemjs@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz#2b9625a3d4e445babac9788daec39094e6b11e3e" - integrity sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA== - dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/plugin-transform-modules-umd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" - integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-modules-umd@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz#69220c66653a19cf2c0872b9c762b9a48b8bebef" - integrity sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" - integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-new-target@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" - integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-new-target@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz#29c59988fa3d0157de1c871a28cd83096363cc34" - integrity sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-nullish-coalescing-operator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" - integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988" - integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-transform-numeric-separator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" - integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-transform-numeric-separator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz#5bc019ce5b3435c1cadf37215e55e433d674d4e8" - integrity sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-transform-object-rest-spread@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz#2b9c2d26bf62710460bdc0d1730d4f1048361b83" - integrity sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g== - dependencies: - "@babel/compat-data" "^7.23.3" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.23.3" - -"@babel/plugin-transform-object-rest-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz#5a3ce73caf0e7871a02e1c31e8b473093af241ff" - integrity sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA== - dependencies: - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.1" - -"@babel/plugin-transform-object-super@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" - integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - -"@babel/plugin-transform-object-super@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz#e71d6ab13483cca89ed95a474f542bbfc20a0520" - integrity sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-replace-supers" "^7.24.1" - -"@babel/plugin-transform-optional-catch-binding@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" - integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-transform-optional-catch-binding@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz#92a3d0efe847ba722f1a4508669b23134669e2da" - integrity sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" - integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-transform-optional-chaining@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6" - integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" - integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-parameters@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz#983c15d114da190506c75b616ceb0f817afcc510" - integrity sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-private-methods@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" - integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-private-methods@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a" - integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-private-property-in-object@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" - integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-transform-private-property-in-object@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz#756443d400274f8fb7896742962cc1b9f25c1f6a" - integrity sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-transform-property-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" - integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-property-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz#d6a9aeab96f03749f4eebeb0b6ea8e90ec958825" - integrity sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-react-constant-elements@^7.18.12": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.23.3.tgz#5efc001d07ef0f7da0d73c3a86c132f73d28e43c" - integrity sha512-zP0QKq/p6O42OL94udMgSfKXyse4RyJ0JqbQ34zDAONWjyrEsghYEyTSK5FIpmXmCpB55SHokL1cRRKHv8L2Qw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-react-display-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200" - integrity sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-react-display-name@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz#554e3e1a25d181f040cf698b93fd289a03bfdcdb" - integrity sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-react-jsx-development@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" - integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.22.5" - -"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5", "@babel/plugin-transform-react-jsx@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" - integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/types" "^7.23.4" - -"@babel/plugin-transform-react-pure-annotations@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz#fabedbdb8ee40edf5da96f3ecfc6958e3783b93c" - integrity sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-react-pure-annotations@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz#c86bce22a53956331210d268e49a0ff06e392470" - integrity sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-regenerator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" - integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - regenerator-transform "^0.15.2" - -"@babel/plugin-transform-regenerator@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" - integrity sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - regenerator-transform "^0.15.2" - -"@babel/plugin-transform-reserved-words@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" - integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-reserved-words@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz#8de729f5ecbaaf5cf83b67de13bad38a21be57c1" - integrity sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-runtime@^7.22.9": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz#dc58ad4a31810a890550365cc922e1ff5acb5d7f" - integrity sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ== - dependencies: - "@babel/helper-module-imports" "^7.24.3" - "@babel/helper-plugin-utils" "^7.24.0" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.1" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - -"@babel/plugin-transform-shorthand-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" - integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-shorthand-properties@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" - integrity sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-spread@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" - integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - -"@babel/plugin-transform-spread@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz#a1acf9152cbf690e4da0ba10790b3ac7d2b2b391" - integrity sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - -"@babel/plugin-transform-sticky-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" - integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-sticky-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz#f03e672912c6e203ed8d6e0271d9c2113dc031b9" - integrity sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-template-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" - integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-template-literals@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz#15e2166873a30d8617e3e2ccadb86643d327aab7" - integrity sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-typeof-symbol@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" - integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-typeof-symbol@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz#6831f78647080dec044f7e9f68003d99424f94c7" - integrity sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-typescript@^7.23.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c" - integrity sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.23.6" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-typescript" "^7.23.3" - -"@babel/plugin-transform-typescript@^7.24.1": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz#03e0492537a4b953e491f53f2bc88245574ebd15" - integrity sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.4" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-typescript" "^7.24.1" - -"@babel/plugin-transform-unicode-escapes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" - integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-unicode-escapes@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz#fb3fa16676549ac7c7449db9b342614985c2a3a4" - integrity sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-unicode-property-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" - integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-unicode-property-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz#56704fd4d99da81e5e9f0c0c93cabd91dbc4889e" - integrity sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-unicode-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" - integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-unicode-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz#57c3c191d68f998ac46b708380c1ce4d13536385" - integrity sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-unicode-sets-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" - integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-unicode-sets-regex@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz#c1ea175b02afcffc9cf57a9c4658326625165b7f" - integrity sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/preset-env@^7.19.4": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.8.tgz#7d6f8171ea7c221ecd28059e65ad37c20e441e3e" - integrity sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.23.3" - "@babel/plugin-syntax-import-attributes" "^7.23.3" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.23.3" - "@babel/plugin-transform-async-generator-functions" "^7.23.7" - "@babel/plugin-transform-async-to-generator" "^7.23.3" - "@babel/plugin-transform-block-scoped-functions" "^7.23.3" - "@babel/plugin-transform-block-scoping" "^7.23.4" - "@babel/plugin-transform-class-properties" "^7.23.3" - "@babel/plugin-transform-class-static-block" "^7.23.4" - "@babel/plugin-transform-classes" "^7.23.8" - "@babel/plugin-transform-computed-properties" "^7.23.3" - "@babel/plugin-transform-destructuring" "^7.23.3" - "@babel/plugin-transform-dotall-regex" "^7.23.3" - "@babel/plugin-transform-duplicate-keys" "^7.23.3" - "@babel/plugin-transform-dynamic-import" "^7.23.4" - "@babel/plugin-transform-exponentiation-operator" "^7.23.3" - "@babel/plugin-transform-export-namespace-from" "^7.23.4" - "@babel/plugin-transform-for-of" "^7.23.6" - "@babel/plugin-transform-function-name" "^7.23.3" - "@babel/plugin-transform-json-strings" "^7.23.4" - "@babel/plugin-transform-literals" "^7.23.3" - "@babel/plugin-transform-logical-assignment-operators" "^7.23.4" - "@babel/plugin-transform-member-expression-literals" "^7.23.3" - "@babel/plugin-transform-modules-amd" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-modules-systemjs" "^7.23.3" - "@babel/plugin-transform-modules-umd" "^7.23.3" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.23.4" - "@babel/plugin-transform-numeric-separator" "^7.23.4" - "@babel/plugin-transform-object-rest-spread" "^7.23.4" - "@babel/plugin-transform-object-super" "^7.23.3" - "@babel/plugin-transform-optional-catch-binding" "^7.23.4" - "@babel/plugin-transform-optional-chaining" "^7.23.4" - "@babel/plugin-transform-parameters" "^7.23.3" - "@babel/plugin-transform-private-methods" "^7.23.3" - "@babel/plugin-transform-private-property-in-object" "^7.23.4" - "@babel/plugin-transform-property-literals" "^7.23.3" - "@babel/plugin-transform-regenerator" "^7.23.3" - "@babel/plugin-transform-reserved-words" "^7.23.3" - "@babel/plugin-transform-shorthand-properties" "^7.23.3" - "@babel/plugin-transform-spread" "^7.23.3" - "@babel/plugin-transform-sticky-regex" "^7.23.3" - "@babel/plugin-transform-template-literals" "^7.23.3" - "@babel/plugin-transform-typeof-symbol" "^7.23.3" - "@babel/plugin-transform-unicode-escapes" "^7.23.3" - "@babel/plugin-transform-unicode-property-regex" "^7.23.3" - "@babel/plugin-transform-unicode-regex" "^7.23.3" - "@babel/plugin-transform-unicode-sets-regex" "^7.23.3" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.7" - babel-plugin-polyfill-corejs3 "^0.8.7" - babel-plugin-polyfill-regenerator "^0.5.4" - core-js-compat "^3.31.0" - semver "^6.3.1" - -"@babel/preset-env@^7.22.9": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.4.tgz#46dbbcd608771373b88f956ffb67d471dce0d23b" - integrity sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A== - dependencies: - "@babel/compat-data" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.4" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.1" - "@babel/plugin-syntax-import-attributes" "^7.24.1" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.1" - "@babel/plugin-transform-async-generator-functions" "^7.24.3" - "@babel/plugin-transform-async-to-generator" "^7.24.1" - "@babel/plugin-transform-block-scoped-functions" "^7.24.1" - "@babel/plugin-transform-block-scoping" "^7.24.4" - "@babel/plugin-transform-class-properties" "^7.24.1" - "@babel/plugin-transform-class-static-block" "^7.24.4" - "@babel/plugin-transform-classes" "^7.24.1" - "@babel/plugin-transform-computed-properties" "^7.24.1" - "@babel/plugin-transform-destructuring" "^7.24.1" - "@babel/plugin-transform-dotall-regex" "^7.24.1" - "@babel/plugin-transform-duplicate-keys" "^7.24.1" - "@babel/plugin-transform-dynamic-import" "^7.24.1" - "@babel/plugin-transform-exponentiation-operator" "^7.24.1" - "@babel/plugin-transform-export-namespace-from" "^7.24.1" - "@babel/plugin-transform-for-of" "^7.24.1" - "@babel/plugin-transform-function-name" "^7.24.1" - "@babel/plugin-transform-json-strings" "^7.24.1" - "@babel/plugin-transform-literals" "^7.24.1" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" - "@babel/plugin-transform-member-expression-literals" "^7.24.1" - "@babel/plugin-transform-modules-amd" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-modules-systemjs" "^7.24.1" - "@babel/plugin-transform-modules-umd" "^7.24.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.24.1" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" - "@babel/plugin-transform-numeric-separator" "^7.24.1" - "@babel/plugin-transform-object-rest-spread" "^7.24.1" - "@babel/plugin-transform-object-super" "^7.24.1" - "@babel/plugin-transform-optional-catch-binding" "^7.24.1" - "@babel/plugin-transform-optional-chaining" "^7.24.1" - "@babel/plugin-transform-parameters" "^7.24.1" - "@babel/plugin-transform-private-methods" "^7.24.1" - "@babel/plugin-transform-private-property-in-object" "^7.24.1" - "@babel/plugin-transform-property-literals" "^7.24.1" - "@babel/plugin-transform-regenerator" "^7.24.1" - "@babel/plugin-transform-reserved-words" "^7.24.1" - "@babel/plugin-transform-shorthand-properties" "^7.24.1" - "@babel/plugin-transform-spread" "^7.24.1" - "@babel/plugin-transform-sticky-regex" "^7.24.1" - "@babel/plugin-transform-template-literals" "^7.24.1" - "@babel/plugin-transform-typeof-symbol" "^7.24.1" - "@babel/plugin-transform-unicode-escapes" "^7.24.1" - "@babel/plugin-transform-unicode-property-regex" "^7.24.1" - "@babel/plugin-transform-unicode-regex" "^7.24.1" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" - semver "^6.3.1" - -"@babel/preset-modules@0.1.6-no-external-plugins": - version "0.1.6-no-external-plugins" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" - integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-react@^7.18.6": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.23.3.tgz#f73ca07e7590f977db07eb54dbe46538cc015709" - integrity sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-transform-react-display-name" "^7.23.3" - "@babel/plugin-transform-react-jsx" "^7.22.15" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.23.3" - -"@babel/preset-react@^7.22.5": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" - integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-transform-react-display-name" "^7.24.1" - "@babel/plugin-transform-react-jsx" "^7.23.4" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.24.1" - -"@babel/preset-typescript@^7.18.6": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913" - integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-typescript" "^7.23.3" - -"@babel/preset-typescript@^7.22.5": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" - integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-syntax-jsx" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-typescript" "^7.24.1" - -"@babel/regjsgen@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" - integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== - -"@babel/runtime-corejs3@^7.22.6": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.4.tgz#b9ebe728087cfbb22bbaccc6f9a70d69834124a0" - integrity sha512-VOQOexSilscN24VEY810G/PqtpFvx/z6UqDIjIWbDe2368HhDLkYN5TYwaEz/+eRCUkhJ2WaNLLmQAlxzfWj4w== - dependencies: - core-js-pure "^3.30.2" - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650" - integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.22.6": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" - integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/template@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/traverse@^7.22.8", "@babel/traverse@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" - integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== - dependencies: - "@babel/code-frame" "^7.24.1" - "@babel/generator" "^7.24.1" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.1" - "@babel/types" "^7.24.0" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/traverse@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.20.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.23.6", "@babel/types@^7.4.4": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@babel/types@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" - integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@braintree/sanitize-url@^6.0.1": - version "6.0.4" - resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" - integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== - -"@cmfcmf/docusaurus-search-local@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-1.1.0.tgz#3db5d7d6e05985cc3b06cec10436385c53033c69" - integrity sha512-0IVb/aA0IK8ZlktuxmgXmluXfcSpo6Vdd2nG21y1aOH9nVYnPP231Dn0H8Ng9Qf9ronQQCDWHnuWpYOr9rUrEQ== - dependencies: - "@algolia/autocomplete-js" "^1.8.2" - "@algolia/autocomplete-theme-classic" "^1.8.2" - "@algolia/client-search" "^4.12.0" - algoliasearch "^4.12.0" - cheerio "^1.0.0-rc.9" - clsx "^1.1.1" - lunr-languages "^1.4.0" - mark.js "^8.11.1" - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - -"@discoveryjs/json-ext@0.5.7": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== - -"@docsearch/css@3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.0.tgz#0e9f56f704b3a34d044d15fd9962ebc1536ba4fb" - integrity sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ== - -"@docsearch/react@^3.5.2": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.0.tgz#b4f25228ecb7fc473741aefac592121e86dd2958" - integrity sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w== - dependencies: - "@algolia/autocomplete-core" "1.9.3" - "@algolia/autocomplete-preset-algolia" "1.9.3" - "@docsearch/css" "3.6.0" - algoliasearch "^4.19.1" - -"@docusaurus/core@3.2.1", "@docusaurus/core@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.2.1.tgz#e9216f9f642b2139541e21f9eebbdb11e12f66da" - integrity sha512-ZeMAqNvy0eBv2dThEeMuNzzuu+4thqMQakhxsgT5s02A8LqRcdkg+rbcnuNqUIpekQ4GRx3+M5nj0ODJhBXo9w== - dependencies: - "@babel/core" "^7.23.3" - "@babel/generator" "^7.23.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.22.9" - "@babel/preset-env" "^7.22.9" - "@babel/preset-react" "^7.22.5" - "@babel/preset-typescript" "^7.22.5" - "@babel/runtime" "^7.22.6" - "@babel/runtime-corejs3" "^7.22.6" - "@babel/traverse" "^7.22.8" - "@docusaurus/cssnano-preset" "3.2.1" - "@docusaurus/logger" "3.2.1" - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - "@svgr/webpack" "^6.5.1" - autoprefixer "^10.4.14" - babel-loader "^9.1.3" - babel-plugin-dynamic-import-node "^2.3.3" - boxen "^6.2.1" - chalk "^4.1.2" - chokidar "^3.5.3" - clean-css "^5.3.2" - cli-table3 "^0.6.3" - combine-promises "^1.1.0" - commander "^5.1.0" - copy-webpack-plugin "^11.0.0" - core-js "^3.31.1" - css-loader "^6.8.1" - css-minimizer-webpack-plugin "^4.2.2" - cssnano "^5.1.15" - del "^6.1.1" - detect-port "^1.5.1" - escape-html "^1.0.3" - eta "^2.2.0" - eval "^0.1.8" - file-loader "^6.2.0" - fs-extra "^11.1.1" - html-minifier-terser "^7.2.0" - html-tags "^3.3.1" - html-webpack-plugin "^5.5.3" - leven "^3.1.0" - lodash "^4.17.21" - mini-css-extract-plugin "^2.7.6" - p-map "^4.0.0" - postcss "^8.4.26" - postcss-loader "^7.3.3" - prompts "^2.4.2" - react-dev-utils "^12.0.1" - react-helmet-async "^1.3.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.3.4" - react-router-config "^5.1.1" - react-router-dom "^5.3.4" - rtl-detect "^1.0.4" - semver "^7.5.4" - serve-handler "^6.1.5" - shelljs "^0.8.5" - terser-webpack-plugin "^5.3.9" - tslib "^2.6.0" - update-notifier "^6.0.2" - url-loader "^4.1.1" - webpack "^5.88.1" - webpack-bundle-analyzer "^4.9.0" - webpack-dev-server "^4.15.1" - webpack-merge "^5.9.0" - webpackbar "^5.0.2" - -"@docusaurus/cssnano-preset@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.2.1.tgz#b36041004e837574d0147fcc4932210cdb1efbc1" - integrity sha512-wTL9KuSSbMJjKrfu385HZEzAoamUsbKqwscAQByZw4k6Ja/RWpqgVvt/CbAC+aYEH6inLzOt+MjuRwMOrD3VBA== - dependencies: - cssnano-preset-advanced "^5.3.10" - postcss "^8.4.26" - postcss-sort-media-queries "^4.4.1" - tslib "^2.6.0" - -"@docusaurus/logger@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.2.1.tgz#6032e421b0b40a2379a3973dcd230d1be49afaa1" - integrity sha512-0voOKJCn9RaM3np6soqEfo7SsVvf2C+CDTWhW+H/1AyBhybASpExtDEz+7ECck9TwPzFQ5tt+I3zVugUJbJWDg== - dependencies: - chalk "^4.1.2" - tslib "^2.6.0" - -"@docusaurus/mdx-loader@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.2.1.tgz#bea07d47300a158537bc81553769acf72c91c6c3" - integrity sha512-Fs8tXhXKZjNkdGaOy1xSLXSwfjCMT73J3Zfrju2U16uGedRFRjgK0ojpK5tiC7TnunsL3tOFgp1BSMBRflX9gw== - dependencies: - "@docusaurus/logger" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - "@mdx-js/mdx" "^3.0.0" - "@slorber/remark-comment" "^1.0.0" - escape-html "^1.0.3" - estree-util-value-to-estree "^3.0.1" - file-loader "^6.2.0" - fs-extra "^11.1.1" - image-size "^1.0.2" - mdast-util-mdx "^3.0.0" - mdast-util-to-string "^4.0.0" - rehype-raw "^7.0.0" - remark-directive "^3.0.0" - remark-emoji "^4.0.0" - remark-frontmatter "^5.0.0" - remark-gfm "^4.0.0" - stringify-object "^3.3.0" - tslib "^2.6.0" - unified "^11.0.3" - unist-util-visit "^5.0.0" - url-loader "^4.1.1" - vfile "^6.0.1" - webpack "^5.88.1" - -"@docusaurus/module-type-aliases@3.2.1", "@docusaurus/module-type-aliases@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.2.1.tgz#fa8fd746890825b4301db2ddbe29d7cfbeee0380" - integrity sha512-FyViV5TqhL1vsM7eh29nJ5NtbRE6Ra6LP1PDcPvhwPSlA7eiWGRKAn3jWwMUcmjkos5SYY+sr0/feCdbM3eQHQ== - dependencies: - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "3.2.1" - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router-config" "*" - "@types/react-router-dom" "*" - react-helmet-async "*" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - -"@docusaurus/plugin-content-blog@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.2.1.tgz#1b28c45102abc4be1a57caba76672c5ccdacce63" - integrity sha512-lOx0JfhlGZoZu6pEJfeEpSISZR5dQbJGGvb42IP13G5YThNHhG9R9uoWuo4IOimPqBC7sHThdLA3VLevk61Fsw== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/logger" "3.2.1" - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - cheerio "^1.0.0-rc.12" - feed "^4.2.2" - fs-extra "^11.1.1" - lodash "^4.17.21" - reading-time "^1.5.0" - srcset "^4.0.0" - tslib "^2.6.0" - unist-util-visit "^5.0.0" - utility-types "^3.10.0" - webpack "^5.88.1" - -"@docusaurus/plugin-content-docs@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.2.1.tgz#d3a36239aa11392b0fbed2eaea105c17f64f50ef" - integrity sha512-GHe5b/lCskAR8QVbfWAfPAApvRZgqk7FN3sOHgjCtjzQACZxkHmq6QqyqZ8Jp45V7lVck4wt2Xw2IzBJ7Cz3bA== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/logger" "3.2.1" - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/module-type-aliases" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - "@types/react-router-config" "^5.0.7" - combine-promises "^1.1.0" - fs-extra "^11.1.1" - js-yaml "^4.1.0" - lodash "^4.17.21" - tslib "^2.6.0" - utility-types "^3.10.0" - webpack "^5.88.1" - -"@docusaurus/plugin-content-pages@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.2.1.tgz#7e04c470958147ec8bf72c05d3608f1bb8307aab" - integrity sha512-TOqVfMVTAHqWNEGM94Drz+PUpHDbwFy6ucHFgyTx9zJY7wPNSG5EN+rd/mU7OvAi26qpOn2o9xTdUmb28QLjEQ== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - fs-extra "^11.1.1" - tslib "^2.6.0" - webpack "^5.88.1" - -"@docusaurus/plugin-debug@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.2.1.tgz#59918ac654cbf0f7cf48d43fb9d944296d440784" - integrity sha512-AMKq8NuUKf2sRpN1m/sIbqbRbnmk+rSA+8mNU1LNxEl9BW9F/Gng8m9HKlzeyMPrf5XidzS1jqkuTLDJ6KIrFw== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - fs-extra "^11.1.1" - react-json-view-lite "^1.2.0" - tslib "^2.6.0" - -"@docusaurus/plugin-google-analytics@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.2.1.tgz#6cab8df9218b016ce508ff96dd39cf9c87cdc9e5" - integrity sha512-/rJ+9u+Px0eTCiF4TNcNtj3kHf8cp6K1HCwOTdbsSlz6Xn21syZYcy+f1VM9wF6HrvUkXUcbM5TDCvg2IRL6bQ== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - tslib "^2.6.0" - -"@docusaurus/plugin-google-gtag@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.2.1.tgz#b54e6bfa0ca2efac5ed02fea39cbf069d2893a2c" - integrity sha512-XtuJnlMvYfppeVdUyKiDIJAa/gTJKCQU92z8CLZZ9ibJdgVjFOLS10s0hIC0eL5z0U2u2loJz2rZ63HOkNHbBA== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - "@types/gtag.js" "^0.0.12" - tslib "^2.6.0" - -"@docusaurus/plugin-google-tag-manager@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.2.1.tgz#8b38237c154a377f6e199b77ecc871c6c6bb41a4" - integrity sha512-wiS/kE0Ny5pnjTxVCs8ljRnkL1RVMj59t6jmSsgEX7piDOoaXSMIUaoIt9ogS/v132uO0xEsxHstkRUZHQyPcQ== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - tslib "^2.6.0" - -"@docusaurus/plugin-sitemap@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.2.1.tgz#306b3e34cfbe38582ccbbd85d83ce0bdd0ae4cf7" - integrity sha512-uWZ7AxzdeaQSTCwD2yZtOiEm9zyKU+wqCmi/Sf25kQQqqFSBZUStXfaQ8OHP9cecnw893ZpZ811rPhB/wfujJw== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/logger" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - fs-extra "^11.1.1" - sitemap "^7.1.1" - tslib "^2.6.0" - -"@docusaurus/preset-classic@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.2.1.tgz#25a18ebaf271ec91ab7430a76a9054f101593de1" - integrity sha512-E3OHSmttpEBcSMhfPBq3EJMBxZBM01W1rnaCUTXy9EHvkmB5AwgTfW1PwGAybPAX579ntE03R+2zmXdizWfKnQ== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/plugin-content-blog" "3.2.1" - "@docusaurus/plugin-content-docs" "3.2.1" - "@docusaurus/plugin-content-pages" "3.2.1" - "@docusaurus/plugin-debug" "3.2.1" - "@docusaurus/plugin-google-analytics" "3.2.1" - "@docusaurus/plugin-google-gtag" "3.2.1" - "@docusaurus/plugin-google-tag-manager" "3.2.1" - "@docusaurus/plugin-sitemap" "3.2.1" - "@docusaurus/theme-classic" "3.2.1" - "@docusaurus/theme-common" "3.2.1" - "@docusaurus/theme-search-algolia" "3.2.1" - "@docusaurus/types" "3.2.1" - -"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" - integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== - dependencies: - "@types/react" "*" - prop-types "^15.6.2" - -"@docusaurus/theme-classic@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.2.1.tgz#0aea144bbbfa77b699f6eff7ffaeb36a1adc6c02" - integrity sha512-+vSbnQyoWjc6vRZi4vJO2dBU02wqzynsai15KK+FANZudrYaBHtkbLZAQhgmxzBGVpxzi87gRohlMm+5D8f4tA== - dependencies: - "@docusaurus/core" "3.2.1" - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/module-type-aliases" "3.2.1" - "@docusaurus/plugin-content-blog" "3.2.1" - "@docusaurus/plugin-content-docs" "3.2.1" - "@docusaurus/plugin-content-pages" "3.2.1" - "@docusaurus/theme-common" "3.2.1" - "@docusaurus/theme-translations" "3.2.1" - "@docusaurus/types" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - "@mdx-js/react" "^3.0.0" - clsx "^2.0.0" - copy-text-to-clipboard "^3.2.0" - infima "0.2.0-alpha.43" - lodash "^4.17.21" - nprogress "^0.2.0" - postcss "^8.4.26" - prism-react-renderer "^2.3.0" - prismjs "^1.29.0" - react-router-dom "^5.3.4" - rtlcss "^4.1.0" - tslib "^2.6.0" - utility-types "^3.10.0" - -"@docusaurus/theme-common@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.2.1.tgz#017b0cf05de2a4fa7b117ee44f25a3e8541c8bb9" - integrity sha512-d+adiD7L9xv6EvfaAwUqdKf4orsM3jqgeqAM+HAjgL/Ux0GkVVnfKr+tsoe+4ow4rHe6NUt+nkkW8/K8dKdilA== - dependencies: - "@docusaurus/mdx-loader" "3.2.1" - "@docusaurus/module-type-aliases" "3.2.1" - "@docusaurus/plugin-content-blog" "3.2.1" - "@docusaurus/plugin-content-docs" "3.2.1" - "@docusaurus/plugin-content-pages" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router-config" "*" - clsx "^2.0.0" - parse-numeric-range "^1.3.0" - prism-react-renderer "^2.3.0" - tslib "^2.6.0" - utility-types "^3.10.0" - -"@docusaurus/theme-search-algolia@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.2.1.tgz#6617d43ab0726b744bf8e32eb8533417c0d66b7d" - integrity sha512-bzhCrpyXBXzeydNUH83II2akvFEGfhsNTPPWsk5N7e+odgQCQwoHhcF+2qILbQXjaoZ6B3c48hrvkyCpeyqGHw== - dependencies: - "@docsearch/react" "^3.5.2" - "@docusaurus/core" "3.2.1" - "@docusaurus/logger" "3.2.1" - "@docusaurus/plugin-content-docs" "3.2.1" - "@docusaurus/theme-common" "3.2.1" - "@docusaurus/theme-translations" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-validation" "3.2.1" - algoliasearch "^4.18.0" - algoliasearch-helper "^3.13.3" - clsx "^2.0.0" - eta "^2.2.0" - fs-extra "^11.1.1" - lodash "^4.17.21" - tslib "^2.6.0" - utility-types "^3.10.0" - -"@docusaurus/theme-translations@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.2.1.tgz#894f6cb5bb121aa45a4a5f1383b70a8e3ae6a5d9" - integrity sha512-jAUMkIkFfY+OAhJhv6mV8zlwY6J4AQxJPTgLdR2l+Otof9+QdJjHNh/ifVEu9q0lp3oSPlJj9l05AaP7Ref+cg== - dependencies: - fs-extra "^11.1.1" - tslib "^2.6.0" - -"@docusaurus/types@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.2.1.tgz#88ccd4b8fa236628a29c89b8b0f60f0cc4716b69" - integrity sha512-n/toxBzL2oxTtRTOFiGKsHypzn/Pm+sXyw+VSk1UbqbXQiHOwHwts55bpKwbcUgA530Is6kix3ELiFOv9GAMfw== - dependencies: - "@mdx-js/mdx" "^3.0.0" - "@types/history" "^4.7.11" - "@types/react" "*" - commander "^5.1.0" - joi "^17.9.2" - react-helmet-async "^1.3.0" - utility-types "^3.10.0" - webpack "^5.88.1" - webpack-merge "^5.9.0" - -"@docusaurus/utils-common@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.2.1.tgz#c275fd9984951244cc4f595ce6dfd0522e40c68d" - integrity sha512-N5vadULnRLiqX2QfTjVEU3u5vo6RG2EZTdyXvJdzDOdrLCGIZAfnf/VkssinFZ922sVfaFfQ4FnStdhn5TWdVg== - dependencies: - tslib "^2.6.0" - -"@docusaurus/utils-validation@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.2.1.tgz#42ff0d2ae11c81d199ea485f27b86b40779673ed" - integrity sha512-+x7IR9hNMXi62L1YAglwd0s95fR7+EtirjTxSN4kahYRWGqOi3jlQl1EV0az/yTEvKbxVvOPcdYicGu9dk4LJw== - dependencies: - "@docusaurus/logger" "3.2.1" - "@docusaurus/utils" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - joi "^17.9.2" - js-yaml "^4.1.0" - tslib "^2.6.0" - -"@docusaurus/utils@3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.2.1.tgz#25247d071618bc7ece9bbc3d59f3ee1ac3ded727" - integrity sha512-DPkIS/EPc+pGAV798PUXgNzJFM3HJouoQXgr0KDZuJVz1EkWbDLOcQwLIz8Qx7liI9ddfkN/TXTRQdsTPZNakw== - dependencies: - "@docusaurus/logger" "3.2.1" - "@docusaurus/utils-common" "3.2.1" - "@svgr/webpack" "^6.5.1" - escape-string-regexp "^4.0.0" - file-loader "^6.2.0" - fs-extra "^11.1.1" - github-slugger "^1.5.0" - globby "^11.1.0" - gray-matter "^4.0.3" - jiti "^1.20.0" - js-yaml "^4.1.0" - lodash "^4.17.21" - micromatch "^4.0.5" - prompts "^2.4.2" - resolve-pathname "^3.0.0" - shelljs "^0.8.5" - tslib "^2.6.0" - url-loader "^4.1.1" - webpack "^5.88.1" - -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== - -"@hapi/topo@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/source-map@^0.3.3": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" - integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" - integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@leichtgewicht/ip-codec@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" - integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== - -"@mdx-js/mdx@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.0.1.tgz#617bd2629ae561fdca1bb88e3badd947f5a82191" - integrity sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA== - dependencies: - "@types/estree" "^1.0.0" - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^3.0.0" - "@types/mdx" "^2.0.0" - collapse-white-space "^2.0.0" - devlop "^1.0.0" - estree-util-build-jsx "^3.0.0" - estree-util-is-identifier-name "^3.0.0" - estree-util-to-js "^2.0.0" - estree-walker "^3.0.0" - hast-util-to-estree "^3.0.0" - hast-util-to-jsx-runtime "^2.0.0" - markdown-extensions "^2.0.0" - periscopic "^3.0.0" - remark-mdx "^3.0.0" - remark-parse "^11.0.0" - remark-rehype "^11.0.0" - source-map "^0.7.0" - unified "^11.0.0" - unist-util-position-from-estree "^2.0.0" - unist-util-stringify-position "^4.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" - -"@mdx-js/react@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.0.1.tgz#997a19b3a5b783d936c75ae7c47cfe62f967f746" - integrity sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A== - dependencies: - "@types/mdx" "^2.0.0" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@pnpm/config.env-replace@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" - integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== - -"@pnpm/network.ca-file@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" - integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== - dependencies: - graceful-fs "4.2.10" - -"@pnpm/npm-conf@^2.1.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz#0058baf1c26cbb63a828f0193795401684ac86f0" - integrity sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA== - dependencies: - "@pnpm/config.env-replace" "^1.1.0" - "@pnpm/network.ca-file" "^1.0.1" - config-chain "^1.1.11" - -"@polka/url@^1.0.0-next.24": - version "1.0.0-next.24" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3" - integrity sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ== - -"@sideway/address@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" - integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" - integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sindresorhus/is@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - -"@sindresorhus/is@^5.2.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" - integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== - -"@slorber/remark-comment@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@slorber/remark-comment/-/remark-comment-1.0.0.tgz#2a020b3f4579c89dec0361673206c28d67e08f5a" - integrity sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA== - dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.1.0" - micromark-util-symbol "^1.0.1" - -"@svgr/babel-plugin-add-jsx-attribute@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" - integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== - -"@svgr/babel-plugin-remove-jsx-attribute@*": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" - integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== - -"@svgr/babel-plugin-remove-jsx-empty-expression@*": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" - integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== - -"@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" - integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== - -"@svgr/babel-plugin-svg-dynamic-title@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" - integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== - -"@svgr/babel-plugin-svg-em-dimensions@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" - integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== - -"@svgr/babel-plugin-transform-react-native-svg@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" - integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== - -"@svgr/babel-plugin-transform-svg-component@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" - integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== - -"@svgr/babel-preset@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" - integrity sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^6.5.1" - "@svgr/babel-plugin-remove-jsx-attribute" "*" - "@svgr/babel-plugin-remove-jsx-empty-expression" "*" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.5.1" - "@svgr/babel-plugin-svg-dynamic-title" "^6.5.1" - "@svgr/babel-plugin-svg-em-dimensions" "^6.5.1" - "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" - "@svgr/babel-plugin-transform-svg-component" "^6.5.1" - -"@svgr/core@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" - integrity sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw== - dependencies: - "@babel/core" "^7.19.6" - "@svgr/babel-preset" "^6.5.1" - "@svgr/plugin-jsx" "^6.5.1" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" - -"@svgr/hast-util-to-babel-ast@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" - integrity sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw== - dependencies: - "@babel/types" "^7.20.0" - entities "^4.4.0" - -"@svgr/plugin-jsx@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" - integrity sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw== - dependencies: - "@babel/core" "^7.19.6" - "@svgr/babel-preset" "^6.5.1" - "@svgr/hast-util-to-babel-ast" "^6.5.1" - svg-parser "^2.0.4" - -"@svgr/plugin-svgo@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" - integrity sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ== - dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.8.0" - -"@svgr/webpack@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.5.1.tgz#ecf027814fc1cb2decc29dc92f39c3cf691e40e8" - integrity sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA== - dependencies: - "@babel/core" "^7.19.6" - "@babel/plugin-transform-react-constant-elements" "^7.18.12" - "@babel/preset-env" "^7.19.4" - "@babel/preset-react" "^7.18.6" - "@babel/preset-typescript" "^7.18.6" - "@svgr/core" "^6.5.1" - "@svgr/plugin-jsx" "^6.5.1" - "@svgr/plugin-svgo" "^6.5.1" - -"@szmarczak/http-timer@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" - integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== - dependencies: - defer-to-connect "^2.0.1" - -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== - -"@tsconfig/docusaurus@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-2.0.3.tgz#08a4a65e038a499fc4154ce32b538913d9f3c90d" - integrity sha512-3l1L5PzWVa7l0691TjnsZ0yOIEwG9DziSqu5IPZPlI5Dowi7z42cEym8Y35GHbgHvPcBfNxfrbxm7Cncn4nByQ== - -"@types/acorn@^4.0.0": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" - integrity sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ== - dependencies: - "@types/estree" "*" - -"@types/body-parser@*": - version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/bonjour@^3.5.9": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" - integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== - dependencies: - "@types/node" "*" - -"@types/connect-history-api-fallback@^1.3.5": - version "1.5.4" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" - integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== - dependencies: - "@types/express-serve-static-core" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== - dependencies: - "@types/node" "*" - -"@types/d3-scale-chromatic@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" - integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== - -"@types/d3-scale@^4.0.3": - version "4.0.8" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" - integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== - dependencies: - "@types/d3-time" "*" - -"@types/d3-time@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" - integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== - -"@types/debug@^4.0.0": - version "4.1.12" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" - integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== - dependencies: - "@types/ms" "*" - -"@types/eslint-scope@^3.7.3": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.56.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.2.tgz#1c72a9b794aa26a8b94ad26d5b9aa51c8a6384bb" - integrity sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree-jsx@^1.0.0": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" - integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== - dependencies: - "@types/estree" "*" - -"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.41" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz#5077defa630c2e8d28aa9ffc2c01c157c305bef6" - integrity sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - -"@types/express@*", "@types/express@^4.17.13": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/gtag.js@^0.0.12": - version "0.0.12" - resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.12.tgz#095122edca896689bdfcdd73b057e23064d23572" - integrity sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg== - -"@types/hast@^2.0.0": - version "2.3.10" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" - integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== - dependencies: - "@types/unist" "^2" - -"@types/hast@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" - integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== - dependencies: - "@types/unist" "*" - -"@types/history@^4.7.11": - version "4.7.11" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" - integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== - -"@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== - -"@types/http-cache-semantics@^4.0.2": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" - integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== - -"@types/http-errors@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== - -"@types/http-proxy@^1.17.8": - version "1.17.14" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" - integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/mdast@^3.0.0": - version "3.0.15" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" - integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== - dependencies: - "@types/unist" "^2" - -"@types/mdast@^4.0.0", "@types/mdast@^4.0.2": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.3.tgz#1e011ff013566e919a4232d1701ad30d70cab333" - integrity sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg== - dependencies: - "@types/unist" "*" - -"@types/mdx@^2.0.0": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.12.tgz#38db34cc8999b982beaec01399620bee6c65ef2e" - integrity sha512-H9VZ9YqE+H28FQVchC83RCs5xQ2J7mAAv6qdDEaWmXEVl3OpdH+xfrSUzQ1lp7U7oSTRZ0RvW08ASPJsYBi7Cw== - -"@types/mime@*": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" - integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== - -"@types/mime@^1": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== - -"@types/ms@*": - version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" - integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== - -"@types/nlcst@^1.0.0": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@types/nlcst/-/nlcst-1.0.4.tgz#3b8a9c279a2367602512588a0ba6a0e93634ee3e" - integrity sha512-ABoYdNQ/kBSsLvZAekMhIPMQ3YUZvavStpKYs7BjLLuKVmIMA0LUgZ7b54zzuWJRbHF80v1cNf4r90Vd6eMQDg== - dependencies: - "@types/unist" "^2" - -"@types/node-forge@^1.3.0": - version "1.3.11" - resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" - integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== - dependencies: - "@types/node" "*" - -"@types/node@*": - version "20.11.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" - integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== - dependencies: - undici-types "~5.26.4" - -"@types/node@^17.0.5": - version "17.0.45" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" - integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== - -"@types/parse-json@^4.0.0": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" - integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== - -"@types/prismjs@^1.26.0": - version "1.26.3" - resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.3.tgz#47fe8e784c2dee24fe636cab82e090d3da9b7dec" - integrity sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw== - -"@types/prop-types@*": - version "15.7.11" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" - integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== - -"@types/qs@*": - version "6.9.11" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" - integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== - -"@types/range-parser@*": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" - integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== - -"@types/react-router-config@*", "@types/react-router-config@^5.0.7": - version "5.0.11" - resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.11.tgz#2761a23acc7905a66a94419ee40294a65aaa483a" - integrity sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router" "^5.1.0" - -"@types/react-router-dom@*": - version "5.3.3" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" - integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router" "*" - -"@types/react-router@*", "@types/react-router@^5.1.0": - version "5.1.20" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c" - integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - -"@types/react@*": - version "18.2.48" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1" - integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== - -"@types/sax@^1.2.1": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.7.tgz#ba5fe7df9aa9c89b6dff7688a19023dd2963091d" - integrity sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A== - dependencies: - "@types/node" "*" - -"@types/scheduler@*": - version "0.16.8" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - -"@types/send@*": - version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/serve-index@^1.9.1": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" - integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== - dependencies: - "@types/express" "*" - -"@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.5" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" - integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== - dependencies: - "@types/http-errors" "*" - "@types/mime" "*" - "@types/node" "*" - -"@types/sockjs@^0.3.33": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" - integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== - dependencies: - "@types/node" "*" - -"@types/unist@*", "@types/unist@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" - integrity sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ== - -"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" - integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== - -"@types/ws@^8.5.5": - version "8.5.10" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" - integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== - dependencies: - "@types/node" "*" - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - -"@types/yauzl@^2.9.1": - version "2.10.3" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" - integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== - dependencies: - "@types/node" "*" - -"@ungap/structured-clone@^1.0.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== - -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== - -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" - -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - -acorn-jsx@^5.0.0: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.0.0: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.0.0, acorn@^8.0.4, acorn@^8.7.1, acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -address@^1.0.1, address@^1.1.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" - integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.12.2, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^8.0.0, ajv@^8.9.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -algoliasearch-helper@^3.13.3: - version "3.17.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.17.0.tgz#b8f2f98c9a49d9affb51205f8df116164050a842" - integrity sha512-R5422OiQjvjlK3VdpNQ/Qk7KsTIGeM5ACm8civGifOVWdRRV/3SgXuKmeNxe94Dz6fwj/IgpVmXbHutU4mHubg== - dependencies: - "@algolia/events" "^4.0.1" - -algoliasearch@^4.12.0, algoliasearch@^4.19.1: - version "4.22.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.22.1.tgz#f10fbecdc7654639ec20d62f109c1b3a46bc6afc" - integrity sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg== - dependencies: - "@algolia/cache-browser-local-storage" "4.22.1" - "@algolia/cache-common" "4.22.1" - "@algolia/cache-in-memory" "4.22.1" - "@algolia/client-account" "4.22.1" - "@algolia/client-analytics" "4.22.1" - "@algolia/client-common" "4.22.1" - "@algolia/client-personalization" "4.22.1" - "@algolia/client-search" "4.22.1" - "@algolia/logger-common" "4.22.1" - "@algolia/logger-console" "4.22.1" - "@algolia/requester-browser-xhr" "4.22.1" - "@algolia/requester-common" "4.22.1" - "@algolia/requester-node-http" "4.22.1" - "@algolia/transporter" "4.22.1" - -algoliasearch@^4.18.0: - version "4.23.2" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.23.2.tgz#3b7bc93d98f3965628c73a06cbf9203531324a9d" - integrity sha512-8aCl055IsokLuPU8BzLjwzXjb7ty9TPcUFFOk0pYOwsE5DMVhE3kwCMFtsCFKcnoPZK7oObm+H5mbnSO/9ioxQ== - dependencies: - "@algolia/cache-browser-local-storage" "4.23.2" - "@algolia/cache-common" "4.23.2" - "@algolia/cache-in-memory" "4.23.2" - "@algolia/client-account" "4.23.2" - "@algolia/client-analytics" "4.23.2" - "@algolia/client-common" "4.23.2" - "@algolia/client-personalization" "4.23.2" - "@algolia/client-search" "4.23.2" - "@algolia/logger-common" "4.23.2" - "@algolia/logger-console" "4.23.2" - "@algolia/recommend" "4.23.2" - "@algolia/requester-browser-xhr" "4.23.2" - "@algolia/requester-common" "4.23.2" - "@algolia/requester-node-http" "4.23.2" - "@algolia/transporter" "4.23.2" - -ansi-align@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" - integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-iterate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-2.0.1.tgz#6efd43f8295b3fee06251d3d62ead4bd9805dd24" - integrity sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -astring@^1.8.0: - version "1.8.6" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.6.tgz#2c9c157cf1739d67561c56ba896e6948f6b93731" - integrity sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -autoprefixer@^10.4.12: - version "10.4.17" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.17.tgz#35cd5695cbbe82f536a50fa025d561b01fdec8be" - integrity sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg== - dependencies: - browserslist "^4.22.2" - caniuse-lite "^1.0.30001578" - fraction.js "^4.3.7" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -autoprefixer@^10.4.14: - version "10.4.19" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" - integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== - dependencies: - browserslist "^4.23.0" - caniuse-lite "^1.0.30001599" - fraction.js "^4.3.7" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -babel-loader@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" - integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== - dependencies: - find-cache-dir "^4.0.0" - schema-utils "^4.0.0" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.10" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" - integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.1" - semver "^6.3.1" - -babel-plugin-polyfill-corejs2@^0.4.7: - version "0.4.8" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz#dbcc3c8ca758a290d47c3c6a490d59429b0d2269" - integrity sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.5.0" - semver "^6.3.1" - -babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" - integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - core-js-compat "^3.36.1" - -babel-plugin-polyfill-corejs3@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz#941855aa7fdaac06ed24c730a93450d2b2b76d04" - integrity sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.4.4" - core-js-compat "^3.33.1" - -babel-plugin-polyfill-regenerator@^0.5.4: - version "0.5.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz#8b0c8fc6434239e5d7b8a9d1f832bb2b0310f06a" - integrity sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.5.0" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz#4f08ef4c62c7a7f66a35ed4c0d75e30506acc6be" - integrity sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - -bail@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" - integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -bonjour-service@^1.0.11: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" - integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== - dependencies: - fast-deep-equal "^3.1.3" - multicast-dns "^7.2.5" - -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== - -boxen@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-6.2.1.tgz#b098a2278b2cd2845deef2dff2efc38d329b434d" - integrity sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw== - dependencies: - ansi-align "^3.0.1" - camelcase "^6.2.0" - chalk "^4.1.2" - cli-boxes "^3.0.0" - string-width "^5.0.1" - type-fest "^2.5.0" - widest-line "^4.0.1" - wrap-ansi "^8.0.1" - -boxen@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-7.1.1.tgz#f9ba525413c2fec9cdb88987d835c4f7cad9c8f4" - integrity sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog== - dependencies: - ansi-align "^3.0.1" - camelcase "^7.0.1" - chalk "^5.2.0" - cli-boxes "^3.0.0" - string-width "^5.1.2" - type-fest "^2.13.0" - widest-line "^4.0.1" - wrap-ansi "^8.1.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.4, browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== - dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -browserslist@^4.21.10, browserslist@^4.23.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== - dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^5.2.1, buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cacheable-lookup@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" - integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== - -cacheable-request@^10.2.8: - version "10.2.14" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" - integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== - dependencies: - "@types/http-cache-semantics" "^4.0.2" - get-stream "^6.0.1" - http-cache-semantics "^4.1.1" - keyv "^4.5.3" - mimic-response "^4.0.0" - normalize-url "^8.0.0" - responselike "^3.0.0" - -call-bind@^1.0.0, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -camelcase@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" - integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001565, caniuse-lite@^1.0.30001578: - version "1.0.30001579" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz#45c065216110f46d6274311a4b3fcf6278e0852a" - integrity sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA== - -caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: - version "1.0.30001607" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz#b91e8e033f6bca4e13d3d45388d87fa88931d9a5" - integrity sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w== - -ccount@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" - integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== - -chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^5.0.1, chalk@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -character-entities-html4@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" - integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== - -character-entities-legacy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" - integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== - -character-entities@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" - integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== - -character-reference-invalid@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" - integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== - -cheerio-select@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" - integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== - dependencies: - boolbase "^1.0.0" - css-select "^5.1.0" - css-what "^6.1.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - -cheerio@^1.0.0-rc.12, cheerio@^1.0.0-rc.9: - version "1.0.0-rc.12" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" - integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== - dependencies: - cheerio-select "^2.1.0" - dom-serializer "^2.0.0" - domhandler "^5.0.3" - domutils "^3.0.1" - htmlparser2 "^8.0.1" - parse5 "^7.0.0" - parse5-htmlparser2-tree-adapter "^7.0.0" - -chokidar@^3.4.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -clean-css@^5.2.2, clean-css@^5.3.2, clean-css@~5.3.2: - version "5.3.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" - integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" - integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== - -cli-table3@^0.6.3: - version "0.6.4" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.4.tgz#d1c536b8a3f2e7bec58f67ac9e5769b1b30088b0" - integrity sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clsx@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -clsx@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" - integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== - -collapse-white-space@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-2.1.0.tgz#640257174f9f42c740b40f3b55ee752924feefca" - integrity sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" - integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== - -colorette@^2.0.10: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -combine-promises@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.2.0.tgz#5f2e68451862acf85761ded4d9e2af7769c2ca6a" - integrity sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ== - -comma-separated-tokens@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" - integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== - -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^5.0.4: - version "5.0.5" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-5.0.5.tgz#5f25933ffe6dedd983c635d38a21d7e623fda357" - integrity sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA== - dependencies: - array-back "^2.0.0" - chalk "^2.4.1" - table-layout "^0.4.3" - typical "^2.6.1" - -commander@7, commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -config-chain@^1.1.11: - version "1.1.13" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" - integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -configstore@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-6.0.0.tgz#49eca2ebc80983f77e09394a1a56e0aca8235566" - integrity sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA== - dependencies: - dot-prop "^6.0.1" - graceful-fs "^4.2.6" - unique-string "^3.0.0" - write-file-atomic "^3.0.3" - xdg-basedir "^5.0.1" - -connect-history-api-fallback@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" - integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== - -consola@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" - integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -copy-text-to-clipboard@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz#0202b2d9bdae30a49a53f898626dcc3b49ad960b" - integrity sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q== - -copy-webpack-plugin@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" - integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== - dependencies: - fast-glob "^3.2.11" - glob-parent "^6.0.1" - globby "^13.1.1" - normalize-path "^3.0.0" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - -core-js-compat@^3.31.0, core-js-compat@^3.33.1: - version "3.35.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.35.1.tgz#215247d7edb9e830efa4218ff719beb2803555e2" - integrity sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw== - dependencies: - browserslist "^4.22.2" - -core-js-compat@^3.36.1: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.1.tgz#1818695d72c99c25d621dca94e6883e190cea3c8" - integrity sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA== - dependencies: - browserslist "^4.23.0" - -core-js-pure@^3.30.2: - version "3.35.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.35.1.tgz#f33ad7fdf9dddae260339a30e5f8363f5c49a3bc" - integrity sha512-zcIdi/CL3MWbBJYo5YCeVAAx+Sy9yJE9I3/u9LkFABwbeaPhTMRWraM8mYFp9jW5Z50hOy7FVzCc8dCrpZqtIQ== - -core-js@^3.31.1: - version "3.36.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.36.1.tgz#c97a7160ebd00b2de19e62f4bbd3406ab720e578" - integrity sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cose-base@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" - integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== - dependencies: - layout-base "^1.0.0" - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - -cosmiconfig@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" - integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -cosmiconfig@^8.3.5: - version "8.3.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" - integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== - dependencies: - import-fresh "^3.3.0" - js-yaml "^4.1.0" - parse-json "^5.2.0" - path-type "^4.0.0" - -cross-fetch@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-random-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-4.0.0.tgz#5a3cc53d7dd86183df5da0312816ceeeb5bb1fc2" - integrity sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA== - dependencies: - type-fest "^1.0.1" - -css-declaration-sorter@^6.3.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" - integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== - -css-loader@^6.8.1: - version "6.11.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" - integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.33" - postcss-modules-extract-imports "^3.1.0" - postcss-modules-local-by-default "^4.0.5" - postcss-modules-scope "^3.2.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.5.4" - -css-minimizer-webpack-plugin@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz#79f6199eb5adf1ff7ba57f105e3752d15211eb35" - integrity sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA== - dependencies: - cssnano "^5.1.8" - jest-worker "^29.1.2" - postcss "^8.4.17" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-select@^4.1.3: - version "4.3.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" - integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== - dependencies: - boolbase "^1.0.0" - css-what "^6.0.1" - domhandler "^4.3.1" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== - dependencies: - boolbase "^1.0.0" - css-what "^6.1.0" - domhandler "^5.0.2" - domutils "^3.0.1" - nth-check "^2.0.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^6.0.1, css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-advanced@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz#25558a1fbf3a871fb6429ce71e41be7f5aca6eef" - integrity sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ== - dependencies: - autoprefixer "^10.4.12" - cssnano-preset-default "^5.2.14" - postcss-discard-unused "^5.1.0" - postcss-merge-idents "^5.1.1" - postcss-reduce-idents "^5.2.0" - postcss-zindex "^5.1.0" - -cssnano-preset-default@^5.2.14: - version "5.2.14" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" - integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A== - dependencies: - css-declaration-sorter "^6.3.1" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.1" - postcss-convert-values "^5.1.3" - postcss-discard-comments "^5.1.2" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.1" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.4" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.4" - postcss-minify-selectors "^5.2.1" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.1" - postcss-normalize-repeat-style "^5.1.1" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.1" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.1" - postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.2" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.1" - -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== - -cssnano@^5.1.15, cssnano@^5.1.8: - version "5.1.15" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" - integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw== - dependencies: - cssnano-preset-default "^5.2.14" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -cytoscape-cose-bilkent@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" - integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== - dependencies: - cose-base "^1.0.0" - -cytoscape@^3.28.1: - version "3.28.1" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.28.1.tgz#f32c3e009bdf32d47845a16a4cd2be2bbc01baf7" - integrity sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg== - dependencies: - heap "^0.2.6" - lodash "^4.17.21" - -"d3-array@1 - 2": - version "2.12.1" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" - integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== - dependencies: - internmap "^1.0.0" - -"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" - integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== - dependencies: - internmap "1 - 2" - -d3-axis@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" - integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== - -d3-brush@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" - integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== - dependencies: - d3-dispatch "1 - 3" - d3-drag "2 - 3" - d3-interpolate "1 - 3" - d3-selection "3" - d3-transition "3" - -d3-chord@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" - integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== - dependencies: - d3-path "1 - 3" - -"d3-color@1 - 3", d3-color@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" - integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== - -d3-contour@4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" - integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== - dependencies: - d3-array "^3.2.0" - -d3-delaunay@6: - version "6.0.4" - resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" - integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== - dependencies: - delaunator "5" - -"d3-dispatch@1 - 3", d3-dispatch@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" - integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== - -"d3-drag@2 - 3", d3-drag@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" - integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== - dependencies: - d3-dispatch "1 - 3" - d3-selection "3" - -"d3-dsv@1 - 3", d3-dsv@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" - integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== - dependencies: - commander "7" - iconv-lite "0.6" - rw "1" - -"d3-ease@1 - 3", d3-ease@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" - integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== - -d3-fetch@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" - integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== - dependencies: - d3-dsv "1 - 3" - -d3-force@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" - integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== - dependencies: - d3-dispatch "1 - 3" - d3-quadtree "1 - 3" - d3-timer "1 - 3" - -"d3-format@1 - 3", d3-format@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" - integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== - -d3-geo@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" - integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== - dependencies: - d3-array "2.5.0 - 3" - -d3-hierarchy@3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" - integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== - -"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" - integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== - dependencies: - d3-color "1 - 3" - -d3-path@1: - version "1.0.9" - resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" - integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== - -"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" - integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== - -d3-polygon@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" - integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== - -"d3-quadtree@1 - 3", d3-quadtree@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" - integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== - -d3-random@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" - integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== - -d3-sankey@^0.12.3: - version "0.12.3" - resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" - integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== - dependencies: - d3-array "1 - 2" - d3-shape "^1.2.0" - -d3-scale-chromatic@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" - integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== - dependencies: - d3-color "1 - 3" - d3-interpolate "1 - 3" - -d3-scale@4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" - integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== - dependencies: - d3-array "2.10.0 - 3" - d3-format "1 - 3" - d3-interpolate "1.2.0 - 3" - d3-time "2.1.1 - 3" - d3-time-format "2 - 4" - -"d3-selection@2 - 3", d3-selection@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" - integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== - -d3-shape@3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" - integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== - dependencies: - d3-path "^3.1.0" - -d3-shape@^1.2.0: - version "1.3.7" - resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" - integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== - dependencies: - d3-path "1" - -"d3-time-format@2 - 4", d3-time-format@4: - version "4.1.0" - resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" - integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== - dependencies: - d3-time "1 - 3" - -"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" - integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== - dependencies: - d3-array "2 - 3" - -"d3-timer@1 - 3", d3-timer@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" - integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== - -"d3-transition@2 - 3", d3-transition@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" - integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== - dependencies: - d3-color "1 - 3" - d3-dispatch "1 - 3" - d3-ease "1 - 3" - d3-interpolate "1 - 3" - d3-timer "1 - 3" - -d3-zoom@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" - integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== - dependencies: - d3-dispatch "1 - 3" - d3-drag "2 - 3" - d3-interpolate "1 - 3" - d3-selection "2 - 3" - d3-transition "2 - 3" - -d3@^7.4.0, d3@^7.8.2: - version "7.8.5" - resolved "https://registry.yarnpkg.com/d3/-/d3-7.8.5.tgz#fde4b760d4486cdb6f0cc8e2cbff318af844635c" - integrity sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA== - dependencies: - d3-array "3" - d3-axis "3" - d3-brush "3" - d3-chord "3" - d3-color "3" - d3-contour "4" - d3-delaunay "6" - d3-dispatch "3" - d3-drag "3" - d3-dsv "3" - d3-ease "3" - d3-fetch "3" - d3-force "3" - d3-format "3" - d3-geo "3" - d3-hierarchy "3" - d3-interpolate "3" - d3-path "3" - d3-polygon "3" - d3-quadtree "3" - d3-random "3" - d3-scale "4" - d3-scale-chromatic "3" - d3-selection "3" - d3-shape "3" - d3-time "3" - d3-time-format "4" - d3-timer "3" - d3-transition "3" - d3-zoom "3" - -dagre-d3-es@7.0.10: - version "7.0.10" - resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz#19800d4be674379a3cd8c86a8216a2ac6827cadc" - integrity sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A== - dependencies: - d3 "^7.8.2" - lodash-es "^4.17.21" - -date-format@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.3.tgz#f63de5dc08dc02efd8ef32bf2a6918e486f35873" - integrity sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ== - -dayjs@^1.11.7: - version "1.11.10" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" - integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== - -debounce@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" - integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== - -debug@2.6.9, debug@^2.6.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decode-named-character-reference@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" - integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== - dependencies: - character-entities "^2.0.0" - -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - -deep-extend@^0.6.0, deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defer-to-connect@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -del@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" - integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -delaunator@5: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" - integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== - dependencies: - robust-predicates "^3.0.0" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - -dequal@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -detect-port@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" - integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== - dependencies: - address "^1.0.1" - debug "4" - -devlop@^1.0.0, devlop@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" - integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== - dependencies: - dequal "^2.0.0" - -devtools-protocol@0.0.1045489: - version "0.0.1045489" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz#f959ad560b05acd72d55644bc3fb8168a83abf28" - integrity sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ== - -dictionary-en-au@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/dictionary-en-au/-/dictionary-en-au-2.4.0.tgz#6d7199c623bce7f9797f96aa89fbf79fd25d1f1f" - integrity sha512-SEETr3rqt26/Umc43gemwaH/ez4gPv7I4alifu/QLi8uxiCm6a7cn3wKb22HNB5l6j/R7/Sfkq9NTKk/QRVUHw== - -dictionary-en-ca@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/dictionary-en-ca/-/dictionary-en-ca-2.4.0.tgz#5af3527670f0d5c0da23af1ee3aed7006b215c27" - integrity sha512-uDoOe7/dz1XD3niVpOroSo3Pas7cdsAp+NSwfan30MGzzeXaD04lQuTRDqHpsXuP8fq3U7f9v8Iaiyk5q/kgzw== - -dictionary-en-gb@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/dictionary-en-gb/-/dictionary-en-gb-2.4.0.tgz#110bd4e8b64111487a6caa16d0b9c324c6245226" - integrity sha512-zwc7e6CM/+Em+v74a5/ia6663nwR9vvtEayaX5WkgvHD99al1qm/RbcdLludqX3mggYxXXFN1zN5hzyREW/DXg== - -dictionary-en-za@^2.0.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dictionary-en-za/-/dictionary-en-za-2.2.0.tgz#59e25092f13d5906515d798f7022e95d8818ea73" - integrity sha512-YFod3pshfaecqCe221rczW5lVWn4ZhfFH6E395DN1bEbL4dUndGm9Bn/zxMOU2w9imYKwptYalO23hetwUx+OA== - -dictionary-en@^3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/dictionary-en/-/dictionary-en-3.2.0.tgz#5d5b5a156a5b1eb26ff96c80da3b919587f16b4b" - integrity sha512-oujbJhuplUTlDntmOoultEcNyk8ge7cFI6yXNn7eJvpbBJOhGNhWtK0XjOJsiwl4EfIeyvDKwGB95vJXv1d+lQ== - -dictionary-vi@^2.1.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dictionary-vi/-/dictionary-vi-2.2.0.tgz#c5ef4a1a7da0cf2ba50d28a6c53456b5e3e39a61" - integrity sha512-WDCaSzHMtayCIEa2hPq0rL8ds603SKNzMzNXU0kbLM7kzXoaXaKeHgPXJHKjKMxxnozKLMsg+rES7hC6Lxe7iA== - -diff@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-packet@^5.2.2: - version "5.6.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" - integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== - dependencies: - "@leichtgewicht/ip-codec" "^2.0.1" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@^1.0.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" - integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.2" - entities "^4.2.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== - dependencies: - domelementtype "^2.2.0" - -domhandler@^5.0.2, domhandler@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== - dependencies: - domelementtype "^2.3.0" - -dompurify@^3.0.5: - version "3.1.0" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.0.tgz#8c6b9fe986969a33aa4686bd829cbe8e14dd9445" - integrity sha512-yoU4rhgPKCo+p5UrWWWNKiIq+ToGqmVVhk0PmMYBK4kRsR3/qhemNFL8f6CFmBd4gMwm3F4T7HBoydP5uY07fA== - -domutils@^2.5.2, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== - dependencies: - dom-serializer "^2.0.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" - integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== - dependencies: - is-obj "^2.0.0" - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.4.601: - version "1.4.640" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.640.tgz#76290a36fa4b5f1f4cadaf1fc582478ebb3ac246" - integrity sha512-z/6oZ/Muqk4BaE7P69bXhUhpJbUM9ZJeka43ZwxsDshKtePns4mhBlh8bU5+yrnOnz3fhG82XLzGUXazOmsWnA== - -electron-to-chromium@^1.4.668: - version "1.4.729" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz#8477d21e2a50993781950885b2731d92ad532c00" - integrity sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA== - -elkjs@^0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.9.2.tgz#3d4ef6f17fde06a5d7eaa3063bb875e25e59e972" - integrity sha512-2Y/RaA1pdgSHpY0YG4TYuYCD2wh97CRvu22eLG3Kz0pgQ/6KbIFTxsTnDc4MH/6hFlg2L/9qXrDMG0nMjP63iw== - -emoji-regex@^10.0.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" - integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -emojilib@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" - integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -emoticon@^4.0.0, emoticon@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-4.0.1.tgz#2d2bbbf231ce3a5909e185bbb64a9da703a1e749" - integrity sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" - integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^4.2.0, entities@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-module-lexer@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" - integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-goat@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-4.0.0.tgz#9424820331b510b0666b98f7873fe11ac4aa8081" - integrity sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg== - -escape-html@^1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escape-string-regexp@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== - -eslint-scope@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -estree-util-attach-comments@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz#ee44f4ff6890ee7dfb3237ac7810154c94c63f84" - integrity sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w== - dependencies: - "@types/estree" "^1.0.0" - -estree-util-attach-comments@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz#344bde6a64c8a31d15231e5ee9e297566a691c2d" - integrity sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw== - dependencies: - "@types/estree" "^1.0.0" - -estree-util-build-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz#b6d0bced1dcc4f06f25cf0ceda2b2dcaf98168f1" - integrity sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ== - dependencies: - "@types/estree-jsx" "^1.0.0" - devlop "^1.0.0" - estree-util-is-identifier-name "^3.0.0" - estree-walker "^3.0.0" - -estree-util-is-identifier-name@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz#fb70a432dcb19045e77b05c8e732f1364b4b49b2" - integrity sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ== - -estree-util-is-identifier-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" - integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== - -estree-util-to-js@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz#0f80d42443e3b13bd32f7012fffa6f93603f4a36" - integrity sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA== - dependencies: - "@types/estree-jsx" "^1.0.0" - astring "^1.8.0" - source-map "^0.7.0" - -estree-util-to-js@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz#10a6fb924814e6abb62becf0d2bc4dea51d04f17" - integrity sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg== - dependencies: - "@types/estree-jsx" "^1.0.0" - astring "^1.8.0" - source-map "^0.7.0" - -estree-util-value-to-estree@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.1.tgz#a007388eca677510f319603a2f279fed6d104a15" - integrity sha512-5mvUrF2suuv5f5cGDnDphIy4/gW86z82kl5qG6mM9z04SEQI4FB5Apmaw/TGEf3l55nLtMs5s51dmhUzvAHQCA== - dependencies: - "@types/estree" "^1.0.0" - is-plain-obj "^4.0.0" - -estree-util-visit@^1.0.0, estree-util-visit@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-1.2.1.tgz#8bc2bc09f25b00827294703835aabee1cc9ec69d" - integrity sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/unist" "^2.0.0" - -estree-util-visit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-2.0.0.tgz#13a9a9f40ff50ed0c022f831ddf4b58d05446feb" - integrity sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/unist" "^3.0.0" - -estree-walker@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" - integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== - dependencies: - "@types/estree" "^1.0.0" - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eta@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eta/-/eta-2.2.0.tgz#eb8b5f8c4e8b6306561a455e62cd7492fe3a9b8a" - integrity sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eval@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.8.tgz#2b903473b8cc1d1989b83a1e7923f883eb357f85" - integrity sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw== - dependencies: - "@types/node" "*" - require-like ">= 0.1.1" - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -express@^4.17.3: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.5.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extract-zip@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-safe-stringify@^2.0.6: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== - dependencies: - punycode "^1.3.2" - -fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== - dependencies: - reusify "^1.0.4" - -fault@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" - integrity sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ== - dependencies: - format "^0.2.0" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - -feed@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" - integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== - dependencies: - xml-js "^1.6.11" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -filesize@^8.0.6: - version "8.0.7" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" - integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-cache-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" - integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== - dependencies: - common-path-prefix "^3.0.0" - pkg-dir "^7.0.0" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^6.1.0, find-up@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -follow-redirects@^1.0.0: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== - -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.3" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3" - integrity sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ== - dependencies: - "@babel/code-frame" "^7.8.3" - "@types/json-schema" "^7.0.5" - chalk "^4.1.0" - chokidar "^3.4.2" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - glob "^7.1.6" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "2.7.0" - semver "^7.3.2" - tapable "^1.0.0" - -form-data-encoder@^2.1.2: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" - integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== - -format@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" - integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fraction.js@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" - integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fs-extra@^11.1.1: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" - integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-monkey@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" - integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -gemoji@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/gemoji/-/gemoji-7.1.0.tgz#165403777681a9690d649aabd104da037bdd7739" - integrity sha512-wI0YWDIfQraQMDs0yXAVQiVBZeMm/rIYssf8LZlMDdssKF19YqJKOHkv4zvwtVQTBJ0LNmErv1S+DqlVUudz8g== - -gemoji@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/gemoji/-/gemoji-8.1.0.tgz#3d47a26e569c51efa95198822a6f483d7a7ae600" - integrity sha512-HA4Gx59dw2+tn+UAa7XEV4ufUKI4fH1KgcbenVA9YKSj1QJTT0xh5Mwv5HMFNN3l2OtUe3ZIfuRwSyZS5pLIWw== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0, get-stream@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -github-slugger@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d" - integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" - integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== - dependencies: - ini "2.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^11.0.0, globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^13.1.1: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -got@^12.1.0: - version "12.6.1" - resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" - integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== - dependencies: - "@sindresorhus/is" "^5.2.0" - "@szmarczak/http-timer" "^5.0.1" - cacheable-lookup "^7.0.0" - cacheable-request "^10.2.8" - decompress-response "^6.0.0" - form-data-encoder "^2.1.2" - get-stream "^6.0.1" - http2-wrapper "^2.1.10" - lowercase-keys "^3.0.0" - p-cancelable "^3.0.0" - responselike "^3.0.0" - -graceful-fs@4.2.10: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -gray-matter@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" - integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== - dependencies: - js-yaml "^3.13.1" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-yarn@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-3.0.0.tgz#c3c21e559730d1d3b57e28af1f30d06fac38147d" - integrity sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA== - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hast-util-from-html@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz#2482fd701b2d8270b912b3909d6fb645d4a346cf" - integrity sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A== - dependencies: - "@types/hast" "^2.0.0" - hast-util-from-parse5 "^7.0.0" - parse5 "^7.0.0" - vfile "^5.0.0" - vfile-message "^3.0.0" - -hast-util-from-parse5@^7.0.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz#aecfef73e3ceafdfa4550716443e4eb7b02e22b0" - integrity sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw== - dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" - hastscript "^7.0.0" - property-information "^6.0.0" - vfile "^5.0.0" - vfile-location "^4.0.0" - web-namespaces "^2.0.0" - -hast-util-from-parse5@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz#654a5676a41211e14ee80d1b1758c399a0327651" - integrity sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ== - dependencies: - "@types/hast" "^3.0.0" - "@types/unist" "^3.0.0" - devlop "^1.0.0" - hastscript "^8.0.0" - property-information "^6.0.0" - vfile "^6.0.0" - vfile-location "^5.0.0" - web-namespaces "^2.0.0" - -hast-util-parse-selector@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz#25ab00ae9e75cbc62cf7a901f68a247eade659e2" - integrity sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA== - dependencies: - "@types/hast" "^2.0.0" - -hast-util-parse-selector@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz#352879fa86e25616036037dd8931fb5f34cb4a27" - integrity sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A== - dependencies: - "@types/hast" "^3.0.0" - -hast-util-raw@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.0.2.tgz#39b4a4886bd9f0a5dd42e86d02c966c2c152884c" - integrity sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA== - dependencies: - "@types/hast" "^3.0.0" - "@types/unist" "^3.0.0" - "@ungap/structured-clone" "^1.0.0" - hast-util-from-parse5 "^8.0.0" - hast-util-to-parse5 "^8.0.0" - html-void-elements "^3.0.0" - mdast-util-to-hast "^13.0.0" - parse5 "^7.0.0" - unist-util-position "^5.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" - web-namespaces "^2.0.0" - zwitch "^2.0.0" - -hast-util-to-estree@^2.1.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz#da60142ffe19a6296923ec222aba73339c8bf470" - integrity sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ== - dependencies: - "@types/estree" "^1.0.0" - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" - comma-separated-tokens "^2.0.0" - estree-util-attach-comments "^2.0.0" - estree-util-is-identifier-name "^2.0.0" - hast-util-whitespace "^2.0.0" - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdxjs-esm "^1.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^0.4.1" - unist-util-position "^4.0.0" - zwitch "^2.0.0" - -hast-util-to-estree@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz#f2afe5e869ddf0cf690c75f9fc699f3180b51b19" - integrity sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw== - dependencies: - "@types/estree" "^1.0.0" - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^3.0.0" - comma-separated-tokens "^2.0.0" - devlop "^1.0.0" - estree-util-attach-comments "^3.0.0" - estree-util-is-identifier-name "^3.0.0" - hast-util-whitespace "^3.0.0" - mdast-util-mdx-expression "^2.0.0" - mdast-util-mdx-jsx "^3.0.0" - mdast-util-mdxjs-esm "^2.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^0.4.0" - unist-util-position "^5.0.0" - zwitch "^2.0.0" - -hast-util-to-jsx-runtime@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz#3ed27caf8dc175080117706bf7269404a0aa4f7c" - integrity sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ== - dependencies: - "@types/estree" "^1.0.0" - "@types/hast" "^3.0.0" - "@types/unist" "^3.0.0" - comma-separated-tokens "^2.0.0" - devlop "^1.0.0" - estree-util-is-identifier-name "^3.0.0" - hast-util-whitespace "^3.0.0" - mdast-util-mdx-expression "^2.0.0" - mdast-util-mdx-jsx "^3.0.0" - mdast-util-mdxjs-esm "^2.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^1.0.0" - unist-util-position "^5.0.0" - vfile-message "^4.0.0" - -hast-util-to-parse5@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz#477cd42d278d4f036bc2ea58586130f6f39ee6ed" - integrity sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw== - dependencies: - "@types/hast" "^3.0.0" - comma-separated-tokens "^2.0.0" - devlop "^1.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - web-namespaces "^2.0.0" - zwitch "^2.0.0" - -hast-util-whitespace@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557" - integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng== - -hast-util-whitespace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" - integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== - dependencies: - "@types/hast" "^3.0.0" - -hastscript@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.2.0.tgz#0eafb7afb153d047077fa2a833dc9b7ec604d10b" - integrity sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw== - dependencies: - "@types/hast" "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-parse-selector "^3.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - -hastscript@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-8.0.0.tgz#4ef795ec8dee867101b9f23cc830d4baf4fd781a" - integrity sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw== - dependencies: - "@types/hast" "^3.0.0" - comma-separated-tokens "^2.0.0" - hast-util-parse-selector "^4.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -heap@^0.2.6: - version "0.2.7" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" - integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== - -highcharts-react-official@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/highcharts-react-official/-/highcharts-react-official-3.2.1.tgz#4b62a7af2969bdebde6b338d36f6b9bf1f1029bc" - integrity sha512-hyQTX7ezCxl7JqumaWiGsroGWalzh24GedQIgO3vJbkGOZ6ySRAltIYjfxhrq4HszJOySZegotEF7v+haQ75UA== - -highcharts@^11.4.1: - version "11.4.1" - resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-11.4.1.tgz#e40e97c4ea61a10389da75bff0cdb8f83bdb57e1" - integrity sha512-t+BjB4hba5rNheczCrpyDz8BJrqGdgECHaaXQrgbf1mRdPMPemlOfo08/kTMgZ/Kp/Xfj015atdXpUFdwUU12Q== - -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hoist-non-react-statics@^3.1.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -htm@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/htm/-/htm-3.1.1.tgz#49266582be0dc66ed2235d5ea892307cc0c24b78" - integrity sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ== - -html-entities@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== - -html-escaper@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-minifier-terser@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942" - integrity sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA== - dependencies: - camel-case "^4.1.2" - clean-css "~5.3.2" - commander "^10.0.0" - entities "^4.4.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.15.1" - -html-tags@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" - integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== - -html-void-elements@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" - integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== - -html-webpack-plugin@^5.5.3: - version "5.6.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" - integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== - dependencies: - "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -htmlparser2@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" - integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - entities "^4.4.0" - -http-cache-semantics@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== - -http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== - dependencies: - "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http2-wrapper@^2.1.10: - version "2.2.1" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" - integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.2.0" - -https-proxy-agent@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@0.6: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0, ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== - -image-size@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.1.1.tgz#ddd67d4dc340e52ac29ce5f546a09f4e29e840ac" - integrity sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ== - dependencies: - queue "6.0.2" - -immer@^9.0.7: - version "9.0.21" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" - integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== - -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-lazy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" - integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infima@0.2.0-alpha.43: - version "0.2.0-alpha.43" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.43.tgz#f7aa1d7b30b6c08afef441c726bac6150228cbe0" - integrity sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== - -inline-style-parser@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.3.tgz#e35c5fb45f3a83ed7849fe487336eb7efa25971c" - integrity sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g== - -"internmap@1 - 2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" - integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== - -internmap@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" - integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== - -is-alphabetical@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" - integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== - -is-alphanumerical@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" - integrity sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw== - dependencies: - is-alphabetical "^2.0.0" - is-decimal "^2.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-ci@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" - integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== - dependencies: - ci-info "^3.2.0" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-decimal@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" - integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" - integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== - -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-npm@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261" - integrity sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-obj@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-reference@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.2.tgz#154747a01f45cd962404ee89d43837af2cba247c" - integrity sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg== - dependencies: - "@types/estree" "*" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== - -is-root@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -is-yarn-global@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.4.1.tgz#b312d902b313f81e4eaf98b6361ba2b45cd694bb" - integrity sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.1.2: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jiti@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== - -joi@^17.9.2: - version "17.12.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.3.tgz#944646979cd3b460178547b12ba37aca8482f63d" - integrity sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1, js-yaml@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json5@^2.1.2, json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/jsonc/-/jsonc-2.0.0.tgz#9e2a25100d164a9bb864c57517563717fa882551" - integrity sha512-B281bLCT2TRMQa+AQUQY5AGcqSOXBOKaYGP4wDzoA/+QswUfN8sODektbPEs9Baq7LGKun5jQbNFpzwGuVYKhw== - dependencies: - fast-safe-stringify "^2.0.6" - graceful-fs "^4.1.15" - mkdirp "^0.5.1" - parse-json "^4.0.0" - strip-bom "^4.0.0" - strip-json-comments "^3.0.1" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -junit-report-builder@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/junit-report-builder/-/junit-report-builder-3.1.0.tgz#3a806c62aef81ca4a630c957340c0f16010d8ebd" - integrity sha512-uKcPKbjl/v3pqQUuQuCehmuObAb9adZiZleKp0JijMmKPpBh5rl9YvyPjVqzaLkA0dROnMnQvjXQF37VbYoofw== - dependencies: - date-format "4.0.3" - lodash "^4.17.21" - make-dir "^3.1.0" - xmlbuilder "^15.1.1" - -katex@^0.16.9: - version "0.16.10" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" - integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== - dependencies: - commander "^8.3.0" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -khroma@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" - integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -kleur@^4.0.3: - version "4.1.5" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" - integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== - -latest-version@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" - integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== - dependencies: - package-json "^8.1.0" - -launch-editor@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" - integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== - dependencies: - picocolors "^1.0.0" - shell-quote "^1.8.1" - -layout-base@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" - integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lilconfig@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" - integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -locate-path@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - -lodash-es@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" - integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.padend@^4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" - integrity sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw== - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== - -lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -longest-streak@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" - integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lowercase-keys@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" - integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lunr-languages@^1.4.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.14.0.tgz#6e97635f434631729dd0e5654daedd291cd6f2d0" - integrity sha512-hWUAb2KqM3L7J5bcrngszzISY4BxrXn/Xhbb9TTCJYEGqlR1nG67/M14sp09+PTIRklobrn57IAxcdcO/ZFyNA== - -make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -mark.js@^8.11.1: - version "8.11.1" - resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" - integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== - -markdown-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-2.0.0.tgz#34bebc83e9938cae16e0e017e4a9814a8330d3c4" - integrity sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q== - -markdown-table@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" - integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== - -mdast-util-directive@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz#3fb1764e705bbdf0afb0d3f889e4404c3e82561f" - integrity sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q== - dependencies: - "@types/mdast" "^4.0.0" - "@types/unist" "^3.0.0" - devlop "^1.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - parse-entities "^4.0.0" - stringify-entities "^4.0.0" - unist-util-visit-parents "^6.0.0" - -mdast-util-find-and-replace@^3.0.0, mdast-util-find-and-replace@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz#a6fc7b62f0994e973490e45262e4bc07607b04e0" - integrity sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA== - dependencies: - "@types/mdast" "^4.0.0" - escape-string-regexp "^5.0.0" - unist-util-is "^6.0.0" - unist-util-visit-parents "^6.0.0" - -mdast-util-from-markdown@^1.0.0, mdast-util-from-markdown@^1.1.0, mdast-util-from-markdown@^1.2.0, mdast-util-from-markdown@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" - integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== - dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - decode-named-character-reference "^1.0.0" - mdast-util-to-string "^3.1.0" - micromark "^3.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-decode-string "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-stringify-position "^3.0.0" - uvu "^0.5.0" - -mdast-util-from-markdown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz#52f14815ec291ed061f2922fd14d6689c810cb88" - integrity sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA== - dependencies: - "@types/mdast" "^4.0.0" - "@types/unist" "^3.0.0" - decode-named-character-reference "^1.0.0" - devlop "^1.0.0" - mdast-util-to-string "^4.0.0" - micromark "^4.0.0" - micromark-util-decode-numeric-character-reference "^2.0.0" - micromark-util-decode-string "^2.0.0" - micromark-util-normalize-identifier "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - unist-util-stringify-position "^4.0.0" - -mdast-util-frontmatter@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz#79c46d7414eb9d3acabe801ee4a70a70b75e5af1" - integrity sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-extension-frontmatter "^1.0.0" - -mdast-util-frontmatter@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz#f5f929eb1eb36c8a7737475c7eb438261f964ee8" - integrity sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA== - dependencies: - "@types/mdast" "^4.0.0" - devlop "^1.0.0" - escape-string-regexp "^5.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - micromark-extension-frontmatter "^2.0.0" - -mdast-util-gfm-autolink-literal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz#5baf35407421310a08e68c15e5d8821e8898ba2a" - integrity sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg== - dependencies: - "@types/mdast" "^4.0.0" - ccount "^2.0.0" - devlop "^1.0.0" - mdast-util-find-and-replace "^3.0.0" - micromark-util-character "^2.0.0" - -mdast-util-gfm-footnote@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz#25a1753c7d16db8bfd53cd84fe50562bd1e6d6a9" - integrity sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ== - dependencies: - "@types/mdast" "^4.0.0" - devlop "^1.1.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - micromark-util-normalize-identifier "^2.0.0" - -mdast-util-gfm-strikethrough@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz#d44ef9e8ed283ac8c1165ab0d0dfd058c2764c16" - integrity sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-gfm-table@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz#7a435fb6223a72b0862b33afbd712b6dae878d38" - integrity sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg== - dependencies: - "@types/mdast" "^4.0.0" - devlop "^1.0.0" - markdown-table "^3.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-gfm-task-list-item@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz#e68095d2f8a4303ef24094ab642e1047b991a936" - integrity sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ== - dependencies: - "@types/mdast" "^4.0.0" - devlop "^1.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-gfm@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz#3f2aecc879785c3cb6a81ff3a243dc11eca61095" - integrity sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw== - dependencies: - mdast-util-from-markdown "^2.0.0" - mdast-util-gfm-autolink-literal "^2.0.0" - mdast-util-gfm-footnote "^2.0.0" - mdast-util-gfm-strikethrough "^2.0.0" - mdast-util-gfm-table "^2.0.0" - mdast-util-gfm-task-list-item "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-mdx-expression@^1.0.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz#d027789e67524d541d6de543f36d51ae2586f220" - integrity sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-mdx-expression@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz#4968b73724d320a379110d853e943a501bfd9d87" - integrity sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - devlop "^1.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-mdx-jsx@^2.0.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz#7c1f07f10751a78963cfabee38017cbc8b7786d1" - integrity sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - ccount "^2.0.0" - mdast-util-from-markdown "^1.1.0" - mdast-util-to-markdown "^1.3.0" - parse-entities "^4.0.0" - stringify-entities "^4.0.0" - unist-util-remove-position "^4.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" - -mdast-util-mdx-jsx@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz#daae777c72f9c4a106592e3025aa50fb26068e1b" - integrity sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - "@types/unist" "^3.0.0" - ccount "^2.0.0" - devlop "^1.1.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - parse-entities "^4.0.0" - stringify-entities "^4.0.0" - unist-util-remove-position "^5.0.0" - unist-util-stringify-position "^4.0.0" - vfile-message "^4.0.0" - -mdast-util-mdx@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz#49b6e70819b99bb615d7223c088d295e53bb810f" - integrity sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw== - dependencies: - mdast-util-from-markdown "^1.0.0" - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdx-jsx "^2.0.0" - mdast-util-mdxjs-esm "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-mdx@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz#792f9cf0361b46bee1fdf1ef36beac424a099c41" - integrity sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w== - dependencies: - mdast-util-from-markdown "^2.0.0" - mdast-util-mdx-expression "^2.0.0" - mdast-util-mdx-jsx "^3.0.0" - mdast-util-mdxjs-esm "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-mdxjs-esm@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz#645d02cd607a227b49721d146fd81796b2e2d15b" - integrity sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-mdxjs-esm@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" - integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== - dependencies: - "@types/estree-jsx" "^1.0.0" - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - devlop "^1.0.0" - mdast-util-from-markdown "^2.0.0" - mdast-util-to-markdown "^2.0.0" - -mdast-util-phrasing@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz#c7c21d0d435d7fb90956038f02e8702781f95463" - integrity sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg== - dependencies: - "@types/mdast" "^3.0.0" - unist-util-is "^5.0.0" - -mdast-util-phrasing@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" - integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== - dependencies: - "@types/mdast" "^4.0.0" - unist-util-is "^6.0.0" - -mdast-util-to-hast@^13.0.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz#1ae54d903150a10fe04d59f03b2b95fd210b2124" - integrity sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA== - dependencies: - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - "@ungap/structured-clone" "^1.0.0" - devlop "^1.0.0" - micromark-util-sanitize-uri "^2.0.0" - trim-lines "^3.0.0" - unist-util-position "^5.0.0" - unist-util-visit "^5.0.0" - vfile "^6.0.0" - -mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz#c13343cb3fc98621911d33b5cd42e7d0731171c6" - integrity sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A== - dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - longest-streak "^3.0.0" - mdast-util-phrasing "^3.0.0" - mdast-util-to-string "^3.0.0" - micromark-util-decode-string "^1.0.0" - unist-util-visit "^4.0.0" - zwitch "^2.0.0" - -mdast-util-to-markdown@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz#9813f1d6e0cdaac7c244ec8c6dabfdb2102ea2b4" - integrity sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ== - dependencies: - "@types/mdast" "^4.0.0" - "@types/unist" "^3.0.0" - longest-streak "^3.0.0" - mdast-util-phrasing "^4.0.0" - mdast-util-to-string "^4.0.0" - micromark-util-decode-string "^2.0.0" - unist-util-visit "^5.0.0" - zwitch "^2.0.0" - -mdast-util-to-nlcst@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/mdast-util-to-nlcst/-/mdast-util-to-nlcst-5.2.1.tgz#2f5c70d99982ab8b4b9e371023b783345c69eafe" - integrity sha512-Xznpj85MsJnLQjBboajOovT2fAAvbbbmYutpFgzLi9pjZEOkgGzjq+t6fHcge8uzZ5uEkj5pigzw2QrnIVq/kw== - dependencies: - "@types/mdast" "^3.0.0" - "@types/nlcst" "^1.0.0" - "@types/unist" "^2.0.0" - nlcst-to-string "^3.0.0" - unist-util-position "^4.0.0" - vfile "^5.0.0" - vfile-location "^4.0.0" - -mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" - integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== - dependencies: - "@types/mdast" "^3.0.0" - -mdast-util-to-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" - integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== - dependencies: - "@types/mdast" "^4.0.0" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdx-mermaid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdx-mermaid/-/mdx-mermaid-2.0.0.tgz#0bc73b31615810f5f52d0031b641a859fa30de7d" - integrity sha512-vmkh4yg/EgkhAWxdFsyol5Tgk9aTnM16njgGIYk3R3SdbejPt8YV+HRYycAOstR1TJefMNAmjAyqkRjukLP7qg== - optionalDependencies: - estree-util-to-js "^1.1.0" - estree-util-visit "^1.2.0" - hast-util-from-html "^1.0.1" - hast-util-to-estree "^2.1.0" - mdast-util-from-markdown "^1.2.0" - mdast-util-mdx "^2.0.0" - micromark-extension-mdxjs "^1.0.0" - puppeteer "^18.0.0" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -memfs@^3.1.2, memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== - dependencies: - fs-monkey "^1.0.4" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -mermaid@^10.9.0: - version "10.9.0" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.9.0.tgz#4d1272fbe434bd8f3c2c150554dc8a23a9bf9361" - integrity sha512-swZju0hFox/B/qoLKK0rOxxgh8Cf7rJSfAUc1u8fezVihYMvrJAS45GzAxTVf4Q+xn9uMgitBcmWk7nWGXOs/g== - dependencies: - "@braintree/sanitize-url" "^6.0.1" - "@types/d3-scale" "^4.0.3" - "@types/d3-scale-chromatic" "^3.0.0" - cytoscape "^3.28.1" - cytoscape-cose-bilkent "^4.1.0" - d3 "^7.4.0" - d3-sankey "^0.12.3" - dagre-d3-es "7.0.10" - dayjs "^1.11.7" - dompurify "^3.0.5" - elkjs "^0.9.0" - katex "^0.16.9" - khroma "^2.0.0" - lodash-es "^4.17.21" - mdast-util-from-markdown "^1.3.0" - non-layered-tidy-tree-layout "^2.0.2" - stylis "^4.1.3" - ts-dedent "^2.2.0" - uuid "^9.0.0" - web-worker "^1.2.0" - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" - integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== - dependencies: - decode-named-character-reference "^1.0.0" - micromark-factory-destination "^1.0.0" - micromark-factory-label "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-factory-title "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-html-tag-name "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" - -micromark-core-commonmark@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz#50740201f0ee78c12a675bf3e68ffebc0bf931a3" - integrity sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA== - dependencies: - decode-named-character-reference "^1.0.0" - devlop "^1.0.0" - micromark-factory-destination "^2.0.0" - micromark-factory-label "^2.0.0" - micromark-factory-space "^2.0.0" - micromark-factory-title "^2.0.0" - micromark-factory-whitespace "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-chunked "^2.0.0" - micromark-util-classify-character "^2.0.0" - micromark-util-html-tag-name "^2.0.0" - micromark-util-normalize-identifier "^2.0.0" - micromark-util-resolve-all "^2.0.0" - micromark-util-subtokenize "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-directive@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-directive/-/micromark-extension-directive-3.0.0.tgz#527869de497a6de9024138479091bc885dae076b" - integrity sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg== - dependencies: - devlop "^1.0.0" - micromark-factory-space "^2.0.0" - micromark-factory-whitespace "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - parse-entities "^4.0.0" - -micromark-extension-frontmatter@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz#2946643938e491374145d0c9aacc3249e38a865f" - integrity sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ== - dependencies: - fault "^2.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-extension-frontmatter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz#651c52ffa5d7a8eeed687c513cd869885882d67a" - integrity sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg== - dependencies: - fault "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm-autolink-literal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz#f1e50b42e67d441528f39a67133eddde2bbabfd9" - integrity sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-sanitize-uri "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm-footnote@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz#91afad310065a94b636ab1e9dab2c60d1aab953c" - integrity sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg== - dependencies: - devlop "^1.0.0" - micromark-core-commonmark "^2.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-normalize-identifier "^2.0.0" - micromark-util-sanitize-uri "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm-strikethrough@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz#6917db8e320da70e39ffbf97abdbff83e6783e61" - integrity sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw== - dependencies: - devlop "^1.0.0" - micromark-util-chunked "^2.0.0" - micromark-util-classify-character "^2.0.0" - micromark-util-resolve-all "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm-table@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz#2cf3fe352d9e089b7ef5fff003bdfe0da29649b7" - integrity sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw== - dependencies: - devlop "^1.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm-tagfilter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz#f26d8a7807b5985fba13cf61465b58ca5ff7dc57" - integrity sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg== - dependencies: - micromark-util-types "^2.0.0" - -micromark-extension-gfm-task-list-item@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz#ee8b208f1ced1eb9fb11c19a23666e59d86d4838" - integrity sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw== - dependencies: - devlop "^1.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-gfm@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz#3e13376ab95dd7a5cfd0e29560dfe999657b3c5b" - integrity sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w== - dependencies: - micromark-extension-gfm-autolink-literal "^2.0.0" - micromark-extension-gfm-footnote "^2.0.0" - micromark-extension-gfm-strikethrough "^2.0.0" - micromark-extension-gfm-table "^2.0.0" - micromark-extension-gfm-tagfilter "^2.0.0" - micromark-extension-gfm-task-list-item "^2.0.0" - micromark-util-combine-extensions "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-mdx-expression@^1.0.0: - version "1.0.8" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz#5bc1f5fd90388e8293b3ef4f7c6f06c24aff6314" - integrity sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw== - dependencies: - "@types/estree" "^1.0.0" - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-mdx-expression@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz#1407b9ce69916cf5e03a196ad9586889df25302a" - integrity sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ== - dependencies: - "@types/estree" "^1.0.0" - devlop "^1.0.0" - micromark-factory-mdx-expression "^2.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-events-to-acorn "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-extension-mdx-jsx@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz#e72d24b7754a30d20fb797ece11e2c4e2cae9e82" - integrity sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA== - dependencies: - "@types/acorn" "^4.0.0" - "@types/estree" "^1.0.0" - estree-util-is-identifier-name "^2.0.0" - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-extension-mdx-jsx@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz#4aba0797c25efb2366a3fd2d367c6b1c1159f4f5" - integrity sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w== - dependencies: - "@types/acorn" "^4.0.0" - "@types/estree" "^1.0.0" - devlop "^1.0.0" - estree-util-is-identifier-name "^3.0.0" - micromark-factory-mdx-expression "^2.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - vfile-message "^4.0.0" - -micromark-extension-mdx-md@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz#595d4b2f692b134080dca92c12272ab5b74c6d1a" - integrity sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA== - dependencies: - micromark-util-types "^1.0.0" - -micromark-extension-mdx-md@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz#1d252881ea35d74698423ab44917e1f5b197b92d" - integrity sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ== - dependencies: - micromark-util-types "^2.0.0" - -micromark-extension-mdxjs-esm@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz#e4f8be9c14c324a80833d8d3a227419e2b25dec1" - integrity sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w== - dependencies: - "@types/estree" "^1.0.0" - micromark-core-commonmark "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.1.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-extension-mdxjs-esm@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz#de21b2b045fd2059bd00d36746081de38390d54a" - integrity sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A== - dependencies: - "@types/estree" "^1.0.0" - devlop "^1.0.0" - micromark-core-commonmark "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-events-to-acorn "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - unist-util-position-from-estree "^2.0.0" - vfile-message "^4.0.0" - -micromark-extension-mdxjs@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz#f78d4671678d16395efeda85170c520ee795ded8" - integrity sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q== - dependencies: - acorn "^8.0.0" - acorn-jsx "^5.0.0" - micromark-extension-mdx-expression "^1.0.0" - micromark-extension-mdx-jsx "^1.0.0" - micromark-extension-mdx-md "^1.0.0" - micromark-extension-mdxjs-esm "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-extension-mdxjs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz#b5a2e0ed449288f3f6f6c544358159557549de18" - integrity sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ== - dependencies: - acorn "^8.0.0" - acorn-jsx "^5.0.0" - micromark-extension-mdx-expression "^3.0.0" - micromark-extension-mdx-jsx "^3.0.0" - micromark-extension-mdx-md "^2.0.0" - micromark-extension-mdxjs-esm "^3.0.0" - micromark-util-combine-extensions "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-factory-destination@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" - integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-factory-destination@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz#857c94debd2c873cba34e0445ab26b74f6a6ec07" - integrity sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-factory-label@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" - integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-factory-label@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz#17c5c2e66ce39ad6f4fc4cbf40d972f9096f726a" - integrity sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw== - dependencies: - devlop "^1.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-factory-mdx-expression@^1.0.0: - version "1.0.9" - resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz#57ba4571b69a867a1530f34741011c71c73a4976" - integrity sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA== - dependencies: - "@types/estree" "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-factory-mdx-expression@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz#f2a9724ce174f1751173beb2c1f88062d3373b1b" - integrity sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg== - dependencies: - "@types/estree" "^1.0.0" - devlop "^1.0.0" - micromark-util-character "^2.0.0" - micromark-util-events-to-acorn "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - unist-util-position-from-estree "^2.0.0" - vfile-message "^4.0.0" - -micromark-factory-space@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" - integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-factory-space@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz#5e7afd5929c23b96566d0e1ae018ae4fcf81d030" - integrity sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-factory-title@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" - integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== - dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-factory-title@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz#726140fc77892af524705d689e1cf06c8a83ea95" - integrity sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A== - dependencies: - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-factory-whitespace@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" - integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== - dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-factory-whitespace@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz#9e92eb0f5468083381f923d9653632b3cfb5f763" - integrity sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA== - dependencies: - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-character@^1.0.0, micromark-util-character@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" - integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== - dependencies: - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-util-character@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" - integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== - dependencies: - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-chunked@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" - integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== - dependencies: - micromark-util-symbol "^1.0.0" - -micromark-util-chunked@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz#e51f4db85fb203a79dbfef23fd41b2f03dc2ef89" - integrity sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg== - dependencies: - micromark-util-symbol "^2.0.0" - -micromark-util-classify-character@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" - integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-util-classify-character@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz#8c7537c20d0750b12df31f86e976d1d951165f34" - integrity sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-combine-extensions@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" - integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== - dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-util-combine-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz#75d6ab65c58b7403616db8d6b31315013bfb7ee5" - integrity sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ== - dependencies: - micromark-util-chunked "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-decode-numeric-character-reference@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" - integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== - dependencies: - micromark-util-symbol "^1.0.0" - -micromark-util-decode-numeric-character-reference@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz#2698bbb38f2a9ba6310e359f99fcb2b35a0d2bd5" - integrity sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ== - dependencies: - micromark-util-symbol "^2.0.0" - -micromark-util-decode-string@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" - integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== - dependencies: - decode-named-character-reference "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-symbol "^1.0.0" - -micromark-util-decode-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz#7dfa3a63c45aecaa17824e656bcdb01f9737154a" - integrity sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA== - dependencies: - decode-named-character-reference "^1.0.0" - micromark-util-character "^2.0.0" - micromark-util-decode-numeric-character-reference "^2.0.0" - micromark-util-symbol "^2.0.0" - -micromark-util-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" - integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== - -micromark-util-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" - integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== - -micromark-util-events-to-acorn@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz#a4ab157f57a380e646670e49ddee97a72b58b557" - integrity sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w== - dependencies: - "@types/acorn" "^4.0.0" - "@types/estree" "^1.0.0" - "@types/unist" "^2.0.0" - estree-util-visit "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" - -micromark-util-events-to-acorn@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz#4275834f5453c088bd29cd72dfbf80e3327cec07" - integrity sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA== - dependencies: - "@types/acorn" "^4.0.0" - "@types/estree" "^1.0.0" - "@types/unist" "^3.0.0" - devlop "^1.0.0" - estree-util-visit "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - vfile-message "^4.0.0" - -micromark-util-html-tag-name@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" - integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== - -micromark-util-html-tag-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz#ae34b01cbe063363847670284c6255bb12138ec4" - integrity sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw== - -micromark-util-normalize-identifier@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" - integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== - dependencies: - micromark-util-symbol "^1.0.0" - -micromark-util-normalize-identifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz#91f9a4e65fe66cc80c53b35b0254ad67aa431d8b" - integrity sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w== - dependencies: - micromark-util-symbol "^2.0.0" - -micromark-util-resolve-all@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" - integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== - dependencies: - micromark-util-types "^1.0.0" - -micromark-util-resolve-all@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz#189656e7e1a53d0c86a38a652b284a252389f364" - integrity sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA== - dependencies: - micromark-util-types "^2.0.0" - -micromark-util-sanitize-uri@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" - integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-symbol "^1.0.0" - -micromark-util-sanitize-uri@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" - integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== - dependencies: - micromark-util-character "^2.0.0" - micromark-util-encode "^2.0.0" - micromark-util-symbol "^2.0.0" - -micromark-util-subtokenize@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" - integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== - dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-util-subtokenize@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz#9f412442d77e0c5789ffdf42377fa8a2bcbdf581" - integrity sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg== - dependencies: - devlop "^1.0.0" - micromark-util-chunked "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromark-util-symbol@^1.0.0, micromark-util-symbol@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" - integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== - -micromark-util-symbol@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" - integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== - -micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" - integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== - -micromark-util-types@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" - integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== - -micromark@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" - integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== - dependencies: - "@types/debug" "^4.0.0" - debug "^4.0.0" - decode-named-character-reference "^1.0.0" - micromark-core-commonmark "^1.0.1" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" - -micromark@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.0.tgz#84746a249ebd904d9658cfabc1e8e5f32cbc6249" - integrity sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ== - dependencies: - "@types/debug" "^4.0.0" - debug "^4.0.0" - decode-named-character-reference "^1.0.0" - devlop "^1.0.0" - micromark-core-commonmark "^2.0.0" - micromark-factory-space "^2.0.0" - micromark-util-character "^2.0.0" - micromark-util-chunked "^2.0.0" - micromark-util-combine-extensions "^2.0.0" - micromark-util-decode-numeric-character-reference "^2.0.0" - micromark-util-encode "^2.0.0" - micromark-util-normalize-identifier "^2.0.0" - micromark-util-resolve-all "^2.0.0" - micromark-util-sanitize-uri "^2.0.0" - micromark-util-subtokenize "^2.0.0" - micromark-util-symbol "^2.0.0" - micromark-util-types "^2.0.0" - -micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -mimic-response@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" - integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== - -mini-css-extract-plugin@^2.7.6: - version "2.8.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz#75245f3f30ce3a56dbdd478084df6fe475f02dc7" - integrity sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA== - dependencies: - schema-utils "^4.0.0" - tapable "^2.2.1" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - -mkdirp@^0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mri@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" - integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== - -mrmime@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" - integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns@^7.2.5: - version "7.2.5" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" - integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== - dependencies: - dns-packet "^5.2.2" - thunky "^1.0.2" - -nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nlcst-affix-emoticon-modifier@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nlcst-affix-emoticon-modifier/-/nlcst-affix-emoticon-modifier-2.1.1.tgz#0fdadc46651e524731e116c0e9dda0af5abda3b0" - integrity sha512-0kOpSNwB6pFMoe5tWFZ3KrvW6ftVqvnXW+jQw3EJnXkzXdAmdhbcoG9r+NMvJ0nc37BLYlEy5A+FGlB8IOfq5A== - dependencies: - "@types/nlcst" "^1.0.0" - "@types/unist" "^2.0.0" - nlcst-emoticon-modifier "^2.0.0" - unist-util-modify-children "^3.0.0" - -nlcst-emoji-modifier@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/nlcst-emoji-modifier/-/nlcst-emoji-modifier-5.2.0.tgz#b8162d56be922ddf53f6f51c477b655b5b8e17e4" - integrity sha512-bxgOEDWN2hz6/JN0uiIww+28Ssktq9FRctHq3bxiBi/8G/mb72cQ99vhzrZMWZe8tKD3YYckVH1bEkzcxTJFxg== - dependencies: - "@types/nlcst" "^1.0.0" - emoji-regex "^10.0.0" - gemoji "^8.0.0" - nlcst-emoticon-modifier "^2.0.0" - nlcst-to-string "^3.0.0" - unist-util-generated "^2.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" - -nlcst-emoticon-modifier@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nlcst-emoticon-modifier/-/nlcst-emoticon-modifier-2.1.1.tgz#ab912c8175b1ac4ae71052c33c2f067a0494959a" - integrity sha512-fDfvvmA6ziUQC+I3BYLNZ7lq0rIG3Uz6IsmhTAkdB8d9UyI5LPz1uvmk+W7fKkX1mVWGJw0PeOT9VtXISrPFbg== - dependencies: - "@types/nlcst" "^1.0.0" - "@types/unist" "^2.0.0" - emoticon "^4.0.0" - nlcst-to-string "^3.0.0" - unist-util-modify-children "^3.0.0" - -nlcst-is-literal@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nlcst-is-literal/-/nlcst-is-literal-2.1.1.tgz#d3f3feb5b4d2c2c60e63c805813f6373248cb30c" - integrity sha512-/PyEKNHN+SrcrmnZRwszzZYbvZSN2AVD506+rfMUzyFHB0PtUmqZOdUuXmQxQeZXv6o29pT5chLjQJdC9weOCQ== - dependencies: - "@types/nlcst" "^1.0.0" - "@types/unist" "^2.0.0" - nlcst-to-string "^3.0.0" - -nlcst-to-string@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz#83b90f2e1ee2081e14701317efc26d3bbadc806e" - integrity sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw== - dependencies: - "@types/nlcst" "^1.0.0" - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-emoji@^2.1.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" - integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== - dependencies: - "@sindresorhus/is" "^4.6.0" - char-regex "^1.0.2" - emojilib "^2.4.0" - skin-tone "^2.0.0" - -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -non-layered-tidy-tree-layout@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz#57d35d13c356643fc296a55fb11ac15e74da7804" - integrity sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -normalize-url@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a" - integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nprogress@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== - -nspell@^2.0.0: - version "2.1.5" - resolved "https://registry.yarnpkg.com/nspell/-/nspell-2.1.5.tgz#85d51ef71499da72d899f261d7399ea2fc607633" - integrity sha512-PSStyugKMiD9mHmqI/CR5xXrSIGejUXPlo88FBRq5Og1kO5QwQ5Ilu8D8O5I/SHpoS+mibpw6uKA8rd3vXd2Sg== - dependencies: - is-buffer "^2.0.0" - -nth-check@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== - dependencies: - boolbase "^1.0.0" - -number-to-words@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/number-to-words/-/number-to-words-1.2.4.tgz#e0f124de9628f8d86c4eeb89bac6c07699264501" - integrity sha512-/fYevVkXRcyBiZDg6yzZbm0RuaD6i0qRfn8yr+6D0KgBMOndFPxuW10qCHpzs50nN8qKuv78k8MuotZhcVX6Pw== - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^8.0.9, open@^8.4.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -opener@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== - -p-cancelable@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" - integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== - -p-limit@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== - dependencies: - "@types/retry" "0.12.0" - retry "^0.13.1" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" - integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== - dependencies: - got "^12.1.0" - registry-auth-token "^5.0.1" - registry-url "^6.0.0" - semver "^7.3.7" - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-entities@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.1.tgz#4e2a01111fb1c986549b944af39eeda258fc9e4e" - integrity sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w== - dependencies: - "@types/unist" "^2.0.0" - character-entities "^2.0.0" - character-entities-legacy "^3.0.0" - character-reference-invalid "^2.0.0" - decode-named-character-reference "^1.0.0" - is-alphanumerical "^2.0.0" - is-decimal "^2.0.0" - is-hexadecimal "^2.0.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-json@^5.0.0, parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-latin@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/parse-latin/-/parse-latin-5.0.1.tgz#f3b4fac54d06f6a0501cf8b8ecfafa4cbb4f2f47" - integrity sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg== - dependencies: - nlcst-to-string "^3.0.0" - unist-util-modify-children "^3.0.0" - unist-util-visit-children "^2.0.0" - -parse-numeric-range@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" - integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== - -parse5-htmlparser2-tree-adapter@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" - integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== - dependencies: - domhandler "^5.0.2" - parse5 "^7.0.0" - -parse5@^7.0.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" - integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== - dependencies: - entities "^4.4.0" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - -periscopic@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.1.0.tgz#7e9037bf51c5855bd33b48928828db4afa79d97a" - integrity sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^3.0.0" - is-reference "^3.0.0" - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-dir@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-6.0.1.tgz#8ec964cecaef98a2bdb9c164733f90a5bcd2352d" - integrity sha512-C9R+PTCKGA32HG0n5I4JMYkdLL58ZpayVuncQHQrGeKa8o26A4o2x0u6BKekHG+Au0jv5ZW7Xfq1Cj6lm9Ag4w== - dependencies: - find-up "^6.1.0" - -pkg-dir@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" - integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== - dependencies: - find-up "^6.3.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" - integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" - integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== - dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" - integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== - -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== - -postcss-discard-empty@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" - integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== - -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== - -postcss-discard-unused@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" - integrity sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-loader@^7.3.3: - version "7.3.4" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" - integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== - dependencies: - cosmiconfig "^8.3.5" - jiti "^1.20.0" - semver "^7.5.4" - -postcss-merge-idents@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz#7753817c2e0b75d0853b56f78a89771e15ca04a1" - integrity sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw== - dependencies: - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-merge-longhand@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" - integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.1.1" - -postcss-merge-rules@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" - integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" - postcss-selector-parser "^6.0.5" - -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" - integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-minify-params@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" - integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== - dependencies: - browserslist "^4.21.4" - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-minify-selectors@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" - integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-modules-extract-imports@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" - integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== - -postcss-modules-local-by-default@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" - integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" - integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== - -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-positions@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" - integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-repeat-style@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" - integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-unicode@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" - integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== - dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" - -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== - dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" - -postcss-normalize-whitespace@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" - integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-ordered-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" - integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== - dependencies: - cssnano-utils "^3.1.0" - postcss-value-parser "^4.2.0" - -postcss-reduce-idents@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" - integrity sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-reduce-initial@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" - integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.15" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" - integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-sort-media-queries@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz#04a5a78db3921eb78f28a1a781a2e68e65258128" - integrity sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw== - dependencies: - sort-css-media-queries "2.1.0" - -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== - dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" - -postcss-unique-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" - integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss-zindex@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" - integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== - -postcss@^8.4.17, postcss@^8.4.33: - version "8.4.33" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" - integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8.4.21, postcss@^8.4.26: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - -preact@^10.13.2: - version "10.19.3" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.19.3.tgz#7a7107ed2598a60676c943709ea3efb8aaafa899" - integrity sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ== - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - -prism-react-renderer@^2.3.0, prism-react-renderer@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz#e59e5450052ede17488f6bc85de1553f584ff8d5" - integrity sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw== - dependencies: - "@types/prismjs" "^1.26.0" - clsx "^2.0.0" - -prismjs@^1.29.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" - integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prop-types@^15.6.2, prop-types@^15.7.2: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -property-information@^6.0.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" - integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -proxy-from-env@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pupa@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-3.1.0.tgz#f15610274376bbcc70c9a3aa8b505ea23f41c579" - integrity sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug== - dependencies: - escape-goat "^4.0.0" - -puppeteer-core@18.2.1: - version "18.2.1" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-18.2.1.tgz#9b7827bb2bf478bb615e2c21425e4659555dc1fe" - integrity sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw== - dependencies: - cross-fetch "3.1.5" - debug "4.3.4" - devtools-protocol "0.0.1045489" - extract-zip "2.0.1" - https-proxy-agent "5.0.1" - proxy-from-env "1.1.0" - rimraf "3.0.2" - tar-fs "2.1.1" - unbzip2-stream "1.4.3" - ws "8.9.0" - -puppeteer@^18.0.0: - version "18.2.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-18.2.1.tgz#08967cd423efe511ee4c6e3a5c882ffaf2e6bbf3" - integrity sha512-7+UhmYa7wxPh2oMRwA++k8UGVDxh3YdWFB52r9C3tM81T6BU7cuusUSxImz0GEYSOYUKk/YzIhkQ6+vc0gHbxQ== - dependencies: - https-proxy-agent "5.0.1" - progress "2.0.3" - proxy-from-env "1.1.0" - puppeteer-core "18.2.1" - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" - integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== - dependencies: - inherits "~2.0.3" - -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -quotation@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/quotation/-/quotation-2.0.3.tgz#b94c05128209a63b40b4e20e0f8f1a38adea7e0b" - integrity sha512-yEc24TEgCFLXx7D4JHJJkK4JFVtatO8fziwUxY4nB/Jbea9o9CVS3gt22mA0W7rPYAGW2fWzYDSOtD94PwOyqA== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-dev-utils@^12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" - integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ== - dependencies: - "@babel/code-frame" "^7.16.0" - address "^1.1.2" - browserslist "^4.18.1" - chalk "^4.1.2" - cross-spawn "^7.0.3" - detect-port-alt "^1.1.6" - escape-string-regexp "^4.0.0" - filesize "^8.0.6" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.5.0" - global-modules "^2.0.0" - globby "^11.0.4" - gzip-size "^6.0.0" - immer "^9.0.7" - is-root "^2.1.0" - loader-utils "^3.2.0" - open "^8.4.0" - pkg-up "^3.1.0" - prompts "^2.4.2" - react-error-overlay "^6.0.11" - recursive-readdir "^2.2.2" - shell-quote "^1.7.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -react-dom@^18: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-error-overlay@^6.0.11: - version "6.0.11" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" - integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== - -react-fast-compare@^3.2.0, react-fast-compare@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" - integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== - -react-helmet-async@*: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.4.tgz#50a4377778f380ed1d0136303916b38eff1bf153" - integrity sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ== - dependencies: - invariant "^2.2.4" - react-fast-compare "^3.2.2" - shallowequal "^1.1.0" - -react-helmet-async@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" - integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== - dependencies: - "@babel/runtime" "^7.12.5" - invariant "^2.2.4" - prop-types "^15.7.2" - react-fast-compare "^3.2.0" - shallowequal "^1.1.0" - -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-json-view-lite@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-json-view-lite/-/react-json-view-lite-1.3.0.tgz#1f1feee6f1b1d75cc498cd57812f441b88b51e21" - integrity sha512-aN1biKC5v4DQkmQBlZjuMFR09MKZGMPtIg+cut8zEeg2HXd6gl2gRy0n4HMacHf0dznQgo0SVXN7eT8zV3hEuQ== - -react-loadable-ssr-addon-v5-slorber@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" - integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== - dependencies: - "@babel/runtime" "^7.10.3" - -react-router-config@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" - integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== - dependencies: - "@babel/runtime" "^7.1.2" - -react-router-dom@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" - integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== - dependencies: - "@babel/runtime" "^7.12.13" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.3.4" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.3.4, react-router@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" - integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== - dependencies: - "@babel/runtime" "^7.12.13" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react@^18: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -readable-stream@^2.0.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reading-time@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" - integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== - dependencies: - resolve "^1.1.6" - -recursive-readdir@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" - integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== - dependencies: - minimatch "^3.0.5" - -reduce-flatten@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327" - integrity sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ== - -regenerate-unicode-properties@^10.1.0: - version "10.1.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" - integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - -regexpu-core@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" - integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== - dependencies: - "@babel/regjsgen" "^0.8.0" - regenerate "^1.4.2" - regenerate-unicode-properties "^10.1.0" - regjsparser "^0.9.1" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -registry-auth-token@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" - integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== - dependencies: - "@pnpm/npm-conf" "^2.1.0" - -registry-url@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" - integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== - dependencies: - rc "1.2.8" - -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== - dependencies: - jsesc "~0.5.0" - -rehype-raw@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-7.0.0.tgz#59d7348fd5dbef3807bbaa1d443efd2dd85ecee4" - integrity sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww== - dependencies: - "@types/hast" "^3.0.0" - hast-util-raw "^9.0.0" - vfile "^6.0.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== - -remark-directive@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remark-directive/-/remark-directive-3.0.0.tgz#34452d951b37e6207d2e2a4f830dc33442923268" - integrity sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-directive "^3.0.0" - micromark-extension-directive "^3.0.0" - unified "^11.0.0" - -remark-emoji@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-4.0.1.tgz#671bfda668047689e26b2078c7356540da299f04" - integrity sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg== - dependencies: - "@types/mdast" "^4.0.2" - emoticon "^4.0.1" - mdast-util-find-and-replace "^3.0.1" - node-emoji "^2.1.0" - unified "^11.0.4" - -remark-frontmatter@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz#84560f7ccef114ef076d3d3735be6d69f8922309" - integrity sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-frontmatter "^1.0.0" - micromark-extension-frontmatter "^1.0.0" - unified "^10.0.0" - -remark-frontmatter@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz#b68d61552a421ec412c76f4f66c344627dc187a2" - integrity sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-frontmatter "^2.0.0" - micromark-extension-frontmatter "^2.0.0" - unified "^11.0.0" - -remark-gfm@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.0.tgz#aea777f0744701aa288b67d28c43565c7e8c35de" - integrity sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-gfm "^3.0.0" - micromark-extension-gfm "^3.0.0" - remark-parse "^11.0.0" - remark-stringify "^11.0.0" - unified "^11.0.0" - -remark-mdx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.0.1.tgz#8f73dd635c1874e44426e243f72c0977cf60e212" - integrity sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA== - dependencies: - mdast-util-mdx "^3.0.0" - micromark-extension-mdxjs "^3.0.0" - -remark-parse@^10.0.0: - version "10.0.2" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.2.tgz#ca241fde8751c2158933f031a4e3efbaeb8bc262" - integrity sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - unified "^10.0.0" - -remark-parse@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" - integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-from-markdown "^2.0.0" - micromark-util-types "^2.0.0" - unified "^11.0.0" - -remark-rehype@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.0.tgz#d5f264f42bcbd4d300f030975609d01a1697ccdc" - integrity sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g== - dependencies: - "@types/hast" "^3.0.0" - "@types/mdast" "^4.0.0" - mdast-util-to-hast "^13.0.0" - unified "^11.0.0" - vfile "^6.0.0" - -remark-retext@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/remark-retext/-/remark-retext-5.0.1.tgz#f19817f21d54bb273a0efc2007458ac38dd42542" - integrity sha512-h3kOjKNy7oJfohqXlKp+W4YDigHD3rw01x91qvQP/cUkK5nJrDl6yEYwTujQCAXSLZrsBxywlK3ntzIX6c29aA== - dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - mdast-util-to-nlcst "^5.0.0" - unified "^10.0.0" - -remark-stringify@^10.0.0: - version "10.0.3" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-10.0.3.tgz#83b43f2445c4ffbb35b606f967d121b2b6d69717" - integrity sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.0.0" - unified "^10.0.0" - -remark-stringify@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-11.0.0.tgz#4c5b01dd711c269df1aaae11743eb7e2e7636fd3" - integrity sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw== - dependencies: - "@types/mdast" "^4.0.0" - mdast-util-to-markdown "^2.0.0" - unified "^11.0.0" - -remark@^14.0.0: - version "14.0.3" - resolved "https://registry.yarnpkg.com/remark/-/remark-14.0.3.tgz#e477886a7579df612908f387c7753dc93cdaa3fc" - integrity sha512-bfmJW1dmR2LvaMJuAnE88pZP9DktIFYXazkTfOIKZzi3Knk9lT0roItIA24ydOucI3bV/g/tXBA6hzqq3FV9Ew== - dependencies: - "@types/mdast" "^3.0.0" - remark-parse "^10.0.0" - remark-stringify "^10.0.0" - unified "^10.0.0" - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -repeat-string@^1.5.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -replace-ext@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -"require-like@>= 0.1.1": - version "0.1.2" - resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-alpn@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve@^1.1.6, resolve@^1.14.2: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" - integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== - dependencies: - lowercase-keys "^3.0.0" - -retext-emoji@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/retext-emoji/-/retext-emoji-8.1.0.tgz#07dcd9593ead4e928162c493b6df6289bb51246a" - integrity sha512-cvT53Ttn6XXgNprhmI8p4qtwujxNwoHW8hHe2B0JLEMxrMzGTbxwKqnwGslLk/FDsH4dSYStmqnpE20auNSrNg== - dependencies: - "@types/nlcst" "^1.0.0" - emoticon "^4.0.0" - gemoji "^7.0.0" - nlcst-affix-emoticon-modifier "^2.0.0" - nlcst-emoji-modifier "^5.0.0" - nlcst-emoticon-modifier "^2.0.0" - nlcst-to-string "^3.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - -retext-indefinite-article@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/retext-indefinite-article/-/retext-indefinite-article-4.3.0.tgz#9054b79504e883ace978c9ac56cf9119717b8a5d" - integrity sha512-NdVOT0pR68ZhC/Eph/eg2z92zwC9H3DzXkEaiaIs0aDAnNBVzJT/DeRFYDTEMDWINnEVTApuGoCl9mqciUUsAw== - dependencies: - "@types/nlcst" "^1.0.0" - format "^0.2.0" - nlcst-to-string "^3.0.0" - number-to-words "^1.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - -retext-latin@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/retext-latin/-/retext-latin-3.1.0.tgz#72b0176af2c69a373fd0d37eadd3924418bb3a89" - integrity sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ== - dependencies: - "@types/nlcst" "^1.0.0" - parse-latin "^5.0.0" - unherit "^3.0.0" - unified "^10.0.0" - -retext-repeated-words@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/retext-repeated-words/-/retext-repeated-words-4.2.0.tgz#1651c7e80356d2d9044f09eb17d6f82a327a018a" - integrity sha512-Tle40/5Xy6KxI94s4XRqGXcj6aWUeCoQZUGQto8OjZP98t4tKVDRVG3QGodF633hVOEiN1vYqj0Zegqoe8XOaw== - dependencies: - "@types/nlcst" "^1.0.0" - nlcst-to-string "^3.0.0" - unified "^10.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" - -retext-spell@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/retext-spell/-/retext-spell-5.3.0.tgz#c5b579d4d1abd4d7603f6cdc2d3f5a2d702e1133" - integrity sha512-b4LLp5S7ScmE+qJ2gu7FKfJICcfIK/UYIn1L84gJNRjDJyVIXWgdqQ7kgoqduP1mH3fFiKz3YVyNS4hD3XTlWw== - dependencies: - "@types/nlcst" "^1.0.0" - nlcst-is-literal "^2.0.0" - nlcst-to-string "^3.0.0" - nspell "^2.0.0" - quotation "^2.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - -retext-stringify@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/retext-stringify/-/retext-stringify-3.1.0.tgz#46ed45e077bfc4a8334977f6c2d6611e1d36263a" - integrity sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w== - dependencies: - "@types/nlcst" "^1.0.0" - nlcst-to-string "^3.0.0" - unified "^10.0.0" - -retext-syntax-mentions@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/retext-syntax-mentions/-/retext-syntax-mentions-3.1.0.tgz#844440a7d53c9e50416261ed7caa089ae80cfd2d" - integrity sha512-xcHHHOm3coErzrxtXN3S75UJ1S+WUJXKes5Mpu8WyVmMMYVC5qjSoBlYLHx1+jztq+KmYYkG3rbM3it2J4y7jA== - dependencies: - "@types/nlcst" "^1.0.0" - nlcst-to-string "^3.0.0" - unified "^10.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" - -retext-syntax-urls@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/retext-syntax-urls/-/retext-syntax-urls-3.1.2.tgz#33185f39bf7d2a17ceb9340c95f803e589c5f726" - integrity sha512-CFuqX1x7GPFQRMPTA88bjrD0l8jTN7Y5Zp8QVr9ToWyJRChIMqUlPq4HfOJbKdDfcwhTVZvh/jRyxLc/K6Tc4g== - dependencies: - "@types/nlcst" "^1.0.0" - "@types/unist" "^2.0.0" - ccount "^2.0.0" - nlcst-to-string "^3.0.0" - unified "^10.0.0" - unist-util-modify-children "^3.0.0" - unist-util-position "^4.0.0" - -retext@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/retext/-/retext-8.1.0.tgz#c43437fb84cd46285ad240a9279142e239bada8d" - integrity sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q== - dependencies: - "@types/nlcst" "^1.0.0" - retext-latin "^3.0.0" - retext-stringify "^3.0.0" - unified "^10.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@3.0.2, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -robust-predicates@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" - integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== - -rtl-detect@^1.0.4: - version "1.1.2" - resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.1.2.tgz#ca7f0330af5c6bb626c15675c642ba85ad6273c6" - integrity sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ== - -rtlcss@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-4.1.1.tgz#f20409fcc197e47d1925996372be196fee900c0c" - integrity sha512-/oVHgBtnPNcggP2aVXQjSy6N1mMAfHg4GSag0QtZBlD5bdDgAHwr4pydqJGd+SUCu9260+Pjqbjwtvu7EMH1KQ== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - postcss "^8.4.21" - strip-json-comments "^3.1.1" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rw@1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" - integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== - -sade@^1.7.3: - version "1.8.1" - resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" - integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== - dependencies: - mri "^1.1.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@^1.2.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" - integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== - dependencies: - "@types/json-schema" "^7.0.9" - ajv "^8.9.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.1.0" - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== - -selfsigned@^2.1.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" - integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== - dependencies: - "@types/node-forge" "^1.3.0" - node-forge "^1" - -semver-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-4.0.0.tgz#3afcf5ed6d62259f5c72d0d5d50dffbdc9680df5" - integrity sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA== - dependencies: - semver "^7.3.5" - -semver@^6.0.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.2, semver@^7.3.7, semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -semver@^7.3.5: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - -serve-handler@^6.1.5: - version "6.1.5" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.5.tgz#a4a0964f5c55c7e37a02a633232b6f0d6f068375" - integrity sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.1.2" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" - integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== - dependencies: - define-data-property "^1.1.1" - function-bind "^1.1.2" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shallowequal@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" - integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3, shell-quote@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== - -shelljs@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sirv@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" - integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== - dependencies: - "@polka/url" "^1.0.0-next.24" - mrmime "^2.0.0" - totalist "^3.0.0" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -sitemap@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== - dependencies: - "@types/node" "^17.0.5" - "@types/sax" "^1.2.1" - arg "^5.0.0" - sax "^1.2.4" - -skin-tone@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" - integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== - dependencies: - unicode-emoji-modifier-base "^1.0.0" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -sockjs@^0.3.24: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -sort-css-media-queries@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" - integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.0: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -space-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" - integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -spellchecker-cli@^6.1.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/spellchecker-cli/-/spellchecker-cli-6.1.1.tgz#65066a11f23dc5e6c6318e59936c0d897152be28" - integrity sha512-blA0aWuGoMn3TSHHiyB3u1E3bJI94r2Zz1FX0HhW5jOZXw3dMO1wXSvzlYnrdMIMPoKMZPxeqwFlBR3qsgZd/g== - dependencies: - chalk "^2.4.2" - command-line-args "^5.1.1" - command-line-usage "^5.0.4" - dictionary-en "^3" - dictionary-en-au "^2.3.0" - dictionary-en-ca "^2.3.0" - dictionary-en-gb "^2.3.0" - dictionary-en-za "^2.0.4" - dictionary-vi "^2.1.3" - fs-extra "^6.0.1" - globby "^11.0.0" - js-yaml "^3.14.1" - jsonc "^2.0.0" - junit-report-builder "^3.0.1" - lodash "^4.17.21" - pkg-dir "^6.0.1" - remark "^14.0.0" - remark-frontmatter "^4.0.0" - remark-retext "^5.0.1" - retext "^8.1.0" - retext-emoji "^8.1.0" - retext-indefinite-article "^4.1.0" - retext-repeated-words "^4.2.0" - retext-spell "^5.1.0" - retext-syntax-mentions "^3.1.0" - retext-syntax-urls "^3.1.2" - toml "^3.0.0" - unist-util-visit "^1.4.1" - vfile "^3.0.1" - vfile-reporter "^6.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -srcset@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/srcset/-/srcset-4.0.0.tgz#336816b665b14cd013ba545b6fe62357f86e65f4" - integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw== - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -"statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - -std-env@^3.0.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" - integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-entities@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" - integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== - dependencies: - character-entities-html4 "^2.0.0" - character-entities-legacy "^3.0.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -style-to-object@^0.4.0, style-to-object@^0.4.1: - version "0.4.4" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec" - integrity sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg== - dependencies: - inline-style-parser "0.1.1" - -style-to-object@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.6.tgz#0c28aed8be1813d166c60d962719b2907c26547b" - integrity sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA== - dependencies: - inline-style-parser "0.2.3" - -stylehacks@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" - integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== - dependencies: - browserslist "^4.21.4" - postcss-selector-parser "^6.0.4" - -stylis@^4.1.3: - version "4.3.1" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb" - integrity sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -svg-parser@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== - -svgo@^2.7.0, svgo@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - -table-layout@^0.4.3: - version "0.4.5" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.5.tgz#d906de6a25fa09c0c90d1d08ecd833ecedcb7378" - integrity sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw== - dependencies: - array-back "^2.0.0" - deep-extend "~0.6.0" - lodash.padend "^4.6.1" - typical "^2.6.1" - wordwrapjs "^3.0.0" - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -tar-fs@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.9: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.20" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" - -terser@^5.10.0, terser@^5.26.0: - version "5.27.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.27.0.tgz#70108689d9ab25fef61c4e93e808e9fd092bf20c" - integrity sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -terser@^5.15.1: - version "5.30.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" - integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -through@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -tiny-invariant@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== - -tiny-warning@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -toml@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" - integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== - -totalist@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" - integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -trim-lines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" - integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== - -trough@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" - integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== - -ts-dedent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" - integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== - -tslib@^2.0.3, tslib@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -type-fest@^1.0.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" - integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== - -type-fest@^2.13.0, type-fest@^2.5.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" - integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typescript@^5.4.4: - version "5.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.4.tgz#eb2471e7b0a5f1377523700a21669dce30c2d952" - integrity sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw== - -typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -unbzip2-stream@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" - integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unherit@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-3.0.1.tgz#65b98bb7cb58cee755d7ec699a49e9e8ff172e23" - integrity sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-emoji-modifier-base@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" - integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" - integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - -unified@^10.0.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" - integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== - dependencies: - "@types/unist" "^2.0.0" - bail "^2.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^4.0.0" - trough "^2.0.0" - vfile "^5.0.0" - -unified@^11.0.0, unified@^11.0.3, unified@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.4.tgz#f4be0ac0fe4c88cb873687c07c64c49ed5969015" - integrity sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ== - dependencies: - "@types/unist" "^3.0.0" - bail "^2.0.0" - devlop "^1.0.0" - extend "^3.0.0" - is-plain-obj "^4.0.0" - trough "^2.0.0" - vfile "^6.0.0" - -unique-string@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-3.0.0.tgz#84a1c377aff5fd7a8bc6b55d8244b2bd90d75b9a" - integrity sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ== - dependencies: - crypto-random-string "^4.0.0" - -unist-util-generated@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae" - integrity sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A== - -unist-util-is@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" - integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== - -unist-util-is@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" - integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-is@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" - integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-modify-children@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-3.1.1.tgz#c4018b86441aa3b54b3edff1151d0aa062384c82" - integrity sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA== - dependencies: - "@types/unist" "^2.0.0" - array-iterate "^2.0.0" - -unist-util-position-from-estree@^1.0.0, unist-util-position-from-estree@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz#8ac2480027229de76512079e377afbcabcfcce22" - integrity sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-position-from-estree@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz#d94da4df596529d1faa3de506202f0c9a23f2200" - integrity sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-position@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.4.tgz#93f6d8c7d6b373d9b825844645877c127455f037" - integrity sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-position@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" - integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-remove-position@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz#a89be6ea72e23b1a402350832b02a91f6a9afe51" - integrity sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ== - dependencies: - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" - -unist-util-remove-position@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163" - integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q== - dependencies: - "@types/unist" "^3.0.0" - unist-util-visit "^5.0.0" - -unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" - integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== - dependencies: - "@types/unist" "^2.0.2" - -unist-util-stringify-position@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" - integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-stringify-position@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" - integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== - dependencies: - "@types/unist" "^3.0.0" - -unist-util-visit-children@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-children/-/unist-util-visit-children-2.0.2.tgz#0f00a5caff567074568da2d89c54b5ee4a8c5440" - integrity sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-visit-parents@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" - integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== - dependencies: - unist-util-is "^3.0.0" - -unist-util-visit-parents@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" - integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - -unist-util-visit-parents@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" - integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - -unist-util-visit@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" - integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== - dependencies: - unist-util-visit-parents "^2.0.0" - -unist-util-visit@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" - integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.1.1" - -unist-util-visit@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" - integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== - dependencies: - "@types/unist" "^3.0.0" - unist-util-is "^6.0.0" - unist-util-visit-parents "^6.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -update-notifier@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-6.0.2.tgz#a6990253dfe6d5a02bd04fbb6a61543f55026b60" - integrity sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og== - dependencies: - boxen "^7.0.0" - chalk "^5.0.1" - configstore "^6.0.0" - has-yarn "^3.0.0" - import-lazy "^4.0.0" - is-ci "^3.0.1" - is-installed-globally "^0.4.0" - is-npm "^6.0.0" - is-yarn-global "^0.4.0" - latest-version "^7.0.0" - pupa "^3.1.0" - semver "^7.3.7" - semver-diff "^4.0.0" - xdg-basedir "^5.1.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-loader@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== - -utility-types@^3.10.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" - integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -uuid@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" - integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== - -uvu@^0.5.0: - version "0.5.6" - resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" - integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== - dependencies: - dequal "^2.0.0" - diff "^5.0.0" - kleur "^4.0.3" - sade "^1.7.3" - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -vfile-location@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.1.0.tgz#69df82fb9ef0a38d0d02b90dd84620e120050dd0" - integrity sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw== - dependencies: - "@types/unist" "^2.0.0" - vfile "^5.0.0" - -vfile-location@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.2.tgz#220d9ca1ab6f8b2504a4db398f7ebc149f9cb464" - integrity sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg== - dependencies: - "@types/unist" "^3.0.0" - vfile "^6.0.0" - -vfile-message@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" - integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== - dependencies: - unist-util-stringify-position "^1.1.1" - -vfile-message@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.4.tgz#15a50816ae7d7c2d1fa87090a7f9f96612b59dea" - integrity sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw== - dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^3.0.0" - -vfile-message@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" - integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-stringify-position "^4.0.0" - -vfile-reporter@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-6.0.2.tgz#cbddaea2eec560f27574ce7b7b269822c191a676" - integrity sha512-GN2bH2gs4eLnw/4jPSgfBjo+XCuvnX9elHICJZjVD4+NM0nsUrMTvdjGY5Sc/XG69XVTgLwj7hknQVc6M9FukA== - dependencies: - repeat-string "^1.5.0" - string-width "^4.0.0" - supports-color "^6.0.0" - unist-util-stringify-position "^2.0.0" - vfile-sort "^2.1.2" - vfile-statistics "^1.1.0" - -vfile-sort@^2.1.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/vfile-sort/-/vfile-sort-2.2.2.tgz#720fe067ce156aba0b411a01bb0dc65596aa1190" - integrity sha512-tAyUqD2R1l/7Rn7ixdGkhXLD3zsg+XLAeUDUhXearjfIcpL1Hcsj5hHpCoy/gvfK/Ws61+e972fm0F7up7hfYA== - -vfile-statistics@^1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.4.tgz#b99fd15ecf0f44ba088cc973425d666cb7a9f245" - integrity sha512-lXhElVO0Rq3frgPvFBwahmed3X03vjPF8OcjKMy8+F1xU/3Q3QU3tKEDp743SFtb74PdF0UWpxPvtOP0GCLheA== - -vfile@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" - integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== - dependencies: - is-buffer "^2.0.0" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" - -vfile@^5.0.0: - version "5.3.7" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.7.tgz#de0677e6683e3380fafc46544cfe603118826ab7" - integrity sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g== - dependencies: - "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" - -vfile@^6.0.0, vfile@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.1.tgz#1e8327f41eac91947d4fe9d237a2dd9209762536" - integrity sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw== - dependencies: - "@types/unist" "^3.0.0" - unist-util-stringify-position "^4.0.0" - vfile-message "^4.0.0" - -watchpack@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" - integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -web-namespaces@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" - integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== - -web-worker@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" - integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -webpack-bundle-analyzer@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz#84b7473b630a7b8c21c741f81d8fe4593208b454" - integrity sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ== - dependencies: - "@discoveryjs/json-ext" "0.5.7" - acorn "^8.0.4" - acorn-walk "^8.0.0" - commander "^7.2.0" - debounce "^1.2.1" - escape-string-regexp "^4.0.0" - gzip-size "^6.0.0" - html-escaper "^2.0.2" - is-plain-object "^5.0.0" - opener "^1.5.2" - picocolors "^1.0.0" - sirv "^2.0.3" - ws "^7.3.1" - -webpack-dev-middleware@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" - integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== - dependencies: - colorette "^2.0.10" - memfs "^3.4.3" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@^4.15.1: - version "4.15.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" - integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== - dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.5" - ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^2.0.0" - default-gateway "^6.0.3" - express "^4.17.3" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" - serve-index "^1.9.1" - sockjs "^0.3.24" - spdy "^4.0.2" - webpack-dev-middleware "^5.3.4" - ws "^8.13.0" - -webpack-merge@^5.9.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" - integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== - dependencies: - clone-deep "^4.0.1" - flat "^5.0.2" - wildcard "^2.0.0" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.88.1: - version "5.91.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" - integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.12.1" - "@webassemblyjs/wasm-edit" "^1.12.1" - "@webassemblyjs/wasm-parser" "^1.12.1" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.21.10" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.16.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.11" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" - watchpack "^2.4.1" - webpack-sources "^3.2.3" - -webpackbar@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" - integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== - dependencies: - chalk "^4.1.0" - consola "^2.15.3" - pretty-time "^1.1.0" - std-env "^3.0.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -widest-line@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" - integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== - dependencies: - string-width "^5.0.1" - -wildcard@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" - integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== - -wordwrapjs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz#c94c372894cadc6feb1a66bff64e1d9af92c5d1e" - integrity sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw== - dependencies: - reduce-flatten "^1.0.1" - typical "^2.6.1" - -wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.9.0.tgz#2a994bb67144be1b53fe2d23c53c028adeb7f45e" - integrity sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg== - -ws@^7.3.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - -ws@^8.13.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" - integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== - -xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-5.1.0.tgz#1efba19425e73be1bc6f2a6ceb52a3d2c884c0c9" - integrity sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ== - -xml-js@^1.6.11: - version "1.6.11" - resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" - integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== - dependencies: - sax "^1.2.4" - -xmlbuilder@^15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" - integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== - -zwitch@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" - integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==