From be4cd657c951766b1bfd8fe24fc0b4cc15305ae5 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Wed, 17 Sep 2025 14:32:46 +0200 Subject: [PATCH] POC --- docs/nix/render_options/__init__.py | 44 +- docs/site/community/services/index.md | 10 +- docs/site/concepts/templates.md | 7 +- docs/site/decisions/README.md | 5 +- docs/site/guides/contributing/debugging.md | 4 +- docs/site/guides/disk-encryption.md | 4 +- docs/site/guides/disko-templates/community.md | 2 +- .../guides/getting-started/add-machines.md | 2 +- .../guides/getting-started/add-services.md | 2 +- docs/site/guides/getting-started/add-user.md | 4 +- .../guides/getting-started/choose-disk.md | 8 +- .../guides/getting-started/convert-flake.md | 2 +- .../getting-started/create-installer.md | 18 +- .../guides/getting-started/flake-check.md | 2 +- .../hardware-report-physical.md | 2 +- .../hardware-report-virtual.md | 4 +- docs/site/guides/getting-started/index.md | 12 +- docs/site/guides/getting-started/update.md | 4 +- docs/site/guides/inventory/autoincludes.md | 2 +- docs/site/guides/inventory/inventory.md | 10 +- .../migrations/migrate-inventory-services.md | 2 +- docs/site/guides/networking/networking.md | 4 +- docs/site/guides/nixos-rebuild.md | 4 +- docs/site/guides/secrets.md | 15 +- docs/site/guides/secure-boot.md | 7 +- docs/site/guides/services/community.md | 4 +- docs/site/guides/vars/sops/age-plugins.md | 2 +- tested-trappist/.gitignore | 21 + tested-trappist/.vscode/extensions.json | 4 + tested-trappist/.vscode/launch.json | 11 + tested-trappist/README.md | 49 + tested-trappist/astro.config.mjs | 58 + tested-trappist/openapi.json | 6754 +++++++++++++++++ tested-trappist/package-lock.json | 6571 ++++++++++++++++ tested-trappist/package.json | 18 + tested-trappist/public/favicon.svg | 1 + tested-trappist/public/logo.svg | 1 + tested-trappist/src/assets/houston.webp | Bin 0 -> 98506 bytes tested-trappist/src/content.config.ts | 7 + .../docs/getting-started/add-machines.md | 128 + .../docs/getting-started/add-services.md | 80 + .../content/docs/getting-started/add-user.md | 131 + .../docs/getting-started/choose-disk.md | 79 + .../docs/getting-started/convert-flake.md | 183 + .../docs/getting-started/create-installer.md | 217 + .../docs/getting-started/flake-check.md | 31 + .../hardware-report-physical.md | 120 + .../hardware-report-virtual.md | 36 + .../content/docs/getting-started/update.md | 133 + .../content/docs/guides/vars/age-plugins.md | 89 + .../guides/vars/vars-advanced-examples.md | 292 + .../content/docs/guides/vars/vars-backend.md | 142 + .../content/docs/guides/vars/vars-concepts.md | 125 + .../content/docs/guides/vars/vars-overview.md | 147 + .../docs/guides/vars/vars-troubleshooting.md | 274 + tested-trappist/src/content/docs/index.md | 148 + .../docs/reference/clanServices/admin.md | 107 + .../docs/reference/clanServices/borgbackup.md | 218 + .../reference/clanServices/certificates.md | 145 + .../docs/reference/clanServices/coredns.md | 213 + .../reference/clanServices/data-mesher.md | 337 + .../docs/reference/clanServices/dyndns.md | 335 + .../clanServices/emergency-access.md | 31 + .../docs/reference/clanServices/garage.md | 15 + .../reference/clanServices/hello-world.md | 61 + .../docs/reference/clanServices/importer.md | 41 + .../reference/clanServices/localbackup.md | 290 + .../reference/clanServices/matrix-synapse.md | 176 + .../docs/reference/clanServices/monitoring.md | 79 + .../docs/reference/clanServices/mycelium.md | 60 + .../docs/reference/clanServices/packages.md | 45 + .../docs/reference/clanServices/sshd.md | 148 + .../docs/reference/clanServices/syncthing.md | 369 + .../clanServices/trusted-nix-caches.md | 30 + .../docs/reference/clanServices/users.md | 242 + .../docs/reference/clanServices/wifi.md | 109 + .../docs/reference/clanServices/wireguard.md | 390 + .../docs/reference/clanServices/zerotier.md | 131 + tested-trappist/tsconfig.json | 5 + 79 files changed, 19525 insertions(+), 88 deletions(-) create mode 100644 tested-trappist/.gitignore create mode 100644 tested-trappist/.vscode/extensions.json create mode 100644 tested-trappist/.vscode/launch.json create mode 100644 tested-trappist/README.md create mode 100644 tested-trappist/astro.config.mjs create mode 100644 tested-trappist/openapi.json create mode 100644 tested-trappist/package-lock.json create mode 100644 tested-trappist/package.json create mode 100644 tested-trappist/public/favicon.svg create mode 100644 tested-trappist/public/logo.svg create mode 100644 tested-trappist/src/assets/houston.webp create mode 100644 tested-trappist/src/content.config.ts create mode 100644 tested-trappist/src/content/docs/getting-started/add-machines.md create mode 100644 tested-trappist/src/content/docs/getting-started/add-services.md create mode 100644 tested-trappist/src/content/docs/getting-started/add-user.md create mode 100644 tested-trappist/src/content/docs/getting-started/choose-disk.md create mode 100644 tested-trappist/src/content/docs/getting-started/convert-flake.md create mode 100644 tested-trappist/src/content/docs/getting-started/create-installer.md create mode 100644 tested-trappist/src/content/docs/getting-started/flake-check.md create mode 100644 tested-trappist/src/content/docs/getting-started/hardware-report-physical.md create mode 100644 tested-trappist/src/content/docs/getting-started/hardware-report-virtual.md create mode 100644 tested-trappist/src/content/docs/getting-started/update.md create mode 100644 tested-trappist/src/content/docs/guides/vars/age-plugins.md create mode 100644 tested-trappist/src/content/docs/guides/vars/vars-advanced-examples.md create mode 100644 tested-trappist/src/content/docs/guides/vars/vars-backend.md create mode 100644 tested-trappist/src/content/docs/guides/vars/vars-concepts.md create mode 100644 tested-trappist/src/content/docs/guides/vars/vars-overview.md create mode 100644 tested-trappist/src/content/docs/guides/vars/vars-troubleshooting.md create mode 100644 tested-trappist/src/content/docs/index.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/admin.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/borgbackup.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/certificates.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/coredns.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/data-mesher.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/dyndns.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/emergency-access.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/garage.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/hello-world.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/importer.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/localbackup.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/matrix-synapse.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/monitoring.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/mycelium.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/packages.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/sshd.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/syncthing.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/trusted-nix-caches.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/users.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/wifi.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/wireguard.md create mode 100644 tested-trappist/src/content/docs/reference/clanServices/zerotier.md create mode 100644 tested-trappist/tsconfig.json diff --git a/docs/nix/render_options/__init__.py b/docs/nix/render_options/__init__.py index 76c7f09fb..f1c5338de 100644 --- a/docs/nix/render_options/__init__.py +++ b/docs/nix/render_options/__init__.py @@ -34,7 +34,6 @@ from typing import Any from clan_lib.errors import ClanError from clan_lib.services.modules import ( CategoryInfo, - ModuleManifest, ) # Get environment variables @@ -103,7 +102,7 @@ def render_option( read_only = option.get("readOnly") res = f""" -{"#" * level} {sanitize(name) if short_head is None else sanitize(short_head)} {"{: #" + sanitize_anchor(name) + "}" if level > 1 else ""} +{"#" * level} {sanitize(name) if short_head is None else sanitize(short_head)} """ @@ -130,14 +129,12 @@ def render_option( """ example = option.get("example", {}).get("text") if example: - example_indented = join_lines_with_indentation(example.split("\n")) res += f""" -???+ example +```nix title="example" +{example} +``` - ```nix -{example_indented} - ``` """ if option.get("relatedPackages"): res += f""" @@ -154,7 +151,7 @@ def render_option( source_path = source_path.split(",")[0] res += f""" -:simple-git: Declared in: [{name}]({source_path}) +πŸ“ƒ Declared in: [{name}]({source_path}) """ res += "\n\n" @@ -224,7 +221,7 @@ def produce_clan_core_docs() -> None: indexfile = f"{module_name}/index.md" core_outputs[indexfile] = module_header(module_name) + clan_core_descr - core_outputs[indexfile] += """!!! info "Submodules"\n""" + core_outputs[indexfile] += """:::note[Submodules]"\n""" for submodule_name, split_options in split.items(): root = options_to_tree(split_options) @@ -320,10 +317,11 @@ Each `clanService`: * Can define **roles** (e.g., `client`, `server`) * Uses **`inventory.instances`** to configure where and how it is deployed -!!! Note - `clanServices` are part of Clan's next-generation service model and are intended to replace `clanModules`. +:::note +`clanServices` are part of Clan's next-generation service model and are intended to replace `clanModules`. - See [Migration Guide](../../guides/migrations/migrate-inventory-services.md) for help on migrating. +See [Migration Guide](../../guides/migrations/migrate-inventory-services.md) for help on migrating. +::: Learn how to use `clanServices` in practice in the [Using clanServices guide](../../guides/inventory/clanServices.md). """ @@ -339,15 +337,20 @@ Learn how to use `clanServices` in practice in the [Using clanServices guide](.. if module_name in ["internet", "tor"]: continue - output = f"# {module_name}\n\n" + output = f"""--- +title: {module_name} +description: {module_info["manifest"]["description"]} +--- + +""" # output += f"`clan.modules.{module_name}`\n" output += f"*{module_info['manifest']['description']}*\n" # output += "## Categories\n\n" - output += render_categories( - module_info["manifest"]["categories"], - ModuleManifest.categories_info(), - ) + # output += render_categories( + # module_info["manifest"]["categories"], + # ModuleManifest.categories_info(), + # ) output += f"{module_info['manifest']['readme']}\n" @@ -417,10 +420,11 @@ This document describes the structure and configurable attributes of a `clan.ser Typically needed by module authors to define roles, behavior and metadata for distributed services. -!!! Note - This is not a user-facing documentation, but rather meant as a reference for *module authors* +:::note +This is not a user-facing documentation, but rather meant as a reference for *module authors* - See: [clanService Authoring Guide](../../guides/services/community.md) +See: [clanService Authoring Guide](../../guides/services/community.md) +::: """ # Inventory options are already included under the clan attribute # We just omitted them in the clan docs, because we want a separate output for the inventory model diff --git a/docs/site/community/services/index.md b/docs/site/community/services/index.md index 58ced0f5f..07a2c1ac4 100644 --- a/docs/site/community/services/index.md +++ b/docs/site/community/services/index.md @@ -1,8 +1,10 @@ -Services provided by the community +--- +title: Services provided by the community +--- -!!! tip "Add your own!" - - Have you built a service or a tool for? Open a PR adding a link to this page! +:::tip[Add your own!] +Have you built a service or a tool for? Open a PR adding a link to this page! +:::
diff --git a/docs/site/concepts/templates.md b/docs/site/concepts/templates.md index 8f1c35243..0ab3fd8ad 100644 --- a/docs/site/concepts/templates.md +++ b/docs/site/concepts/templates.md @@ -64,6 +64,7 @@ Just like with Nix you could specify a remote url or path to the flake containin `clan flakes create --template=github:owner/repo#foo` -!!! Note "Implementation Note" - Not all features of Nix's attribute selection are currently matched. - There are minor differences in case of unexpected behavior please create an [issue](https://git.clan.lol/clan/clan-core/issues/new) +:::note +Not all features of Nix's attribute selection are currently matched. +There are minor differences in case of unexpected behavior please create an [issue](https://git.clan.lol/clan/clan-core/issues/new) +::: \ No newline at end of file diff --git a/docs/site/decisions/README.md b/docs/site/decisions/README.md index e6839a4ac..3aeca99eb 100644 --- a/docs/site/decisions/README.md +++ b/docs/site/decisions/README.md @@ -6,8 +6,9 @@ This section contains the architecture decisions that have been reviewed and gen > An architecture decision record (ADR) is a document that captures an important architecture decision made along with its context and consequences. -!!! Note - For further reading about adr's we recommend [architecture-decision-record](https://github.com/joelparkerhenderson/architecture-decision-record) +:::note +For further reading about adr's we recommend [architecture-decision-record](https://github.com/joelparkerhenderson/architecture-decision-record) +::: ## Crafting a new ADR diff --git a/docs/site/guides/contributing/debugging.md b/docs/site/guides/contributing/debugging.md index 36fcd2dfe..2d59ccd37 100644 --- a/docs/site/guides/contributing/debugging.md +++ b/docs/site/guides/contributing/debugging.md @@ -5,7 +5,7 @@ Here are some methods for debugging and testing the clan-cli To streamline your development process, I suggest not installing `clan-cli`. Instead, clone the `clan-core` repository and add `clan-core/pkgs/clan-cli/bin` to your PATH to use the checked-out version directly. -!!! Note +:::Note After cloning, navigate to `clan-core/pkgs/clan-cli` and execute `direnv allow` to activate the devshell. This will set up a symlink to nixpkgs at a specific location; without it, `clan-cli` won't function correctly. With this setup, you can easily use [breakpoint()](https://docs.python.org/3/library/pdb.html) to inspect the application's internal state as needed. @@ -26,7 +26,7 @@ pkgs.mkShell { ## Debugging nixos-anywhere -If you encounter a bug in a complex shell script such as `nixos-anywhere`, start by replacing the `nixos-anywhere` command with a local checkout of the project, look in the [contribution](./CONTRIBUTING.md) section for an example. +If you encounter a bug in a complex shell script such as `nixos-anywhere`, start by replacing the `nixos-anywhere` command with a local checkout of the project, look in the [contribution](./CONTRIBUTING.md) section for an example. ## The Debug Flag diff --git a/docs/site/guides/disk-encryption.md b/docs/site/guides/disk-encryption.md index 7fd06e3ea..071e6a639 100644 --- a/docs/site/guides/disk-encryption.md +++ b/docs/site/guides/disk-encryption.md @@ -1,10 +1,10 @@ This guide provides an example setup for a single-disk ZFS system with native encryption, accessible for decryption remotely. -!!! Warning +:::warning This configuration only applies to `systemd-boot` enabled systems and **requires** UEFI booting. -!!! Info "Secure Boot" +:::Info "Secure Boot" This guide is compatible with systems that have [secure boot disabled](./secure-boot.md). If you encounter boot issues, check if secure boot needs to be disabled in your UEFI settings. Replace the highlighted lines with your own disk-id. diff --git a/docs/site/guides/disko-templates/community.md b/docs/site/guides/disko-templates/community.md index 78da39a58..2dc5ba388 100644 --- a/docs/site/guides/disko-templates/community.md +++ b/docs/site/guides/disko-templates/community.md @@ -1,5 +1,5 @@ -!!! Danger ":fontawesome-solid-road-barrier: Under Construction :fontawesome-solid-road-barrier:" +:::Danger ":fontawesome-solid-road-barrier: Under Construction :fontawesome-solid-road-barrier:" Currently under construction use with caution :fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: diff --git a/docs/site/guides/getting-started/add-machines.md b/docs/site/guides/getting-started/add-machines.md index a6285cb98..ca7be567c 100644 --- a/docs/site/guides/getting-started/add-machines.md +++ b/docs/site/guides/getting-started/add-machines.md @@ -41,7 +41,7 @@ See the complete [list](../inventory/autoincludes.md) of auto-loaded files. ### Configuring a machine -!!! Note +:::Note The option: `inventory.machines.` is used to define metadata about the machine That includes for example `deploy.targethost` `machineClass` or `tags` diff --git a/docs/site/guides/getting-started/add-services.md b/docs/site/guides/getting-started/add-services.md index 9d8dcb42f..4b3556e59 100644 --- a/docs/site/guides/getting-started/add-services.md +++ b/docs/site/guides/getting-started/add-services.md @@ -12,7 +12,7 @@ In Clan Services are multi-Host & role-based: To learn more: [Guide about clanService](../inventory/clanServices.md) -!!! Important +:::Important It is recommended to add at least one networking service such as `zerotier` that allows to reach all your clan machines from your setup computer across the globe. ## Configure a Zerotier Network (recommended) diff --git a/docs/site/guides/getting-started/add-user.md b/docs/site/guides/getting-started/add-user.md index 46d6a50ec..1c2419105 100644 --- a/docs/site/guides/getting-started/add-user.md +++ b/docs/site/guides/getting-started/add-user.md @@ -1,6 +1,6 @@ # How to add users -!!! Note "Under construction" +:::Note "Under construction" The users concept of clan is not done yet. This guide outlines some solutions from our community. Defining users can be done in many different ways. We want to highlight two approaches: @@ -109,7 +109,7 @@ We can use this property of clan services to bind a nixosModule to the user, whi 1. Type `path` or `string`: Must point to a separate file. Inlining a module is not possible -!!! Note "This is inspiration" +:::Note "This is inspiration" Our community might come up with better solutions soon. We are seeking contributions to improve this pattern if you have a nicer solution in mind. diff --git a/docs/site/guides/getting-started/choose-disk.md b/docs/site/guides/getting-started/choose-disk.md index 2533a426f..0e2bf54de 100644 --- a/docs/site/guides/getting-started/choose-disk.md +++ b/docs/site/guides/getting-started/choose-disk.md @@ -25,7 +25,7 @@ Available 'machine' templates For this guide we will select the `single-disk` template, that uses `A simple ext4 disk with a single partition`. -!!! tip +:::tip For advanced partitioning, see [Disko templates](https://github.com/nix-community/disko-templates) or [Disko examples](https://github.com/nix-community/disko/tree/master/example). You can also [contribute a disk template to clan core](https://docs.clan.lol/guides/disko-templates/community/) @@ -58,15 +58,15 @@ Applied disk template 'single-disk' to machine 'jon' A disko.nix file should be created in `machines/jon` You can have a look and customize it if needed. -!!! Danger +:::Danger Don't change the `disko.nix` after the machine is installed for the first time, unless you really know what you are doing. Changing disko configuration requires wiping and reinstalling the machine. ## Deploy the machine -**Finally deployment time!** +**Finally deployment time!** -This command is destructive and will format your disk and install NixOS on it! It is equivalent to appending `--phases kexec,disko,install,reboot`. +This command is destructive and will format your disk and install NixOS on it! It is equivalent to appending `--phases kexec,disko,install,reboot`. ```bash diff --git a/docs/site/guides/getting-started/convert-flake.md b/docs/site/guides/getting-started/convert-flake.md index ba269bbde..5c1fcffc0 100644 --- a/docs/site/guides/getting-started/convert-flake.md +++ b/docs/site/guides/getting-started/convert-flake.md @@ -2,7 +2,7 @@ This guide will help you convert your existing NixOS configurations into a Clan. -!!! Warning +:::Warning Migrating instead of starting new can be trickier and might lead to bugs or unexpected issues. We recommend reading the [Getting Started](./index.md) guide first. diff --git a/docs/site/guides/getting-started/create-installer.md b/docs/site/guides/getting-started/create-installer.md index 1f094eb98..bd6f998a9 100644 --- a/docs/site/guides/getting-started/create-installer.md +++ b/docs/site/guides/getting-started/create-installer.md @@ -2,13 +2,13 @@ To install Clan on physical machines, you need to use our custom installer image. This is necessary for proper installation and operation. -!!! note "Deploying to a Virtual Machine?" +:::note "Deploying to a Virtual Machine?" If you're deploying to a virtual machine (VM), you can skip this section and go directly to the [Deploy Virtual Machine](./hardware-report-virtual.md) step. In this scenario, we automatically use [nixos-anywhere](https://github.com/nix-community/nixos-anywhere) to replace the kernel during runtime. -??? info "Why nixos-anywhere Doesn't Work on Physical Hardware?" +:::info "Why nixos-anywhere Doesn't Work on Physical Hardware?" nixos-anywhere relies on [kexec](https://wiki.archlinux.org/title/Kexec) to replace the running kernel with our custom one. This method often has compatibility issues with real hardware, especially systems with dedicated graphics cards like laptops and servers, leading to crashes and black screens. -??? info "Reasons for a Custom Install Image" +:::info "Reasons for a Custom Install Image" Our custom install images are built to include essential tools like [nixos-facter](https://github.com/nix-community/nixos-facter) and support for [ZFS](https://wiki.archlinux.org/title/ZFS). They're also optimized to run on systems with as little as 1 GB of RAM, ensuring efficient performance even on lower-end hardware. ## Prerequisites @@ -36,7 +36,7 @@ To install Clan on physical machines, you need to use our custom installer image └─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store ``` - !!! Info "In this case the USB device is `sdb`" + :::Info "In this case the USB device is `sdb`" 3. Ensure all partitions on the drive are unmounted. Replace `sdb1` in the command below with your device identifier (like `sdc1`, etc.): @@ -62,11 +62,11 @@ sudo umount /dev/sdb1 --disk main /dev/sd \ flash-installer ``` - !!! Note + :::Note Replace `$HOME/.ssh/id_ed25519.pub` with a path to your SSH public key. Replace `/dev/sd` with the drive path you want to flash - !!! Danger "Specifying the wrong device can lead to unrecoverable data loss." + :::Danger "Specifying the wrong device can lead to unrecoverable data loss." The `clan flash` utility will erase the disk. Make sure to specify the correct device @@ -114,12 +114,12 @@ sudo umount /dev/sdb1 wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-aarch64-linux.iso ``` - !!! Note + :::Note If you don't have `wget` installed, you can use `curl --progress-bar -OL ` instead. ## Flash the Installer to the USB Drive - !!! Danger "Specifying the wrong device can lead to unrecoverable data loss." + :::Danger "Specifying the wrong device can lead to unrecoverable data loss." The `dd` utility will erase the disk. Make sure to specify the correct device (`of=...`) @@ -197,7 +197,7 @@ IPv4 address 192.168.188.50 (Your new local ip) Press ++ctrl+d++ to exit `IWD`. -!!! Important +:::Important Press ++ctrl+d++ **again** to update the displayed QR code and connection information. You're all set up diff --git a/docs/site/guides/getting-started/flake-check.md b/docs/site/guides/getting-started/flake-check.md index e2172bece..57741e6ae 100644 --- a/docs/site/guides/getting-started/flake-check.md +++ b/docs/site/guides/getting-started/flake-check.md @@ -22,7 +22,7 @@ nix flake check This command helps ensure that your system configuration is correct and free from errors. -!!! Tip +:::Tip You can integrate this step into your [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) workflow to ensure that only valid Nix configurations are merged into your codebase. diff --git a/docs/site/guides/getting-started/hardware-report-physical.md b/docs/site/guides/getting-started/hardware-report-physical.md index a60a74851..f40225f59 100644 --- a/docs/site/guides/getting-started/hardware-report-physical.md +++ b/docs/site/guides/getting-started/hardware-report-physical.md @@ -70,7 +70,7 @@ This is an example of the booted installer. This password is autogenerated and meant to be easily typeable. 3. See how to connect the installer medium to wlan [here](./create-installer.md). -!!!tip +:::tip For easy sharing of deployment information via QR code, we highly recommend using [KDE Connect](https://apps.kde.org/de/kdeconnect/). There are two ways to deploy your machine: diff --git a/docs/site/guides/getting-started/hardware-report-virtual.md b/docs/site/guides/getting-started/hardware-report-virtual.md index 957528d89..75291a05c 100644 --- a/docs/site/guides/getting-started/hardware-report-virtual.md +++ b/docs/site/guides/getting-started/hardware-report-virtual.md @@ -12,7 +12,7 @@ Now that you have created a machine, added some services, and set up secrets, th Clan supports any cloud machine if it is reachable via SSH and supports `kexec`. -??? tip "NixOS can cause strange issues when booting in certain cloud environments." +:::tip "NixOS can cause strange issues when booting in certain cloud environments." If on Linode: Make sure that the system uses "Direct Disk boot kernel" (found in the configuration panel) @@ -26,5 +26,5 @@ clan machines install [MACHINE] \ --target-host myuser@ ``` -!!! Warning +:::Warning After running the above command, be aware that the SSH login user changes from `myuser` to `root`. For subsequent SSH connections to the target machine, use `root` as the login user. This change occurs because the system switches to the NixOS kernel using `kexec`. diff --git a/docs/site/guides/getting-started/index.md b/docs/site/guides/getting-started/index.md index 42830bf41..8558969e1 100644 --- a/docs/site/guides/getting-started/index.md +++ b/docs/site/guides/getting-started/index.md @@ -1,6 +1,6 @@ # :material-clock-fast: Getting Started -Ready to manage your fleet of machines? +Ready to manage your fleet of machines? We will create a declarative infrastructure using **clan**, **git**, and **nix flakes**. @@ -13,7 +13,7 @@ Make sure you have the following: * πŸ’» **Administration Machine**: Run the setup commands from this machine. * πŸ› οΈ **Nix**: The Nix package manager, installed on your administration machine. - ??? info "**How to install Nix (Linux / MacOS / NixOS)**" + :::info "**How to install Nix (Linux / MacOS / NixOS)**" **On Linux or macOS:** @@ -43,7 +43,7 @@ Make sure you have the following: ## Create a New Clan 1. Navigate to your desired directory: - + ```shellSession cd ``` @@ -75,8 +75,8 @@ my-clan/ └── sops/ ``` -!!! note "Templates" - This is the structure for the `default` template. +:::note "Templates" + This is the structure for the `default` template. Use `clan templates list` and `clan templates --help` for available templates & more. Keep in mind that the exact files may change as templates evolve. @@ -121,7 +121,7 @@ Name: __CHANGE_ME__ Description: None ``` -This confirms your setup is working correctly. +This confirms your setup is working correctly. You can now change the default name by editing the `meta.name` field in your `clan.nix` file. diff --git a/docs/site/guides/getting-started/update.md b/docs/site/guides/getting-started/update.md index a88ef7dcf..45ef56434 100644 --- a/docs/site/guides/getting-started/update.md +++ b/docs/site/guides/getting-started/update.md @@ -60,7 +60,7 @@ If the machine does not have enough resources to run the NixOS **evaluation** or it is also possible to specify a `buildHost` instead. During an update, clan will ssh into the `buildHost` and run `nixos-rebuild` from there. -!!! Note +:::Note The `buildHost` option should be set directly within your machine’s Nix configuration, **not** under `inventory.machines`. @@ -89,7 +89,7 @@ clan machines update jon --build-host root@192.168.1.10 clan machines update jon --build-host local ``` -!!! Note +:::Note Make sure the CPU architecture of the `buildHost` matches that of the `targetHost` For example, if deploying to a macOS machine with an ARM64-Darwin architecture, you need a second macOS machine with the same architecture to build it. diff --git a/docs/site/guides/inventory/autoincludes.md b/docs/site/guides/inventory/autoincludes.md index 459015a5b..c3e95fc00 100644 --- a/docs/site/guides/inventory/autoincludes.md +++ b/docs/site/guides/inventory/autoincludes.md @@ -6,7 +6,7 @@ Clan automatically imports specific files from each machine directory and regist Every folder under `machines/{machineName}` is automatically registered as a Clan machine. -!!! info "Files loaded automatically for each machine" +:::info "Files loaded automatically for each machine" The following files are detected and imported for every Clan machine: diff --git a/docs/site/guides/inventory/inventory.md b/docs/site/guides/inventory/inventory.md index 4659849f2..51192b77f 100644 --- a/docs/site/guides/inventory/inventory.md +++ b/docs/site/guides/inventory/inventory.md @@ -9,7 +9,7 @@ The inventory logic will automatically derive the modules and configurations to The following tutorial will walk through setting up a Backup service where the terms `Service` and `Role` will become more clear. -!!! example "Experimental status" +:::example "Experimental status" The inventory implementation is not considered stable yet. We are actively soliciting feedback from users. @@ -36,7 +36,7 @@ Each service can still be customized and configured according to the modules opt ### Setting up the Backup Service -!!! Example "Borgbackup Example" +:::Example "Borgbackup Example" To configure a service it needs to be added to the machine. It is required to assign the service (`borgbackup`) an arbitrary instance name. (`instance_1`) @@ -64,7 +64,7 @@ The inventory allows machines to set Tags It is possible to add services to multiple machines via tags as shown -!!! Example "Tags Example" +:::Example "Tags Example" ```{.nix hl_lines="5 8 18"} { @@ -93,11 +93,11 @@ It is possible to add services to multiple machines via tags as shown ### Multiple Service Instances -!!! danger "Important" +:::danger "Important" Not all modules implement support for multiple instances yet. Multiple instance usage could create complexity, refer to each modules documentation, for intended usage. -!!! Example +:::Example In this example `backup_server` has role `client` and `server` in different instances. diff --git a/docs/site/guides/migrations/migrate-inventory-services.md b/docs/site/guides/migrations/migrate-inventory-services.md index 8c2c89059..b95f29666 100644 --- a/docs/site/guides/migrations/migrate-inventory-services.md +++ b/docs/site/guides/migrations/migrate-inventory-services.md @@ -290,7 +290,7 @@ The following table shows the migration status of each deprecated clanModule: --- -!!! Warning +:::Warning * Old `clanModules` (`class = "nixos"`) are deprecated and will be removed in the near future. * `inventory.services` is no longer recommended; use `inventory.instances` instead. * Module authors should begin exporting service modules under the `clan.modules` attribute of their flake. diff --git a/docs/site/guides/networking/networking.md b/docs/site/guides/networking/networking.md index 972aedb29..7042ea786 100644 --- a/docs/site/guides/networking/networking.md +++ b/docs/site/guides/networking/networking.md @@ -98,7 +98,7 @@ clan network overview ## Option 2: Manual targetHost (Bypasses Fallback!) -!!! warning +:::warning Setting `targetHost` directly **disables all automatic networking and fallback**. Only use this if you need complete control and don't want Clan's intelligent connection management. ### Using Inventory (For Static Addresses) @@ -155,7 +155,7 @@ Use machine-level `targetHost` when you need to **interpolate values from the Ni - Building from multiple config values: `"${config.users.users.deploy.name}@${config.networking.hostName}"` - Any address that depends on evaluated NixOS configuration -!!! info "Key Difference" +:::info "Key Difference" **Inventory-level** (`deploy.targetHost`) is evaluated immediately and works with static strings. **Machine-level** (`clan.core.networking.targetHost`) is evaluated after NixOS configuration and can access `config.*` values. diff --git a/docs/site/guides/nixos-rebuild.md b/docs/site/guides/nixos-rebuild.md index 6a92d9446..824681507 100644 --- a/docs/site/guides/nixos-rebuild.md +++ b/docs/site/guides/nixos-rebuild.md @@ -7,10 +7,10 @@ However, there are important considerations when using `nixos-rebuild` directly ## Important Considerations -!!! warning "Vars Must Be Uploaded First" +:::warning "Vars Must Be Uploaded First" If your configuration uses clan vars, failing to run `clan vars upload` before `nixos-rebuild` will result in missing secrets and potentially broken services. -!!! info "Build Host Configuration" +:::info "Build Host Configuration" Clan automatically handles build host configuration based on your machine settings. When using `nixos-rebuild` manually, you need to specify `--build-host` and `--target-host` options yourself. diff --git a/docs/site/guides/secrets.md b/docs/site/guides/secrets.md index 14652e52e..c6030d955 100644 --- a/docs/site/guides/secrets.md +++ b/docs/site/guides/secrets.md @@ -17,7 +17,7 @@ Clan can also be configured to be used with other secret store [backends](../ref To get started, you'll need to create **your admin keypair**. -!!! info +:::info Don't worry β€” if you've already made one before, this step won't change or overwrite it. ```bash @@ -33,7 +33,7 @@ Generated age private key at '/home/joerg/.config/sops/age/keys.txt' for your us Also add your age public key to the repository with 'clan secrets users add YOUR_USER age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace YOUR_USER with your actual username) ``` -!!! warning +:::warning Make sure to keep a safe backup of the private key you've just created. If it's lost, you won't be able to get to your secrets anymore because they all need the admin key to be unlocked. @@ -47,7 +47,7 @@ Alternatively, you can provide your [age] secret key as an environment variable using `SOPS_AGE_KEY_FILE`. For more information see the [SOPS] guide on [encrypting with age]. -!!! note +:::note It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`. ## Add Your Public Key(s) @@ -68,7 +68,7 @@ sops/ ``` If you followed the quickstart tutorial all necessary secrets are initialized at this point. -!!! note +:::note You can add multiple age keys for a user by providing multiple `--age-key ` flags: ```console @@ -260,7 +260,7 @@ The secrets system conceptually knows two different entities: **A machine** Can decrypt secrets that where encrypted specifically for that machine. -!!! Danger +:::Danger **Always make sure at least one _User_ has access to a secret**. Otherwise you could lock yourself out from accessing the secret. ### Inherited implications @@ -275,8 +275,9 @@ By default clan uses [sops](https://github.com/getsops/sops) through [sops-nix]( - **Machine key-pairs are auto-generated**: When a machine is created **no user-interaction is required** to setup public/private key-pairs. - **secrets are re-encrypted**: In case machines, users or groups are modified secrets get re-encrypted on demand. - !!! Important - After revoking access to a secret you should also change the underlying secret. i.e. change the API key, or the password. + :::caution + After revoking access to a secret you should also change the underlying secret. i.e. change the API key, or the password. + ::: --- diff --git a/docs/site/guides/secure-boot.md b/docs/site/guides/secure-boot.md index 51d39c633..7241cdb22 100644 --- a/docs/site/guides/secure-boot.md +++ b/docs/site/guides/secure-boot.md @@ -8,7 +8,7 @@ At the moment, NixOS/Clan does not support [Secure Boot](https://wiki.gentoo.org - Restart your computer. - As your computer restarts, press the appropriate key to enter the UEFI/BIOS settings. -??? tip "The key depends on your laptop or motherboard manufacturer. Click to see a reference list:" +:::tip "The key depends on your laptop or motherboard manufacturer. Click to see a reference list:" | Manufacturer | UEFI/BIOS Key(s) | |--------------------|---------------------------| @@ -31,8 +31,9 @@ At the moment, NixOS/Clan does not support [Secure Boot](https://wiki.gentoo.org | EVGA | `Del` | | Origin PC | `F2`, `Delete` | - !!! Note - Pressing the key quickly and repeatedly is sometimes necessary to access the UEFI/BIOS menu, as the window to enter this mode is brief. + :::note + Pressing the key quickly and repeatedly is sometimes necessary to access the UEFI/BIOS menu, as the window to enter this mode is brief. + ::: ## Access Advanced Mode (Optional) diff --git a/docs/site/guides/services/community.md b/docs/site/guides/services/community.md index ba2687feb..6243da511 100644 --- a/docs/site/guides/services/community.md +++ b/docs/site/guides/services/community.md @@ -145,7 +145,7 @@ Next we need to define the settings and the behavior of these distinct roles. ## Using values from a NixOS machine inside the module -!!! Example "Experimental Status" +:::Example "Experimental Status" This feature is experimental and should be used with care. Sometimes a settings value depends on something within a machines `config`. @@ -174,7 +174,7 @@ The following example shows how to create a local instance of machine specific s } ``` -!!! Danger +:::Danger `localSettings` are a local attribute. Other machines cannot access it. If calling extendSettings is done that doesn't change the original `settings` this means if a different machine tries to access i.e `roles.client.settings` it would *NOT* contain your changes. diff --git a/docs/site/guides/vars/sops/age-plugins.md b/docs/site/guides/vars/sops/age-plugins.md index cc1340bb3..2790052c5 100644 --- a/docs/site/guides/vars/sops/age-plugins.md +++ b/docs/site/guides/vars/sops/age-plugins.md @@ -29,7 +29,7 @@ Below is a [list of popular `age` plugins](https://github.com/FiloSottile/awesom If you want to use `fido2 tokens` to encrypt your secret instead of the normal age secret key then you need to prefix your age secret key with the corresponding plugin name. In our case we want to use the `age-plugin-fido2-hmac` plugin so we replace `AGE-SECRET-KEY` with `AGE-PLUGIN-FIDO2-HMAC`. -??? tip +:::tip - On Linux the age secret key is located at `~/.config/sops/age/keys.txt` - On macOS it is located at `/Users/admin/Library/Application Support/sops/age/keys.txt` diff --git a/tested-trappist/.gitignore b/tested-trappist/.gitignore new file mode 100644 index 000000000..6240da8b1 --- /dev/null +++ b/tested-trappist/.gitignore @@ -0,0 +1,21 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/tested-trappist/.vscode/extensions.json b/tested-trappist/.vscode/extensions.json new file mode 100644 index 000000000..22a15055d --- /dev/null +++ b/tested-trappist/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/tested-trappist/.vscode/launch.json b/tested-trappist/.vscode/launch.json new file mode 100644 index 000000000..d64220976 --- /dev/null +++ b/tested-trappist/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/tested-trappist/README.md b/tested-trappist/README.md new file mode 100644 index 000000000..1b7f5c3d7 --- /dev/null +++ b/tested-trappist/README.md @@ -0,0 +1,49 @@ +# Starlight Starter Kit: Basics + +[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) + +``` +npm create astro@latest -- --template starlight +``` + +> πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! + +## πŸš€ Project Structure + +Inside of your Astro + Starlight project, you'll see the following folders and files: + +``` +. +β”œβ”€β”€ public/ +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ assets/ +β”‚ β”œβ”€β”€ content/ +β”‚ β”‚ └── docs/ +β”‚ └── content.config.ts +β”œβ”€β”€ astro.config.mjs +β”œβ”€β”€ package.json +└── tsconfig.json +``` + +Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. + +Images can be added to `src/assets/` and embedded in Markdown with a relative link. + +Static assets, like favicons, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## πŸ‘€ Want to learn more? + +Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). diff --git a/tested-trappist/astro.config.mjs b/tested-trappist/astro.config.mjs new file mode 100644 index 000000000..da1b3dcfe --- /dev/null +++ b/tested-trappist/astro.config.mjs @@ -0,0 +1,58 @@ +// @ts-check +import { defineConfig } from "astro/config"; +import starlightOpenAPI, { openAPISidebarGroups } from "starlight-openapi"; +import starlight from "@astrojs/starlight"; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + starlight({ + title: "Clan", + favicon: "/public/favicon.svg", + // logo: { src: "/public/logo.svg", alt: "Clan Logo" }, + social: [ + { + icon: "seti:git", + label: "Git", + href: "https://git.clan.lol/clan/clan-core", + }, + ], + plugins: [ + // Generate the OpenAPI documentation pages. + starlightOpenAPI([ + { + base: "api", + schema: "openapi.json", + sidebar: { + collapsed: true, + label: "Internal API", + }, + }, + ]), + ], + sidebar: [ + { + label: "Getting Started", + autogenerate: { directory: "getting-started" }, + collapsed: false, + }, + { + label: "Guides", + autogenerate: { directory: "guides" }, + collapsed: false, + }, + { + label: "Reference", + items: [ + { + label: "Clan Services", + autogenerate: { directory: "reference/clanServices" }, + collapsed: false, + }, + ...openAPISidebarGroups, + ], + }, + ], + }), + ], +}); diff --git a/tested-trappist/openapi.json b/tested-trappist/openapi.json new file mode 100644 index 000000000..71514757f --- /dev/null +++ b/tested-trappist/openapi.json @@ -0,0 +1,6754 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Function-Based Python API", + "version": "1.0.0", + "description": "!!! INTERNAL USE ONLY !!! We don't provide a world usable API yet.\nThis prototype maps python function calls to POST Requests because we are planning towards RESTfull API in the future." + }, + "paths": { + "/create_clan": { + "post": { + "summary": "create_clan", + "operationId": "create_clan", + "description": "Create a new clan repository with the specified template.\n\nArgs:\n opts: CreateOptions containing the destination path, template name,\n source flake, and other options.\n\nRaises:\n ClanError: If the source flake is not a valid flake or if the destination\n directory already exists.\n\n", + "tags": [ + "Clan" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_clan_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_clan_return" + } + } + } + } + } + } + }, + "/get_clan_details": { + "post": { + "summary": "get_clan_details", + "operationId": "get_clan_details", + "description": "Retrieve the clan details from the inventory of a given flake.\n\nArgs:\n flake: The Flake instance representing the clan.\n\nReturns:\n InventoryMeta: The meta information from the clan's inventory.\n\nRaises:\n ClanError: If the flake does not exist, or if the inventory is invalid (missing the meta attribute).\n\n", + "tags": [ + "Clan / Detail" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_details_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_details_return" + } + } + } + } + } + } + }, + "/set_clan_details": { + "post": { + "summary": "set_clan_details", + "operationId": "set_clan_details", + "description": "Update the clan metadata in the inventory of a given flake.\n\nArgs:\n options: UpdateOptions containing the flake and the new metadata.\n\nReturns:\n InventorySnapshot: The updated inventory snapshot after modifying the metadata.\n\nRaises:\n ClanError: If the flake does not exist or if the inventory is invalid (missing the meta attribute).\n\n", + "tags": [ + "Clan / Detail" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_clan_details_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_clan_details_return" + } + } + } + } + } + } + }, + "/get_clan_details_schema": { + "post": { + "summary": "get_clan_details_schema", + "operationId": "get_clan_details_schema", + "description": "Get attributes for each field of the clan.\n\nThis function checks which fields of the 'clan' resource are readonly and provides a reason if so.\n\nArgs:\n flake (Flake): The Flake object for which to retrieve fields.\n\nReturns:\n dict[str, FieldSchema]: A map from field-names to { 'readonly' (bool) and 'reason' (str or None ) }\n\n", + "tags": [ + "Clan / Detail / Schema" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_details_schema_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_details_schema_return" + } + } + } + } + } + } + }, + "/get_clan_directory_relative": { + "post": { + "summary": "get_clan_directory_relative", + "operationId": "get_clan_directory_relative", + "description": "Get the clan directory path relative to the flake root\nfrom the clan.directory configuration setting.\n\nArgs:\n flake: The clan flake to get the relative directory from\n\nReturns:\n The relative directory path (e.g., \".\", \"direct-config\", \"subdir/config\")\n\nRaises:\n ClanError: If the flake evaluation fails or directories cannot be found\n\n", + "tags": [ + "Clan / Directory / Relative" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_directory_relative_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_directory_relative_return" + } + } + } + } + } + } + }, + "/get_clan_folder": { + "post": { + "summary": "get_clan_folder", + "operationId": "get_clan_folder", + "description": "Api method to open the clan folder.\n\nImplementations is specific to the platform and returns the path to the clan folder.\n", + "tags": [ + "Clan / Folder" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_folder_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_clan_folder_return" + } + } + } + } + } + } + }, + "/check_clan_valid": { + "post": { + "summary": "check_clan_valid", + "operationId": "check_clan_valid", + "description": "Check if a clan is valid by verifying if it has the clanInternals attribute.\n\nArgs:\n flake: The Flake instance representing the clan.\n\nReturns:\n bool: True if the clan exists, False otherwise.\n\n", + "tags": [ + "Clan / Valid" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_clan_valid_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_clan_valid_return" + } + } + } + } + } + } + }, + "/get_generators": { + "post": { + "summary": "get_generators", + "operationId": "get_generators", + "description": "Get generators for a machine, with optional closure computation.\n\nArgs:\n machines: The machines to get generators for.\n full_closure: If True, include all dependency generators. If False, only include missing ones.\n generator_name: Name of a specific generator to get, or None for all generators.\n include_previous_values: If True, populate prompts with their previous values.\n\nReturns:\n List of generators based on the specified selection and closure mode.\n\n", + "tags": [ + "Generator" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_generators_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_generators_return" + } + } + } + } + } + } + }, + "/run_generators": { + "post": { + "summary": "run_generators", + "operationId": "run_generators", + "description": "Run the specified generators for machines.\n\nArgs:\n machines: The machines to run generators for.\n generators: Can be:\n - None: Run all generators (with closure based on full_closure parameter)\n - str: Single generator name to run (with closure based on full_closure parameter)\n - list[str]: Specific generator names to run exactly as provided.\n Dependency generators are not added automatically in this case.\n The caller must ensure that all dependencies are included.\n full_closure: Whether to include all dependencies (True) or only missing ones (False).\n Only used when generators is None or a string.\n prompt_values: A dictionary mapping generator names to their prompt values,\n or a function that returns prompt values for a generator.\n no_sandbox: Whether to disable sandboxing when executing the generator.\n\nRaises:\n ClanError: If the machine or generator is not found, or if there are issues with\n executing the generator.\n\n", + "tags": [ + "Generator" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_generators_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_generators_return" + } + } + } + } + } + } + }, + "/list_log_days": { + "post": { + "summary": "list_log_days", + "operationId": "list_log_days", + "description": "List all available log days.\n\nReturns:\n A list of date strings in YYYY-MM-DD format representing all available log days.\n\nRaises:\n ClanError: If LOG_MANAGER_INSTANCE is not initialized.\n\n", + "tags": [ + "Log / Day" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_log_days_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_log_days_return" + } + } + } + } + } + } + }, + "/get_log_file": { + "post": { + "summary": "get_log_file", + "operationId": "get_log_file", + "description": "Get the contents of a specific log file by operation key.\n\nArgs:\n id_key: The operation key to search for.\n selector: Optional group path to search in. If None, searches all groups.\n date_day: Optional specific date to search in (YYYY-MM-DD format). If None, searches all days.\n\nReturns:\n The contents of the log file as a string.\n\nRaises:\n ClanError: If the log file is not found or LOG_MANAGER_INSTANCE is not initialized.\n\n", + "tags": [ + "Log / File" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_log_file_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_log_file_return" + } + } + } + } + } + } + }, + "/list_log_groups": { + "post": { + "summary": "list_log_groups", + "operationId": "list_log_groups", + "description": "List all log groups at the specified hierarchical path.\n\nArgs:\n selector: List of path components to navigate to. Empty list returns top-level groups.\n date_day: Optional date to filter by (YYYY-MM-DD format). If None, uses most recent day.\n\nReturns:\n A list of folder names (decoded) at the specified path level.\n\nRaises:\n ClanError: If LOG_MANAGER_INSTANCE is not initialized.\n\n", + "tags": [ + "Log / Group" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_log_groups_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_log_groups_return" + } + } + } + } + } + } + }, + "/list_machines": { + "post": { + "summary": "list_machines", + "operationId": "list_machines", + "description": "List machines of a clan", + "tags": [ + "Machine" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_machines_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_machines_return" + } + } + } + } + } + } + }, + "/get_machine": { + "post": { + "summary": "get_machine", + "operationId": "get_machine", + "description": "Retrieve a machine's inventory details by name from the given flake.\n\nArgs:\n flake (Flake): The flake object representing the configuration source.\n name (str): The name of the machine to retrieve from the inventory.\n\nReturns:\n InventoryMachine: An instance representing the machine's inventory details.\n\nRaises:\n ClanError: If the machine with the specified name is not found in the clan\n\n", + "tags": [ + "Machine" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_return" + } + } + } + } + } + } + }, + "/set_machine": { + "post": { + "summary": "set_machine", + "operationId": "set_machine", + "description": "Update the machine information in the inventory.", + "tags": [ + "Machine" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_machine_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_machine_return" + } + } + } + } + } + } + }, + "/delete_machine": { + "post": { + "summary": "delete_machine", + "operationId": "delete_machine", + "description": "Delete a machine from the clan's inventory and remove its associated files.\n\nArgs:\n machine: The Machine instance to be deleted.\n\nRaises:\n ClanError: If the machine does not exist in the inventory or if there are issues with\n removing its files.\n\n", + "tags": [ + "Machine" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/delete_machine_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/delete_machine_return" + } + } + } + } + } + } + }, + "/create_machine": { + "post": { + "summary": "create_machine", + "operationId": "create_machine", + "description": "Create a new machine in the clan directory.\n\nThis function will create a new machine based on a template.\n\n:param opts: Options for creating the machine, including clan directory, machine details, and template name.\n:param commit: Whether to commit the changes to the git repository.\n:param _persist: Temporary workaround for 'morph'. Whether to persist the changes to the inventory store.\n", + "tags": [ + "Machine" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_machine_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_machine_return" + } + } + } + } + } + } + }, + "/get_machine_details": { + "post": { + "summary": "get_machine_details", + "operationId": "get_machine_details", + "description": "Retrieve detailed information about a machine, including its inventory,\nhardware configuration, and disk schema if available.\n\nArgs:\n machine (Machine): The machine instance for which details are to be retrieved.\n\nReturns:\n MachineDetails: An instance containing the machine's inventory, hardware configuration,\n and disk schema.\n\nRaises:\n ClanError: If the machine's inventory cannot be found or if there are issues with the\n hardware configuration or disk schema extraction.\n\n", + "tags": [ + "Machine / Detail" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_details_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_details_return" + } + } + } + } + } + } + }, + "/get_machine_disk_schemas": { + "post": { + "summary": "get_machine_disk_schemas", + "operationId": "get_machine_disk_schemas", + "description": "Get the available disk schemas.\nThis function reads the disk schemas from the templates directory and returns them as a dictionary.\nOffering options based on the hardware report of the machine.\n\n:param machine: The machine to get the disk schemas for\n:return: A dictionary of disk schemas, keyed by schema name\n\n:raises ClanError: If the hardware configuration is missing or invalid\n", + "tags": [ + "Machine / Disk / Schema" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_disk_schemas_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_disk_schemas_return" + } + } + } + } + } + } + }, + "/set_machine_disk_schema": { + "post": { + "summary": "set_machine_disk_schema", + "operationId": "set_machine_disk_schema", + "description": "Set the disk placeholders of the template", + "tags": [ + "Machine / Disk / Schema" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_machine_disk_schema_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/set_machine_disk_schema_return" + } + } + } + } + } + } + }, + "/get_machine_fields_schema": { + "post": { + "summary": "get_machine_fields_schema", + "operationId": "get_machine_fields_schema", + "description": "Get attributes for each field of the machine.\n\nThis function checks which fields of the 'machine' resource are readonly and provides a reason if so.\n\nArgs:\n machine (Machine): The machine object for which to retrieve fields.\n\nReturns:\n dict[str, FieldSchema]: A map from field-names to { 'readonly' (bool) and 'reason' (str or None ) }\n\n", + "tags": [ + "Machine / Field / Schema" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_fields_schema_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_fields_schema_return" + } + } + } + } + } + } + }, + "/run_machine_flash": { + "post": { + "summary": "run_machine_flash", + "operationId": "run_machine_flash", + "description": "Flash a machine with the given configuration.\n\nArgs:\n machine: The Machine instance to flash.\n mode: The mode to use for flashing (e.g., \"install\", \"reinstall\n disks: List of Disk instances representing the disks to flash.\n system_config: SystemConfig instance containing language, keymap, and SSH keys.\n dry_run: If True, perform a dry run without making changes.\n write_efi_boot_entries: If True, write EFI boot entries.\n debug: If True, enable debug mode.\n extra_args: Additional arguments to pass to the disko-install command.\n graphical: If True, run the command in graphical mode.\n\nRaises:\n ClanError: If the language or keymap is invalid, or if there are issues with\n reading SSH keys, or if disko-install fails.\n\n", + "tags": [ + "Machine / Flash" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_flash_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_flash_return" + } + } + } + } + } + } + }, + "/get_machine_flash_options": { + "post": { + "summary": "get_machine_flash_options", + "operationId": "get_machine_flash_options", + "description": "Retrieve available languages and keymaps for flash configuration.\n\nReturns:\n FlashOptions: A dictionary containing lists of available languages and keymaps.\n\nRaises:\n ClanError: If the locale file or keymaps directory does not exist.\n\n", + "tags": [ + "Machine / Flash / Option" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_flash_options_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_flash_options_return" + } + } + } + } + } + } + }, + "/run_machine_hardware_info": { + "post": { + "summary": "run_machine_hardware_info", + "operationId": "run_machine_hardware_info", + "description": "Generate hardware information for a machine\nand place the resulting *.nix file in the machine's directory.\n", + "tags": [ + "Machine / Hardware / Info" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_hardware_info_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_hardware_info_return" + } + } + } + } + } + } + }, + "/get_machine_hardware_summary": { + "post": { + "summary": "get_machine_hardware_summary", + "operationId": "get_machine_hardware_summary", + "description": "Return a high-level summary of hardware config and platform type.", + "tags": [ + "Machine / Hardware / Summary" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_hardware_summary_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_hardware_summary_return" + } + } + } + } + } + } + }, + "/get_machine_host": { + "post": { + "summary": "get_machine_host", + "operationId": "get_machine_host", + "description": "Get the build or target host for a machine.", + "tags": [ + "Machine / Host" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_host_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_host_return" + } + } + } + } + } + } + }, + "/run_machine_install": { + "post": { + "summary": "run_machine_install", + "operationId": "run_machine_install", + "description": "Install a machine using nixos-anywhere.\n\nArgs:\n opts: InstallOptions containing the machine to install, kexec option, debug mode,\n no-reboot option, phases, build-on option, hardware config update, password,\n identity file, and use_tor flag.\n target_host: Remote object representing the target host for installation.\n\nRaises:\n ClanError: If the machine is not found in the inventory or if there are issues with\n generating facts or variables.\n\n", + "tags": [ + "Machine / Install" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_install_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_install_return" + } + } + } + } + } + } + }, + "/check_machine_ssh_login": { + "post": { + "summary": "check_machine_ssh_login", + "operationId": "check_machine_ssh_login", + "description": "Checks if a remote machine is reachable via SSH by attempting to run a simple command.\n\nArgs:\n remote (Remote): The remote host to check for SSH login.\n opts (ConnectionOptions, optional): Connection options such as timeout.\n If not provided, default values are used.\nUsage:\n result = check_machine_ssh_login(remote)\n if result.ok:\n print(\"SSH login successful\")\n else:\n print(f\"SSH login failed: {result.reason}\")\n\nRaises:\n ClanError: If the SSH login fails.\n\n", + "tags": [ + "Machine / Ssh / Login" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_ssh_login_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_ssh_login_return" + } + } + } + } + } + } + }, + "/check_machine_ssh_reachable": { + "post": { + "summary": "check_machine_ssh_reachable", + "operationId": "check_machine_ssh_reachable", + "description": "Checks if a remote machine is reachable via SSH by attempting to open a TCP connection\nto the specified address and port.\n\nArgs:\n remote (Remote): The remote host to check for SSH reachability.\n opts (ConnectionOptions, optional): Connection options such as timeout.\n If not provided, default values are used.\n\nReturns:\n CheckResult: An object indicating whether the SSH port is reachable (`ok=True`) or not (`ok=False`),\n and a reason if the check failed.\nUsage:\n result = check_machine_ssh_reachable(remote)\n if result.ok:\n print(\"SSH port is reachable\")\n print(f\"SSH port is not reachable: {result.reason}\")\n\n", + "tags": [ + "Machine / Ssh / Reachable" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_ssh_reachable_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_ssh_reachable_return" + } + } + } + } + } + } + }, + "/list_machine_state": { + "post": { + "summary": "list_machine_state", + "operationId": "list_machine_state", + "description": "Retrieve the current state of all machines in the clan.\n\nArgs:\n flake (Flake): The flake object representing the configuration source.\n\n", + "tags": [ + "Machine / State" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_machine_state_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_machine_state_return" + } + } + } + } + } + } + }, + "/get_machine_state": { + "post": { + "summary": "get_machine_state", + "operationId": "get_machine_state", + "description": "Retrieve the current state of the machine.\n\nArgs:\n machine (Machine): The machine object for which we want to retrieve the latest state.\n\n", + "tags": [ + "Machine / State" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_state_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_machine_state_return" + } + } + } + } + } + } + }, + "/check_machine_up_to_date": { + "post": { + "summary": "check_machine_up_to_date", + "operationId": "check_machine_up_to_date", + "description": "Check if a machine needs an update.\n\nArgs:\n machine: The Machine instance to check.\n target_host: Optional Remote or LocalHost instance representing the target host.\n\nReturns:\n bool: True if the machine needs an update, False otherwise.\n\n", + "tags": [ + "Machine / Up / To / Date" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_up_to_date_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/check_machine_up_to_date_return" + } + } + } + } + } + } + }, + "/run_machine_update": { + "post": { + "summary": "run_machine_update", + "operationId": "run_machine_update", + "description": "Update an existing machine using nixos-rebuild or darwin-rebuild.\n\nArgs:\n machine: The Machine instance to deploy.\n target_host: Remote object representing the target host for deployment.\n build_host: Optional Remote object representing the build host.\n upload_inputs: Whether to upload flake inputs from the local.\n\nRaises:\n ClanError: If the machine is not found in the inventory or if there are issues with\n generating facts or variables.\n\n", + "tags": [ + "Machine / Update" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_update_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_machine_update_return" + } + } + } + } + } + } + }, + "/create_secrets_user": { + "post": { + "summary": "create_secrets_user", + "operationId": "create_secrets_user", + "description": "Initialize sops keys for vars", + "tags": [ + "Secret / User" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_secrets_user_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_secrets_user_return" + } + } + } + } + } + } + }, + "/create_service_instance": { + "post": { + "summary": "create_service_instance", + "operationId": "create_service_instance", + "description": "Show information about a module", + "tags": [ + "Service / Instance" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_service_instance_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_service_instance_return" + } + } + } + } + } + } + }, + "/list_service_instances": { + "post": { + "summary": "list_service_instances", + "operationId": "list_service_instances", + "description": "Returns all currently present service instances including their full configuration", + "tags": [ + "Service / Instance" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_service_instances_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_service_instances_return" + } + } + } + } + } + } + }, + "/list_service_modules": { + "post": { + "summary": "list_service_modules", + "operationId": "list_service_modules", + "description": "Show information about a module", + "tags": [ + "Service / Module" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_service_modules_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_service_modules_return" + } + } + } + } + } + } + }, + "/get_service_module_schema": { + "post": { + "summary": "get_service_module_schema", + "operationId": "get_service_module_schema", + "description": "Returns the schema for a service module\n\n:param module_ref: The module reference to get the schema for\n:return: Dict of schemas for the service module roles\n:raises ClanError: If the module_ref is invalid or missing required fields\n", + "tags": [ + "Service / Module / Schema" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_service_module_schema_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_service_module_schema_return" + } + } + } + } + } + } + }, + "/get_system_file": { + "post": { + "summary": "get_system_file", + "operationId": "get_system_file", + "description": "Api method to open a file dialog window.\n\nImplementations is specific to the platform and\nreturns the name of the selected file or None if no file was selected.\n", + "tags": [ + "System / File" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_system_file_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/get_system_file_return" + } + } + } + } + } + } + }, + "/list_system_services_mdns": { + "post": { + "summary": "list_system_services_mdns", + "operationId": "list_system_services_mdns", + "description": "List mDNS/DNS-SD services on the local network.\n\nReturns:\n DNSInfo: A dictionary containing discovered mDNS/DNS-SD services.\n\n", + "tags": [ + "System / Service / Mdn" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_system_services_mdns_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_system_services_mdns_return" + } + } + } + } + } + } + }, + "/list_system_storage_devices": { + "post": { + "summary": "list_system_storage_devices", + "operationId": "list_system_storage_devices", + "description": "List local block devices by running `lsblk`.\n\nReturns:\n A list of detected block devices with metadata like size, path, type, etc.\n\n", + "tags": [ + "System / Storage / Device" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_system_storage_devices_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_system_storage_devices_return" + } + } + } + } + } + } + }, + "/list_tags": { + "post": { + "summary": "list_tags", + "operationId": "list_tags", + "description": "List all tags of a clan.\n\nReturns:\n - 'options' - Existing Tags that can be added to machines\n - 'special' - Prefined Tags that are special and cannot be added to machines, they can be used in roles and refer to a fixed set of machines.\n\n", + "tags": [ + "Tag" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_tags_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_tags_return" + } + } + } + } + } + } + }, + "/delete_task": { + "post": { + "summary": "delete_task", + "operationId": "delete_task", + "description": "Cancel a task by its op_key.", + "tags": [ + "Task" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/delete_task_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/delete_task_return" + } + } + } + } + } + } + }, + "/list_tasks": { + "post": { + "summary": "list_tasks", + "operationId": "list_tasks", + "description": "List all tasks.", + "tags": [ + "Task" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_tasks_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/list_tasks_return" + } + } + } + } + } + } + }, + "/run_task_blocking": { + "post": { + "summary": "run_task_blocking", + "operationId": "run_task_blocking", + "description": "A long blocking task that simulates a long-running operation.", + "tags": [ + "Task / Blocking" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_task_blocking_args" + } + } + } + }, + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_task_blocking_return" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "get_system_file_args": { + "type": "object", + "required": [ + "file_request" + ], + "additionalProperties": false, + "properties": { + "file_request": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "get_system_file", + "select_folder", + "save", + "open_multiple_files" + ] + }, + "title": { + "type": "string", + "nullable": true + }, + "filters": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": true + }, + "mime_types": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "patterns": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "suffixes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false, + "nullable": true + }, + "initial_file": { + "type": "string", + "nullable": true + }, + "initial_folder": { + "type": "string", + "nullable": true + } + }, + "required": [ + "mode" + ], + "additionalProperties": false + } + } + }, + "get_system_file_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_clan_folder_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "get_clan_folder_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_system_storage_devices_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "list_system_storage_devices_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "blockdevices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "id_link": { + "type": "string" + }, + "path": { + "type": "string" + }, + "rm": { + "type": "string" + }, + "size": { + "type": "string" + }, + "ro": { + "type": "boolean" + }, + "mountpoints": { + "type": "array", + "items": { + "type": "string" + } + }, + "type_": { + "type": "string", + "enum": [ + "disk" + ] + } + }, + "required": [ + "id_link", + "mountpoints", + "name", + "path", + "rm", + "ro", + "size", + "type_" + ], + "additionalProperties": false + } + } + }, + "required": [ + "blockdevices" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_clan_directory_relative_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "get_clan_directory_relative_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "string" + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_system_services_mdns_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "list_system_services_mdns_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "services": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "interface": { + "type": "string" + }, + "protocol": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type_": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "host": { + "type": "string", + "nullable": true + }, + "ip": { + "type": "string", + "nullable": true + }, + "port": { + "type": "string", + "nullable": true + }, + "txt": { + "type": "string", + "nullable": true + } + }, + "required": [ + "domain", + "host", + "interface", + "ip", + "name", + "port", + "protocol", + "txt", + "type_" + ], + "additionalProperties": false + } + } + }, + "required": [ + "services" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "delete_task_args": { + "type": "object", + "required": [ + "task_id" + ], + "additionalProperties": false, + "properties": { + "task_id": { + "type": "string" + } + } + }, + "delete_task_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_task_blocking_args": { + "type": "object", + "required": [ + "somearg" + ], + "additionalProperties": false, + "properties": { + "somearg": { + "type": "string" + } + } + }, + "run_task_blocking_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "string" + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_tasks_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "list_tasks_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_host_args": { + "type": "object", + "required": [ + "name", + "flake", + "field" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "field": { + "type": "string", + "enum": [ + "targetHost", + "buildHost" + ] + } + } + }, + "get_machine_host_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + "source": { + "type": "string", + "enum": [ + "inventory", + "machine" + ] + } + }, + "required": [ + "data", + "source" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "check_clan_valid_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "check_clan_valid_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "boolean" + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_machines_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "opts": { + "type": "object", + "properties": { + "filter": { + "type": "object", + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "nullable": true + } + } + }, + "list_machines_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "instance_refs": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_args": { + "type": "object", + "required": [ + "flake", + "name" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "name": { + "type": "string" + } + } + }, + "get_machine_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "set_machine_args": { + "type": "object", + "required": [ + "machine", + "update" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "update": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + } + }, + "set_machine_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_fields_schema_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + } + }, + "get_machine_fields_schema_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "readonly": { + "type": "boolean" + }, + "reason": { + "type": "string", + "nullable": true + }, + "readonly_members": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "readonly", + "readonly_members", + "reason" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_machine_state_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "list_machine_state_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "not_installed", + "offline", + "out_of_sync", + "online" + ] + } + }, + "required": [ + "status" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_state_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + } + }, + "get_machine_state_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "not_installed", + "offline", + "out_of_sync", + "online" + ] + } + }, + "required": [ + "status" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "create_clan_args": { + "type": "object", + "required": [ + "opts" + ], + "additionalProperties": false, + "properties": { + "opts": { + "type": "object", + "properties": { + "dest": { + "type": "string" + }, + "template": { + "type": "string" + }, + "src_flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false, + "nullable": true + }, + "setup_git": { + "type": "boolean" + }, + "initial": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false, + "nullable": true + }, + "update_clan": { + "type": "boolean" + } + }, + "required": [ + "dest", + "template" + ], + "additionalProperties": false + } + } + }, + "create_clan_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_clan_details_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "get_clan_details_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_clan_details_schema_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "get_clan_details_schema_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "readonly": { + "type": "boolean" + }, + "reason": { + "type": "string", + "nullable": true + }, + "readonly_members": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "readonly", + "readonly_members", + "reason" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "set_clan_details_args": { + "type": "object", + "required": [ + "options" + ], + "additionalProperties": false, + "properties": { + "options": { + "type": "object", + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "meta": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "meta" + ], + "additionalProperties": false + } + } + }, + "set_clan_details_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "machines": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "instances": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "module": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "roles": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "extraModules": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "string" + } + ] + } + }, + "machines": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "settings": {} + }, + "additionalProperties": false + } + }, + "settings": {}, + "tags": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "meta": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_machine_hardware_info_args": { + "type": "object", + "required": [ + "opts", + "target_host" + ], + "additionalProperties": false, + "properties": { + "opts": { + "type": "object", + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "backend": { + "type": "string", + "enum": [ + "nixos-facter", + "nixos-generate-config", + "none" + ] + }, + "password": { + "type": "string", + "nullable": true + } + }, + "required": [ + "machine" + ], + "additionalProperties": false + }, + "target_host": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + } + } + }, + "run_machine_hardware_info_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "string", + "enum": [ + "nixos-facter", + "nixos-generate-config", + "none" + ] + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_hardware_summary_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + } + }, + "get_machine_hardware_summary_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "hardware_config": { + "type": "string", + "enum": [ + "nixos-facter", + "nixos-generate-config", + "none" + ] + }, + "platform": { + "type": "string", + "nullable": true + } + }, + "required": [ + "hardware_config", + "platform" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_service_modules_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "list_service_modules_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "modules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "usage_ref": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "info": { + "type": "object", + "properties": { + "manifest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "categories": { + "type": "array", + "items": { + "type": "string" + } + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "description", + "name" + ], + "additionalProperties": false + }, + "roles": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } + }, + "required": [ + "manifest", + "roles" + ], + "additionalProperties": false + }, + "native": { + "type": "boolean" + }, + "instance_refs": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "info", + "instance_refs", + "native", + "usage_ref" + ], + "additionalProperties": false + } + }, + "core_input_name": { + "type": "string" + } + }, + "required": [ + "core_input_name", + "modules" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_service_module_schema_args": { + "type": "object", + "required": [ + "flake", + "module_ref" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "module_ref": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + } + }, + "get_service_module_schema_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "create_service_instance_args": { + "type": "object", + "required": [ + "flake", + "module_ref", + "roles" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "module_ref": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "roles": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "extraModules": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "string" + } + ] + } + }, + "machines": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "settings": {} + }, + "additionalProperties": false + } + }, + "settings": {}, + "tags": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "additionalProperties": false + } + } + } + }, + "create_service_instance_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_service_instances_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "list_service_instances_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "resolved": { + "type": "object", + "properties": { + "usage_ref": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "info": { + "type": "object", + "properties": { + "manifest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "categories": { + "type": "array", + "items": { + "type": "string" + } + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "description", + "name" + ], + "additionalProperties": false + }, + "roles": { + "type": "object", + "additionalProperties": { + "nullable": true + } + } + }, + "required": [ + "manifest", + "roles" + ], + "additionalProperties": false + }, + "native": { + "type": "boolean" + }, + "instance_refs": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "info", + "instance_refs", + "native", + "usage_ref" + ], + "additionalProperties": false + }, + "module": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "roles": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "extraModules": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "string" + } + ] + } + }, + "machines": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "settings": {} + }, + "additionalProperties": false + } + }, + "settings": {}, + "tags": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "module", + "resolved", + "roles" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_disk_schemas_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "check_hw": { + "type": "boolean" + } + } + }, + "get_machine_disk_schemas_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "readme": { + "type": "string" + }, + "frontmatter": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + }, + "required": [ + "description" + ], + "additionalProperties": false + }, + "placeholders": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "required": { + "type": "boolean" + } + }, + "required": [ + "label", + "options", + "required" + ], + "additionalProperties": false + } + } + }, + "required": [ + "frontmatter", + "name", + "placeholders", + "readme" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "set_machine_disk_schema_args": { + "type": "object", + "required": [ + "machine", + "schema_name", + "placeholders" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "schema_name": { + "type": "string" + }, + "placeholders": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "force": { + "type": "boolean" + }, + "check_hw": { + "type": "boolean" + } + } + }, + "set_machine_disk_schema_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_details_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + } + }, + "get_machine_details_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "machine": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "hw_config": { + "type": "string", + "enum": [ + "nixos-facter", + "nixos-generate-config", + "none" + ], + "nullable": true + }, + "disk_schema": { + "type": "object", + "properties": { + "schema_name": { + "type": "string" + }, + "placeholders": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "placeholders", + "schema_name" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "machine" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_generators_args": { + "type": "object", + "required": [ + "machines", + "full_closure" + ], + "additionalProperties": false, + "properties": { + "machines": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + }, + "full_closure": { + "type": "boolean" + }, + "generator_name": { + "type": "string", + "nullable": true + }, + "include_previous_values": { + "type": "boolean" + } + } + }, + "get_generators_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "files": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "secret": { + "type": "boolean" + }, + "deploy": { + "type": "boolean" + }, + "owner": { + "type": "string" + }, + "group": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "needed_for": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "additionalProperties": false + } + }, + "share": { + "type": "boolean" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "prompt_type": { + "type": "string", + "enum": [ + "line", + "hidden", + "multiline", + "multiline-hidden" + ] + }, + "persist": { + "type": "boolean" + }, + "previous_value": { + "type": "string", + "nullable": true + }, + "display": { + "type": "object", + "properties": { + "label": { + "type": "string", + "nullable": true + }, + "group": { + "type": "string", + "nullable": true + }, + "helperText": { + "type": "string", + "nullable": true + }, + "required": { + "type": "boolean" + } + }, + "required": [ + "group", + "helperText", + "label", + "required" + ], + "additionalProperties": false + } + }, + "required": [ + "description", + "name", + "prompt_type" + ], + "additionalProperties": false + } + }, + "dependencies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "machine": { + "type": "string", + "nullable": true + }, + "name": { + "type": "string" + } + }, + "required": [ + "machine", + "name" + ], + "additionalProperties": false + } + }, + "migrate_fact": { + "type": "string", + "nullable": true + }, + "validation_hash": { + "type": "string", + "nullable": true + }, + "machine": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_generators_args": { + "type": "object", + "required": [ + "machines" + ], + "additionalProperties": false, + "properties": { + "machines": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + }, + "generators": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "full_closure": { + "type": "boolean" + }, + "prompt_values": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "no_sandbox": { + "type": "boolean" + } + } + }, + "run_generators_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_machine_flash_options_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "get_machine_flash_options_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "languages": { + "type": "array", + "items": { + "type": "string" + } + }, + "keymaps": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "keymaps", + "languages" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_machine_flash_args": { + "type": "object", + "required": [ + "disks", + "system_config" + ], + "additionalProperties": false, + "properties": { + "disks": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "device": { + "type": "string" + } + }, + "required": [ + "device", + "name" + ], + "additionalProperties": false + } + }, + "system_config": { + "type": "object", + "properties": { + "keymap": { + "type": "string" + }, + "language": { + "type": "string" + }, + "ssh_keys_path": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "mode": { + "type": "string", + "enum": [ + "format", + "mount" + ] + }, + "dry_run": { + "type": "boolean" + }, + "write_efi_boot_entries": { + "type": "boolean" + }, + "debug": { + "type": "boolean" + }, + "extra_args": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "graphical": { + "type": "boolean" + } + } + }, + "run_machine_flash_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_log_days_args": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "list_log_days_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_log_groups_args": { + "type": "object", + "required": [ + "selector" + ], + "additionalProperties": false, + "properties": { + "selector": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "date_day": { + "type": "string", + "nullable": true + } + } + }, + "list_log_groups_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "get_log_file_args": { + "type": "object", + "required": [ + "id_key" + ], + "additionalProperties": false, + "properties": { + "id_key": { + "type": "string" + }, + "selector": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "date_day": { + "type": "string", + "nullable": true + } + } + }, + "get_log_file_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "string" + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "delete_machine_args": { + "type": "object", + "required": [ + "machine" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + } + } + }, + "delete_machine_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_machine_install_args": { + "type": "object", + "required": [ + "opts", + "target_host" + ], + "additionalProperties": false, + "properties": { + "opts": { + "type": "object", + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "kexec": { + "type": "string", + "nullable": true + }, + "anywhere_priv_key": { + "type": "string", + "nullable": true + }, + "debug": { + "type": "boolean" + }, + "no_reboot": { + "type": "boolean" + }, + "phases": { + "type": "string", + "nullable": true + }, + "build_on": { + "type": "string", + "enum": [ + "auto", + "local", + "remote" + ], + "nullable": true + }, + "update_hardware_config": { + "type": "string", + "enum": [ + "nixos-facter", + "nixos-generate-config", + "none" + ] + }, + "persist_state": { + "type": "boolean" + } + }, + "required": [ + "machine" + ], + "additionalProperties": false + }, + "target_host": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + } + } + }, + "run_machine_install_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "create_machine_args": { + "type": "object", + "required": [ + "opts" + ], + "additionalProperties": false, + "properties": { + "opts": { + "type": "object", + "properties": { + "clan_dir": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + }, + "machine": { + "type": "object", + "properties": { + "deploy": { + "type": "object", + "properties": { + "buildHost": { + "type": "string", + "nullable": true + }, + "targetHost": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "description": { + "type": "string", + "nullable": true + }, + "icon": { + "type": "string", + "nullable": true + }, + "installedAt": { + "type": "integer", + "nullable": true + }, + "machineClass": { + "type": "string", + "enum": [ + "nixos", + "darwin" + ] + }, + "name": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "template": { + "type": "string" + }, + "target_host": { + "type": "string", + "nullable": true + } + }, + "required": [ + "clan_dir", + "machine" + ], + "additionalProperties": false + }, + "commit": { + "type": "boolean" + } + } + }, + "create_machine_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "run_machine_update_args": { + "type": "object", + "required": [ + "machine", + "target_host", + "build_host" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "target_host": { + "oneOf": [ + { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "command_prefix": { + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "build_host": { + "oneOf": [ + { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "command_prefix": { + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "upload_inputs": { + "type": "boolean" + } + } + }, + "run_machine_update_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "check_machine_up_to_date_args": { + "type": "object", + "required": [ + "machine", + "target_host" + ], + "additionalProperties": false, + "properties": { + "machine": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "flake", + "name" + ], + "additionalProperties": false + }, + "target_host": { + "oneOf": [ + { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "command_prefix": { + "type": "string" + } + }, + "additionalProperties": false + } + ] + } + } + }, + "check_machine_up_to_date_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "boolean" + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "check_machine_ssh_login_args": { + "type": "object", + "required": [ + "remote" + ], + "additionalProperties": false, + "properties": { + "remote": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + "opts": { + "type": "object", + "properties": { + "timeout": { + "type": "integer" + } + }, + "additionalProperties": false, + "nullable": true + } + } + }, + "check_machine_ssh_login_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "check_machine_ssh_reachable_args": { + "type": "object", + "required": [ + "remote" + ], + "additionalProperties": false, + "properties": { + "remote": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "command_prefix": { + "type": "string", + "nullable": true + }, + "user": { + "type": "string" + }, + "port": { + "type": "integer", + "nullable": true + }, + "private_key": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "forward_agent": { + "type": "boolean" + }, + "host_key_check": { + "type": "string", + "enum": [ + "strict", + "ask", + "accept-new", + "tofu", + "none" + ] + }, + "verbose_ssh": { + "type": "boolean" + }, + "ssh_options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "socks_port": { + "type": "integer", + "nullable": true + }, + "socks_wrapper": { + "type": "object", + "properties": { + "cmd": { + "type": "array", + "items": { + "type": "string" + } + }, + "packages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "cmd", + "packages" + ], + "additionalProperties": false, + "nullable": true + } + }, + "required": [ + "address" + ], + "additionalProperties": false + }, + "opts": { + "type": "object", + "properties": { + "timeout": { + "type": "integer" + } + }, + "additionalProperties": false, + "nullable": true + } + } + }, + "check_machine_ssh_reachable_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "list_tags_args": { + "type": "object", + "required": [ + "flake" + ], + "additionalProperties": false, + "properties": { + "flake": { + "type": "object", + "properties": { + "identifier": { + "type": "string" + }, + "hash": { + "type": "string", + "nullable": true + }, + "store_path": { + "type": "string", + "nullable": true + }, + "nix_options": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "identifier" + ], + "additionalProperties": false + } + } + }, + "list_tags_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "type": "object", + "properties": { + "options": { + "type": "array", + "items": { + "type": "string" + } + }, + "special": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "options", + "special" + ], + "additionalProperties": false + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "create_secrets_user_args": { + "type": "object", + "required": [ + "flake_dir" + ], + "additionalProperties": false, + "properties": { + "flake_dir": { + "type": "string" + }, + "user": { + "type": "string", + "nullable": true + }, + "force": { + "type": "boolean" + } + } + }, + "create_secrets_user_return": { + "oneOf": [ + { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "The status of the response." + }, + "data": { + "nullable": true + } + }, + "required": [ + "data", + "op_key", + "status" + ], + "additionalProperties": false + }, + { + "$ref": "#/components/schemas/error" + } + ] + }, + "error": { + "type": "object", + "properties": { + "op_key": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "error" + ] + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "location": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "description", + "location", + "message" + ], + "additionalProperties": false + } + } + }, + "required": [ + "errors", + "op_key", + "status" + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/tested-trappist/package-lock.json b/tested-trappist/package-lock.json new file mode 100644 index 000000000..ffd8f9ef8 --- /dev/null +++ b/tested-trappist/package-lock.json @@ -0,0 +1,6571 @@ +{ + "name": "tested-trappist", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tested-trappist", + "version": "0.0.1", + "dependencies": { + "@astrojs/starlight": "^0.35.3", + "astro": "^5.6.1", + "sharp": "^0.34.2", + "starlight-openapi": "^0.20.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-13.0.5.tgz", + "integrity": "sha512-xfh4xVJD62gG6spIc7lwxoWT+l16nZu1ELyU8FkjaP/oD2yP09EvLAU6KhtudN9aML2Khhs9pY6Slr7KGTES3w==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, + "node_modules/@astrojs/compiler": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", + "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==", + "license": "MIT" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.2.tgz", + "integrity": "sha512-KCkCqR3Goym79soqEtbtLzJfqhTWMyVaizUi35FLzgGSzBotSw8DB1qwsu7U96ihOJgYhDk2nVPz+3LnXPeX6g==", + "license": "MIT" + }, + "node_modules/@astrojs/markdown-remark": { + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.6.tgz", + "integrity": "sha512-bwylYktCTsLMVoCOEHbn2GSUA3c5KT/qilekBKA3CBng0bo1TYjNZPr761vxumRk9kJGqTOtU+fgCAp5Vwokug==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.7.2", + "@astrojs/prism": "3.3.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "import-meta-resolve": "^4.1.0", + "js-yaml": "^4.1.0", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "shiki": "^3.2.1", + "smol-toml": "^1.3.4", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/mdx": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.5.tgz", + "integrity": "sha512-YB3Hhsvl1BxyY0ARe1OrnVzLNKDPXAz9epYvmL+MQ8A85duSsSLQaO3GHB6/qZJKNoLmP6PptOtCONCKkbhPeQ==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "6.3.6", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.15.0", + "es-module-lexer": "^1.7.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "kleur": "^4.1.5", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.6", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + }, + "peerDependencies": { + "astro": "^5.0.0" + } + }, + "node_modules/@astrojs/prism": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", + "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@astrojs/sitemap": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.6.0.tgz", + "integrity": "sha512-4aHkvcOZBWJigRmMIAJwRQXBS+ayoP5z40OklTXYXhUDhwusz+DyDl+nSshY6y9DvkVEavwNcFO8FD81iGhXjg==", + "license": "MIT", + "dependencies": { + "sitemap": "^8.0.0", + "stream-replace-string": "^2.0.0", + "zod": "^3.25.76" + } + }, + "node_modules/@astrojs/starlight": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.35.3.tgz", + "integrity": "sha512-z9MbODjZl/STU3PPU18iOTkLObJBw7PA8xMe5s+KPscQGL0LNZyQUYeClG+F1/em/k+2AsokGpVPta+aOTk1sg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "^6.3.1", + "@astrojs/mdx": "^4.2.3", + "@astrojs/sitemap": "^3.3.0", + "@pagefind/default-ui": "^1.3.0", + "@types/hast": "^3.0.4", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.4", + "astro-expressive-code": "^0.41.1", + "bcp-47": "^2.1.0", + "hast-util-from-html": "^2.0.1", + "hast-util-select": "^6.0.2", + "hast-util-to-string": "^3.0.0", + "hastscript": "^9.0.0", + "i18next": "^23.11.5", + "js-yaml": "^4.1.0", + "klona": "^2.0.6", + "mdast-util-directive": "^3.0.0", + "mdast-util-to-markdown": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "pagefind": "^1.3.0", + "rehype": "^13.0.1", + "rehype-format": "^5.0.0", + "remark-directive": "^3.0.0", + "ultrahtml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.2" + }, + "peerDependencies": { + "astro": "^5.5.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", + "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.2.0", + "debug": "^4.4.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "is-docker": "^3.0.0", + "is-wsl": "^3.1.0", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capsizecss/unpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-2.4.0.tgz", + "integrity": "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==", + "license": "MIT", + "dependencies": { + "blob-to-buffer": "^1.2.8", + "cross-fetch": "^3.0.4", + "fontkit": "^2.0.2" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@expressive-code/core": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.3.tgz", + "integrity": "sha512-9qzohqU7O0+JwMEEgQhnBPOw5DtsQRBXhW++5fvEywsuX44vCGGof1SL5OvPElvNgaWZ4pFZAFSlkNOkGyLwSQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.3.tgz", + "integrity": "sha512-rFQtmf/3N2CK3Cq/uERweMTYZnBu+CwxBdHuOftEmfA9iBE7gTVvwpbh82P9ZxkPLvc40UMhYt7uNuAZexycRQ==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.3.tgz", + "integrity": "sha512-RlTARoopzhFJIOVHLGvuXJ8DCEme/hjV+ZnRJBIxzxsKVpGPW4Oshqg9xGhWTYdHstTsxO663s0cdBLzZj9TQA==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3", + "shiki": "^3.2.2" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.3.tgz", + "integrity": "sha512-SN8tkIzDpA0HLAscEYD2IVrfLiid6qEdE9QLlGVSxO1KEw7qYvjpbNBQjUjMr5/jvTJ7ys6zysU2vLPHE0sb2g==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz", + "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz", + "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/default-ui": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz", + "integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==", + "license": "MIT" + }, + "node_modules/@pagefind/freebsd-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz", + "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz", + "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz", + "integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz", + "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@readme/better-ajv-errors": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-2.3.2.tgz", + "integrity": "sha512-T4GGnRAlY3C339NhoUpgJJFsMYko9vIgFAlhgV+/vEGFw66qEY4a4TRJIAZBcX/qT1pq5DvXSme+SQODHOoBrw==", + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/runtime": "^7.22.5", + "@humanwhocodes/momoa": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/openapi-parser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-4.1.2.tgz", + "integrity": "sha512-lAFH88r/CHs5VZDUocEda0OSMSQsr6801sziIjOKyVA+0hSFN+BPuelPF5XvkMROHecnPd+XEJN1iNQqCgER/g==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^13.0.5", + "@readme/better-ajv-errors": "^2.3.2", + "@readme/openapi-schemas": "^3.1.0", + "@types/json-schema": "^7.0.15", + "ajv": "^8.12.0", + "ajv-draft-04": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-schemas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz", + "integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", + "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", + "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", + "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", + "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", + "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", + "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.12.2.tgz", + "integrity": "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.12.2.tgz", + "integrity": "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz", + "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz", + "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.2" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz", + "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.2" + } + }, + "node_modules/@shikijs/types": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz", + "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/fontkit": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/fontkit/-/fontkit-2.0.8.tgz", + "integrity": "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "24.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.1.tgz", + "integrity": "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.12.0" + } + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "5.13.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.13.8.tgz", + "integrity": "sha512-SNURCAlfL4Z2ylF3NMmNk/s3RnSDSolXALXtH0gsN8hFZ7oppnF0sXVQLAGAxnzADemfRp3/9G58EALZ36qUdA==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^2.12.2", + "@astrojs/internal-helpers": "0.7.2", + "@astrojs/markdown-remark": "6.3.6", + "@astrojs/telemetry": "3.3.0", + "@capsizecss/unpack": "^2.4.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.2.0", + "acorn": "^8.15.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "boxen": "8.0.1", + "ci-info": "^4.3.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^1.0.1", + "cookie": "^1.0.2", + "cssesc": "^3.0.0", + "debug": "^4.4.1", + "deterministic-object-hash": "^2.0.2", + "devalue": "^5.3.2", + "diff": "^5.2.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "es-module-lexer": "^1.7.0", + "esbuild": "^0.25.0", + "estree-walker": "^3.0.3", + "flattie": "^1.1.1", + "fontace": "~0.3.0", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "import-meta-resolve": "^4.2.0", + "js-yaml": "^4.1.0", + "kleur": "^4.1.5", + "magic-string": "^0.30.18", + "magicast": "^0.3.5", + "mrmime": "^2.0.1", + "neotraverse": "^0.6.18", + "p-limit": "^6.2.0", + "p-queue": "^8.1.0", + "package-manager-detector": "^1.3.0", + "picomatch": "^4.0.3", + "prompts": "^2.4.2", + "rehype": "^13.0.2", + "semver": "^7.7.2", + "shiki": "^3.12.0", + "smol-toml": "^1.4.2", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tsconfck": "^3.1.6", + "ultrahtml": "^1.6.0", + "unifont": "~0.5.2", + "unist-util-visit": "^5.0.0", + "unstorage": "^1.17.0", + "vfile": "^6.0.3", + "vite": "^6.3.6", + "vitefu": "^1.1.1", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^21.1.1", + "yocto-spinner": "^0.2.3", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.24.6", + "zod-to-ts": "^1.2.0" + }, + "bin": { + "astro": "astro.js" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.34.0" + } + }, + "node_modules/astro-expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.3.tgz", + "integrity": "sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw==", + "license": "MIT", + "dependencies": { + "rehype-expressive-code": "^0.41.3" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/blob-to-buffer": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", + "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "license": "ISC" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cookie-es": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-selector-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.3.tgz", + "integrity": "sha512-gJMigczVZqYAk0hPVzx/M4Hm1D9QOtqkdQk9005TNzDIUGzo5cnHEDiKUT7jGPximL/oYb+LIitcHFQ4aKupxg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz", + "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/deterministic-object-hash": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", + "license": "MIT", + "dependencies": { + "base-64": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/devalue": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz", + "integrity": "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", + "license": "MIT" + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/emoji-regex": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.3.tgz", + "integrity": "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3", + "@expressive-code/plugin-frames": "^0.41.3", + "@expressive-code/plugin-shiki": "^0.41.3", + "@expressive-code/plugin-text-markers": "^0.41.3" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.0.tgz", + "integrity": "sha512-czoqATrcnxgWb/nAkfyIrRp6Q8biYj7nGnL6zfhTcX+JKKpWHFBnb8uNMw/kZr7u++3Y3wYSYoZgHkCcsuBpBg==", + "license": "MIT", + "dependencies": { + "@types/fontkit": "^2.0.8", + "fontkit": "^2.0.4" + } + }, + "node_modules/fontkit": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", + "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", + "license": "MIT", + "dependencies": { + "@swc/helpers": "^0.5.12", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/h3": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", + "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.2", + "crossws": "^0.3.5", + "defu": "^6.1.4", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.2", + "radix3": "^1.1.2", + "ufo": "^1.6.1", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", + "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "html-whitespace-sensitive-tag-names": "^3.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "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": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "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": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-whitespace-sensitive-tag-names": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", + "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/i18next": { + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "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-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "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-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "license": "CC0-1.0" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@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-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.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", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "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" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@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" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-mock-http": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", + "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/ofetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", + "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.3", + "node-fetch-native": "^1.6.4", + "ufo": "^1.5.4" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" + }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", + "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/p-limit": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT" + }, + "node_modules/pagefind": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz", + "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==", + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.4.0", + "@pagefind/darwin-x64": "1.4.0", + "@pagefind/freebsd-x64": "1.4.0", + "@pagefind/linux-arm64": "1.4.0", + "@pagefind/linux-x64": "1.4.0", + "@pagefind/windows-x64": "1.4.0" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "license": "MIT" + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", + "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.3.tgz", + "integrity": "sha512-8d9Py4c/V6I/Od2VIXFAdpiO2kc0SV2qTJsRAaqSIcM9aruW4ASLNe2kOEo1inXAAkIhpFzAHTc358HKbvpNUg==", + "license": "MIT", + "dependencies": { + "expressive-code": "^0.41.3" + } + }, + "node_modules/rehype-format": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", + "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-format": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restructure": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", + "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", + "license": "MIT" + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rollup": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.50.2", + "@rollup/rollup-android-arm64": "4.50.2", + "@rollup/rollup-darwin-arm64": "4.50.2", + "@rollup/rollup-darwin-x64": "4.50.2", + "@rollup/rollup-freebsd-arm64": "4.50.2", + "@rollup/rollup-freebsd-x64": "4.50.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", + "@rollup/rollup-linux-arm-musleabihf": "4.50.2", + "@rollup/rollup-linux-arm64-gnu": "4.50.2", + "@rollup/rollup-linux-arm64-musl": "4.50.2", + "@rollup/rollup-linux-loong64-gnu": "4.50.2", + "@rollup/rollup-linux-ppc64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-musl": "4.50.2", + "@rollup/rollup-linux-s390x-gnu": "4.50.2", + "@rollup/rollup-linux-x64-gnu": "4.50.2", + "@rollup/rollup-linux-x64-musl": "4.50.2", + "@rollup/rollup-openharmony-arm64": "4.50.2", + "@rollup/rollup-win32-arm64-msvc": "4.50.2", + "@rollup/rollup-win32-ia32-msvc": "4.50.2", + "@rollup/rollup-win32-x64-msvc": "4.50.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } + }, + "node_modules/shiki": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.12.2.tgz", + "integrity": "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.12.2", + "@shikijs/engine-javascript": "3.12.2", + "@shikijs/engine-oniguruma": "3.12.2", + "@shikijs/langs": "3.12.2", + "@shikijs/themes": "3.12.2", + "@shikijs/types": "3.12.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.0.tgz", + "integrity": "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==", + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/smol-toml": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", + "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/starlight-openapi": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/starlight-openapi/-/starlight-openapi-0.20.0.tgz", + "integrity": "sha512-IA8mBbuscQPUN5Fy5+7xxJqW9851FhRlWajAD4GOm2RYlaCesO8qrIq7qElfTIdcfi7XP8m3a+zxrJ7yz1FzYA==", + "license": "MIT", + "dependencies": { + "@readme/openapi-parser": "^4.1.2", + "github-slugger": "^2.0.0", + "url-template": "^3.1.1" + }, + "engines": { + "node": ">=18.17.1" + }, + "peerDependencies": { + "@astrojs/markdown-remark": ">=6.0.1", + "@astrojs/starlight": ">=0.34.0", + "astro": ">=5.5.0" + } + }, + "node_modules/stream-replace-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", + "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", + "license": "MIT" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", + "license": "MIT" + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.5.2.tgz", + "integrity": "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0", + "ofetch": "^1.4.1", + "ohash": "^2.0.0" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.1.tgz", + "integrity": "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^4.0.3", + "destr": "^2.0.5", + "h3": "^1.15.4", + "lru-cache": "^10.4.3", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.4.1", + "ufo": "^1.6.1" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6.0.3 || ^7.0.0", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1.0.1", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/url-template": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-3.1.1.tgz", + "integrity": "sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA==", + "license": "BSD-3-Clause", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", + "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", + "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-spinner": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", + "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", + "license": "MIT", + "dependencies": { + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18.19" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, + "node_modules/zod-to-ts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", + "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", + "peerDependencies": { + "typescript": "^4.9.4 || ^5.0.2", + "zod": "^3" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/tested-trappist/package.json b/tested-trappist/package.json new file mode 100644 index 000000000..ca39747c6 --- /dev/null +++ b/tested-trappist/package.json @@ -0,0 +1,18 @@ +{ + "name": "tested-trappist", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/starlight": "^0.35.3", + "astro": "^5.6.1", + "sharp": "^0.34.2", + "starlight-openapi": "^0.20.0" + } +} diff --git a/tested-trappist/public/favicon.svg b/tested-trappist/public/favicon.svg new file mode 100644 index 000000000..43aa47bce --- /dev/null +++ b/tested-trappist/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tested-trappist/public/logo.svg b/tested-trappist/public/logo.svg new file mode 100644 index 000000000..e164bb029 --- /dev/null +++ b/tested-trappist/public/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tested-trappist/src/assets/houston.webp b/tested-trappist/src/assets/houston.webp new file mode 100644 index 0000000000000000000000000000000000000000..930c164974ad8eb528878f15a98016249b8cf546 GIT binary patch literal 98506 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 b6~t;_wBcJ3AWgga7~Sz~izoKbpAY~5r|m$8 literal 0 HcmV?d00001 diff --git a/tested-trappist/src/content.config.ts b/tested-trappist/src/content.config.ts new file mode 100644 index 000000000..d9ee8c9d1 --- /dev/null +++ b/tested-trappist/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/tested-trappist/src/content/docs/getting-started/add-machines.md b/tested-trappist/src/content/docs/getting-started/add-machines.md new file mode 100644 index 000000000..77644810e --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/add-machines.md @@ -0,0 +1,128 @@ +--- +title: How to add machines +--- + +Machines can be added using the following methods + +- Create a file `machines/{machine_name}/configuration.nix` (See: [File Autoincludes](../inventory/autoincludes.md)) +- Imperative via cli command: `clan machines create` +- Editing nix expressions in flake.nix See [`clan-core.lib.clan`](/options/?scope=Flake Options (clan.nix file)) + +See the complete [list](../inventory/autoincludes.md) of auto-loaded files. + +## Create a machine + +=== "clan.nix (declarative)" + + ```{.nix hl_lines="3-4"} + { + inventory.machines = { + # Define a machine + jon = { }; + }; + + # Additional NixOS configuration can be added here. + # machines/jon/configuration.nix will be automatically imported. + # See: https://docs.clan.lol/guides/more-machines/#automatic-registration + machines = { + # jon = { config, ... }: { + # environment.systemPackages = [ pkgs.asciinema ]; + # }; + }; + } + ``` + +=== "CLI (imperative)" + + ```sh + clan machines create jon + ``` + + The imperative command might create a machine folder in `machines/jon` + And might persist information in `inventory.json` + +### Configuring a machine + +:::note +The option: `inventory.machines.` is used to define metadata about the machine +That includes for example `deploy.targethost` `machineClass` or `tags` + +The option: `machines.` is used to add extra *nixosConfiguration* to a machine +::: + +Add the following to your `clan.nix` file for each machine. +This example demonstrates what is needed based on a machine called `jon`: + +```nix title="clan.nix" {3-6, 15-19} +{ + inventory.machines = { + jon = { + # Define tags here (optional) + tags = [ ]; # (1) + }; + sara = { + deploy.targetHost = "root@sara"; + tags = [ ]; + }; + }; + # Define additional nixosConfiguration here + # Or in /machines/jon/configuration.nix (autoloaded) + machines = { + jon = { config, pkgs, ... }: { + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC..." # elided (2) + ]; + }; + }; +} +``` + +1. Tags can be used to automatically add this machine to services later on. - You dont need to set this now. +2. Add your *ssh key* here - That will ensure you can always login to your machine via *ssh* in case something goes wrong. + +### (Optional) Create a `configuration.nix` + +```nix title="./machines/jon/configuration.nix" +{ + imports = [ + # enables GNOME desktop (optional) + ../../modules/gnome.nix + ]; + + # Set nixosOptions here + # Or import your own modules via 'imports' + # ... +} +``` + +### (Optional) Renaming a Machine + +Older templates included static machine folders like `jon` and `sara`. +If your setup still uses such static machines, you can rename a machine folder to match your own machine name: + +```bash +git mv ./machines/jon ./machines/ +``` + +Since your Clan configuration lives inside a Git repository, remember: + +* Only files tracked by Git (`git add`) are recognized. +* Whenever you add, rename, or remove files, run: + +```bash +git add ./machines/ +``` + +to stage the changes. + +--- + +### (Optional) Removing a Machine + +If you want to work with a single machine for now, you can remove other machine entries both from your `flake.nix` and from the `machines` directory. For example, to remove the machine `sara`: + +```bash +git rm -rf ./machines/sara +``` + +Make sure to also remove or update any references to that machine in your `nix files` or `inventory.json` if you have any of that diff --git a/tested-trappist/src/content/docs/getting-started/add-services.md b/tested-trappist/src/content/docs/getting-started/add-services.md new file mode 100644 index 000000000..2f5b355da --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/add-services.md @@ -0,0 +1,80 @@ +--- +title: How to add services +--- + +A service in clan is a self-contained, reusable unit of system configuration that provides a specific piece of functionality across one or more machines. + +Think of it as a recipe for running a tool β€” like automatic backups, VPN networking, monitoring, etc. + +In Clan Services are multi-Host & role-based: + +- Roles map machines to logical service responsibilities, enabling structured, clean deployments. + +- You can use tags instead of explicit machine names. + +To learn more: [Guide about clanService](../inventory/clanServices.md) + +:::caution +It is recommended to add at least one networking service such as `zerotier` that allows to reach all your clan machines from your setup computer across the globe. +::: + +## Configure a Zerotier Network (recommended) + +```{.nix title="clan.nix" hl_lines="8-16"} +{ + inventory.machines = { + jon = { }; + sara = { }; + }; + + inventory.instances = { + zerotier = { # (1) + # Replace with the name (string) of your machine that you will use as zerotier-controller + # See: https://docs.zerotier.com/controller/ + # Deploy this machine first to create the network secrets + roles.controller.machines."jon" = { }; # (2) + # Peers of the network + # this line means 'all' clan machines will be 'peers' + roles.peer.tags.all = { }; # (3) + }; + }; + # ... + # elided +} +``` + +1. See [reference/clanServices](../../reference/clanServices/index.md) for all available services and how to configure them. + Or read [authoring/clanServices](../services/community.md) if you want to bring your own + +2. Replace `__YOUR_CONTROLLER_` with the *name* of your machine. + +3. This line will add all machines of your clan as `peer` to zerotier + +## Adding more recommended defaults + +Adding the following services is recommended for most users: + +```{.nix title="clan.nix" hl_lines="7-14"} +{ + inventory.machines = { + jon = { }; + sara = { }; + }; + inventory.instances = { + admin = { # (1) + roles.default.tags.all = { }; + roles.default.settings = { + allowedKeys = { + "my-user" = "ssh-ed25519 AAAAC3N..."; # (2) + }; + }; + }; + # ... + # elided + }; +} +``` + +1. The `admin` service will generate a **root-password** and **add your ssh-key** that allows for convienient administration. +2. Equivalent to directly setting `authorizedKeys` like in [configuring a machine](./add-machines.md#configuring-a-machine) +3. Adds `user = jon` as a user on all machines. Will create a `home` directory, and prompt for a password before deployment. diff --git a/tested-trappist/src/content/docs/getting-started/add-user.md b/tested-trappist/src/content/docs/getting-started/add-user.md new file mode 100644 index 000000000..9606e2d4c --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/add-user.md @@ -0,0 +1,131 @@ +--- +title: How to add users +--- + +:::note[Under construction] + +The users concept of clan is not done yet. This guide outlines some solutions from our community. +Defining users can be done in many different ways. We want to highlight two approaches: + +- Using clan's [users](../../reference/clanServices/users.md) service. +- Using a custom approach. +::: + +## Adding Users using the [users](../../reference/clanServices/users.md) service + +To add a first *user* this guide will be leveraging two things: + +- [clanServices](../../reference/clanServices/index.md): Allows to bind arbitrary logic to something we call an `Γ¬nstance`. +- [clanServices/users](../../reference/clanServices/users.md): Implements logic for adding a single user perInstance. + +The example shows how to add a user called `jon`: + +```{.nix title="clan.nix" hl_lines="7-21"} +{ + inventory.machines = { + jon = { }; + sara = { }; + }; + inventory.instances = { + jon-user = { # (1) + module.name = "users"; + + roles.default.tags.all = { }; # (2) + + roles.default.settings = { + user = "jon"; # (3) + groups = [ + "wheel" # Allow using 'sudo' + "networkmanager" # Allows to manage network connections. + "video" # Allows to access video devices. + "input" # Allows to access input devices. + ]; + }; + }; + # ... + # elided + }; +} +``` + +1. Add `user = jon` as a user on all machines. Will create a `home` directory, and prompt for a password before deployment. +2. Add this user to `all` machines +3. Define the `name` of the user to be `jon` + +The `users` service creates a `/home/jon` directory, allows `jon` to sign in and will take care of the user's password. + +For more information see [clanService/users](../../reference/clanServices/users.md) + +## Using a custom approach + +Some people like to define a `users` folder in their repository root. +That allows to bind all user specific logic to a single place (`default.nix`) +Which can be imported into individual machines to make the user available on that machine. + +```bash +. +β”œβ”€β”€ machines +β”‚Β Β  β”œβ”€β”€ jon +# ...... +β”œβ”€β”€ users +β”‚Β Β  β”œβ”€β”€ jon +β”‚ β”‚ └── default.nix # <- a NixOS module; sets some options +# ... ... ... +``` + +## using [home-manager](https://github.com/nix-community/home-manager) + +When using clan's `users` service it is possible to define extraModules. +In fact this is always possible when using clan's services. + +We can use this property of clan services to bind a nixosModule to the user, which configures home-manager. + +```{.nix title="clan.nix" hl_lines="22"} +{ + inventory.machines = { + jon = { }; + sara = { }; + }; + inventory.instances = { + jon-user = { + module.name = "users"; + + roles.default.tags.all = { }; + + roles.default.settings = { + user = "jon", + groups = [ + "wheel" + "networkmanager" + "video" + "input" + ]; + }; + + roles.default.extraModules = [ ./users/jon/home.nix ]; # (1) + }; + # ... + # elided + }; +} +``` + +1. Type `path` or `string`: Must point to a separate file. Inlining a module is not possible + +:::Note[This is inspiration] +Our community might come up with better solutions soon. +We are seeking contributions to improve this pattern if you have a nicer solution in mind. +::: + +```nix title="users/jon/home.nix" +# NixOS module to import home-manager and the home-manager configuration of 'jon' +{ self, ...}: +{ + imports = [ self.inputs.home-manager.nixosModules.default ]; + home-manager.users.jon = { + imports = [ + ./home-configuration.nix + ]; + }; +} +``` diff --git a/tested-trappist/src/content/docs/getting-started/choose-disk.md b/tested-trappist/src/content/docs/getting-started/choose-disk.md new file mode 100644 index 000000000..427abd31c --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/choose-disk.md @@ -0,0 +1,79 @@ +--- +title: Configure Disk Config +--- + +By default clan uses [disko](https://github.com/nix-community/disko) which allows for declarative disk partitioning. + +To see what disk templates are available run: +```{.shellSession hl_lines="10" .no-copy} +$ clan templates list + +Available 'clan' template +β”œβ”€β”€ +β”‚ β”œβ”€β”€ default: Initialize a new clan flake +β”‚ β”œβ”€β”€ flake-parts: Flake-parts +β”‚ └── minimal: for clans managed via (G)UI +Available 'disko' templates +β”œβ”€β”€ +β”‚ └── single-disk: A simple ext4 disk with a single partition +Available 'machine' templates +β”œβ”€β”€ +β”‚ β”œβ”€β”€ demo-template: Demo machine for the CLAN project +β”‚ β”œβ”€β”€ flash-installer: Initialize a new flash-installer machine +β”‚ β”œβ”€β”€ new-machine: Initialize a new machine +β”‚ └── test-morph-template: Morph a machine +``` + + +For this guide we will select the `single-disk` template, that uses `A simple ext4 disk with a single partition`. + +:::tip +For advanced partitioning, see [Disko templates](https://github.com/nix-community/disko-templates) or [Disko examples](https://github.com/nix-community/disko/tree/master/example). +You can also [contribute a disk template to clan core](https://docs.clan.lol/guides/disko-templates/community/) +::: + +To setup a disk schema for a machine run + +```bash +clan templates apply disk single-disk jon --set mainDisk "" +``` + +Which should fail and give the valid options for the specific hardware: + +```shellSession +Invalid value for placeholder mainDisk - Valid options: +/dev/disk/by-id/nvme-WD_PC_SN740_SDDQNQD-512G-1201_232557804368 +``` + +Re-run the command with the correct disk: + +```bash +clan templates apply disk single-disk jon --set mainDisk "/dev/disk/by-id/nvme-WD_PC_SN740_SDDQNQD-512G-1201_232557804368" +``` + +Should now be successful + +```shellSession +Applied disk template 'single-disk' to machine 'jon' +``` + +A disko.nix file should be created in `machines/jon` +You can have a look and customize it if needed. + +:::danger +Don't change the `disko.nix` after the machine is installed for the first time, unless you really know what you are doing. +Changing disko configuration requires wiping and reinstalling the machine. +::: + +## Deploy the machine + +**Finally deployment time!** + +This command is destructive and will format your disk and install NixOS on it! It is equivalent to appending `--phases kexec,disko,install,reboot`. + + +```bash +clan machines install [MACHINE] --target-host root@ +``` + + diff --git a/tested-trappist/src/content/docs/getting-started/convert-flake.md b/tested-trappist/src/content/docs/getting-started/convert-flake.md new file mode 100644 index 000000000..9e0ee87c1 --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/convert-flake.md @@ -0,0 +1,183 @@ +--- +title: Convert existing NixOS configurations +--- + +This guide will help you convert your existing NixOS configurations into a Clan. + +:::caution +Migrating instead of starting new can be trickier and might lead to bugs or +unexpected issues. We recommend reading the [Getting Started](./index.md) guide first. + +Once you have a working setup and understand the concepts transfering your NixOS configurations over is easy. +::: + +## Back up your existing configuration + +Before you start, it is strongly recommended to back up your existing +configuration in any form you see fit. If you use version control to manage +your configuration changes, it is also a good idea to follow the migration +guide in a separte branch until everything works as expected. + +## Starting Point + +We assume you are already using NixOS flakes to manage your configuration. If +not, migrate to a flake-based setup following the official [NixOS +documentation](https://nix.dev/manual/nix/2.25/command-ref/new-cli/nix3-flake.html). +The snippet below shows a common Nix flake. For this example we will assume you +have have two hosts: **berlin** and **cologne**. + +```nix +{ + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + + outputs = { self, nixpkgs, ... }: { + + nixosConfigurations = { + + berlin = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ ./machines/berlin/configuration.nix ]; + }; + + cologne = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ ./machines/cologne/configuration.nix ]; + }; + }; + }; +} +``` + +## 1. Add `clan-core` to `inputs` + +Add `clan-core` to your flake as input. + +```nix +inputs.clan-core = { + url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; + # Don't do this if your machines are on nixpkgs stable. + inputs.nixpkgs.follows = "nixpkgs"; +} +``` + +## 2. Update Outputs + +To be able to access our newly added dependency, it has to be added to the +output parameters. + +```diff +- outputs = { self, nixpkgs, ... }: ++ outputs = { self, nixpkgs, clan-core }: +``` + +The existing `nixosConfigurations` output of your flake will be created by +clan. In addition, a new `clanInternals` output will be added. Since both of +these are provided by the output of `clan-core.lib.clan`, a common syntax is to use a +`let...in` statement to create your clan and access it's parameters in the flake +outputs. + +For the provide flake example, your flake should now look like this: + +```nix +{ + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + + inputs.clan-core = { + url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { self, nixpkgs, clan-core, ... }: + let + clan = clan-core.lib.clan { + self = self; # this needs to point at the repository root + specialArgs = {}; + meta.name = throw "Change me to something unique"; + + machines = { + berlin = { + nixpkgs.hostPlatform = "x86_64-linux"; + imports = [ ./machines/berlin/configuration.nix ]; + }; + cologne = { + nixpkgs.hostPlatform = "x86_64-linux"; + imports = [ ./machines/cologne/configuration.nix ]; + }; + }; + }; + in + { + inherit (clan.config) nixosConfigurations nixosModules clanInternals; + clan = clan.config; + }; +} +``` + +βœ… Et voilΓ ! Your existing hosts are now part of a clan. + +Existing Nix tooling +should still work as normal. To check that you didn't make any errors, run `nix +flake show` and verify both hosts are still recognized as if nothing had +changed. You should also see the new `clan` output. + +``` +❯ nix flake show +git+file:///my-nixos-config +β”œβ”€β”€β”€clan: unknown +└───nixosConfigurations + β”œβ”€β”€β”€berlin: NixOS configuration + └───cologne: NixOS configuration +``` + +Of course you can also rebuild your configuration using `nixos-rebuild` and +veryify everything still works. + +## 3. Add `clan-cli` to your `devShells` + +At this point Clan is set up, but you can't use the CLI yet. To do so, it is +recommended to expose it via a `devShell` in your flake. It is also possible to +install it any other way you would install a package in Nix, but using a +developtment shell ensures the CLI's version will always be in sync with your +configuration. + +A minimal example is provided below, add it to your flake outputs. + +```nix +devShells."x86_64-linux".default = nixpkgs.legacyPackages."x86_64-linux".mkShell { + packages = [ clan-core.packages."x86_64-linux".clan-cli ]; +} +``` + +To use the CLI, execute `nix develop` in the directory of your flake. The +resulting shell, provides you with the `clan` CLI tool. Since you will be using +it every time you interact with Clan, it is recommended to set up +[direnv](https://direnv.net/). + +Verify everything works as expected by running `clan machines list`. + +``` +❯ nix develop +[user@host:~/my-nixos-config]$ clan machines list +berlin +cologne +``` + +## Specify Targets + +Clan needs to know where it can reach your hosts. For testing purpose set +`clan.core.networking.targetHost` to the machines adress or hostname. + +```nix +# machines/berlin/configuration.nix +{ + clan.core.networking.targetHost = "123.4.56.78"; +} +``` + +See our guide on for properly [configuring machines networking](../networking/networking.md) + +## Next Steps + +You are now fully set up. Use the CLI to manage your hosts or proceed to +configure further services. At this point you should be able to run commands +like `clan machines update berlin` to deploy a host. diff --git a/tested-trappist/src/content/docs/getting-started/create-installer.md b/tested-trappist/src/content/docs/getting-started/create-installer.md new file mode 100644 index 000000000..8d7fe6c48 --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/create-installer.md @@ -0,0 +1,217 @@ +--- +title: USB Installer Image for Physical Machines +--- + +To install Clan on physical machines, you need to use our custom installer image. This is necessary for proper installation and operation. + +:::note[Deploying to a Virtual Machine?] +If you're deploying to a virtual machine (VM), you can skip this section and go directly to the [Deploy Virtual Machine](./hardware-report-virtual.md) step. In this scenario, we automatically use [nixos-anywhere](https://github.com/nix-community/nixos-anywhere) to replace the kernel during runtime. +::: + +:::tip[Why nixos-anywhere Doesn't Work on Physical Hardware?] +nixos-anywhere relies on [kexec](https://wiki.archlinux.org/title/Kexec) to replace the running kernel with our custom one. This method often has compatibility issues with real hardware, especially systems with dedicated graphics cards like laptops and servers, leading to crashes and black screens. +::: + +:::tip[Reasons for a Custom Install Image] +Our custom install images are built to include essential tools like [nixos-facter](https://github.com/nix-community/nixos-facter) and support for [ZFS](https://wiki.archlinux.org/title/ZFS). They're also optimized to run on systems with as little as 1 GB of RAM, ensuring efficient performance even on lower-end hardware. +::: + +## Prerequisites + +- [x] A free USB Drive with at least 1.5GB (All data on it will be lost) +- [x] Linux/NixOS Machine with Internet + +## Identify the USB Flash Drive + +1. Insert your USB flash drive into your computer. + +2. Identify your flash drive with `lsblk`: + + ```shellSession + lsblk + ``` + + ```{.shellSession hl_lines="2" .no-copy} + NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS + sdb 8:0 1 117,2G 0 disk + └─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO + nvme0n1 259:0 0 1,8T 0 disk + β”œβ”€nvme0n1p1 259:1 0 512M 0 part /boot + └─nvme0n1p2 259:2 0 1,8T 0 part + └─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store + ``` + + :::tip + In this case the USB device is `sdb` + ::: + +3. Ensure all partitions on the drive are unmounted. Replace `sdb1` in the command below with your device identifier (like `sdc1`, etc.): + +```shellSession +sudo umount /dev/sdb1 +``` + +## Installer + +=== "**Linux OS**" + **Create a Custom Installer** + + We recommend to build your own installer because of the following reasons: + + - Include your ssh public keys into the image that allows passwordless ssh connection later on. + - Set your preferred language and keymap + + ```bash + clan flash write --flake https://git.clan.lol/clan/clan-core/archive/main.tar.gz \ + --ssh-pubkey $HOME/.ssh/id_ed25519.pub \ + --keymap us \ + --language en_US.UTF-8 \ + --disk main /dev/sd \ + flash-installer + ``` + :::note + Replace `$HOME/.ssh/id_ed25519.pub` with a path to your SSH public key. + Replace `/dev/sd` with the drive path you want to flash + ::: + + :::danger + Specifying the wrong device can lead to unrecoverable data loss. + + The `clan flash` utility will erase the disk. Make sure to specify the correct device + ::: + + - **SSH-Pubkey Option** + + To add an ssh public key into the installer image append the option: + ``` + --ssh-pubkey + ``` + If you do not have an ssh key yet, you can generate one with `ssh-keygen -t ed25519` command. + This ssh key will be installed into the root user. + + - **Connect to the installer** + + On boot, the installer will display on-screen the IP address it received from the network. + If you need to configure Wi-Fi first, refer to the next section. + If Multicast-DNS (Avahi) is enabled on your own machine, you can also access the installer using the `flash-installer.local` address. + + - **List Keymaps** + + You can get a list of all keymaps with the following command: + ``` + clan flash list keymaps + ``` + + - **List Languages** + + You can get a list of all languages with the following command: + ``` + clan flash list languages + ``` + +=== "**Other OS**" + **Download Generic Installer** + + For x86_64: + + ```shellSession + wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-x86_64-linux.iso + ``` + + For generic arm64 / aarch64 (probably does not work on raspberry pi...) + + ```shellSession + wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-aarch64-linux.iso + ``` + + :::note + If you don't have `wget` installed, you can use `curl --progress-bar -OL ` instead. + ::: + + ## Flash the Installer to the USB Drive + + :::danger + Specifying the wrong device can lead to unrecoverable data loss. + + The `dd` utility will erase the disk. Make sure to specify the correct device (`of=...`) + + For example if the USB device is `sdb` use `of=/dev/sdb` (on macOS it will look more like /dev/disk1) + ::: + + On Linux, you can use the `lsblk` utility to identify the correct disko + + ``` + lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT + ``` + + On macos use `diskutil`: + + ``` + diskutil list + ``` + + Use the `dd` utility to write the NixOS installer image to your USB drive. + Replace `/dev/sd` with your external drive from above. + + ```shellSession + sudo dd bs=4M conv=fsync status=progress if=./nixos-installer-x86_64-linux.iso of=/dev/sd + ``` + + - **Connect to the installer + + On boot, the installer will display on-screen the IP address it received from the network. + If you need to configure Wi-Fi first, refer to the next section. + If Multicast-DNS (Avahi) is enabled on your own machine, you can also access the installer using the `nixos-installer.local` address. + +## Boot From USB Stick + +- To use, boot from the Clan USB drive with **secure boot turned off**. For step by step instructions go to [Disabling Secure Boot](../secure-boot.md) + +## (Optional) Connect to Wifi Manually + +If you don't have access via LAN the Installer offers support for connecting via Wifi. + +```shellSession +iwctl +``` + +This will enter `iwd` + +```{.console, .no-copy} +[iwd]# +``` + +Now run the following command to connect to your Wifi: + +```{.shellSession .no-copy} +# Identify your network device. +device list + +# Replace 'wlan0' with your wireless device name +# Find your Wifi SSID. +station wlan0 scan +station wlan0 get-networks + +# Replace your_ssid with the Wifi SSID +# Connect to your network. +station wlan0 connect your_ssid + +# Verify you are connected +station wlan0 show +``` + +If the connection was successful you should see something like this: + +```{.console, .no-copy} +State connected +Connected network FRITZ!Box (Your router device) +IPv4 address 192.168.188.50 (Your new local ip) +``` + +Press ++ctrl+d++ to exit `IWD`. + +:::caution +Press ++ctrl+d++ **again** to update the displayed QR code and connection information. +::: + +You're all set up diff --git a/tested-trappist/src/content/docs/getting-started/flake-check.md b/tested-trappist/src/content/docs/getting-started/flake-check.md new file mode 100644 index 000000000..b4ade4073 --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/flake-check.md @@ -0,0 +1,31 @@ +--- +title: Generate Facts and Vars +--- + +Typically, this step is handled automatically when a machine is deployed. However, to enable the use of `nix flake check` with your configuration, it must be completed manually beforehand. + +Currently, generating all the necessary facts requires two separate commands. This is due to the coexistence of two parallel secret management solutions: +the newer, recommended version (`clan vars`) and the older version (`clan facts`) that we are slowly phasing out. + +To generate both facts and vars, execute the following commands: + +```sh +clan facts generate && clan vars generate +``` + + +### Check Configuration + +Validate your configuration by running: + +```bash +nix flake check +``` + +This command helps ensure that your system configuration is correct and free from errors. + +:::tip + +You can integrate this step into your [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) workflow to ensure that only valid Nix configurations are merged into your codebase. +::: + diff --git a/tested-trappist/src/content/docs/getting-started/hardware-report-physical.md b/tested-trappist/src/content/docs/getting-started/hardware-report-physical.md new file mode 100644 index 000000000..f101af382 --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/hardware-report-physical.md @@ -0,0 +1,120 @@ +--- +title: Installing a Physical Machine +next: { link: "/getting-started/choose-disk", label: Configure Disk } +--- + +Now that you have created a machine, added some services, and set up secrets, this guide will walk you through how to deploy it. + + +### Prerequisites +- [x] RAM > 2GB +- [x] **Two Computers**: You need one computer that you're getting ready (we'll call this the Target Computer) and another one to set it up from (we'll call this the Setup Computer). Make sure both can talk to each other over the network using SSH. +- [x] **Machine configuration**: See our basic [adding and configuring machine guide](./add-machines.md) +- [x] **Initialized secrets**: See [secrets](../secrets.md) for how to initialize your secrets. +- [x] **USB Flash Drive**: See [Clan Installer](./create-installer.md) + + +### Image Installer +This method makes use of the [image installers](./create-installer.md). + +The installer will randomly generate a password and local addresses on boot, then run a SSH server with these preconfigured. +The installer shows its deployment relevant information in two formats, a text form, as well as a QR code. + + +This is an example of the booted installer. + +```{ .bash .annotate .no-copy .nohighlight} +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ”‚ # This is the QR Code (1) β”‚ +β”‚ β”‚β–ˆβ–ˆ β–„β–„β–„β–„β–„ β–ˆβ–€β–„β–ˆβ–€β–ˆβ–€β–„β–ˆ β–„β–„β–„β–„β–„ β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆ β–ˆ β–ˆ β–ˆβ–€β–„β–„β–„β–ˆ β–€β–ˆ β–ˆ β–ˆ β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆ β–ˆβ–„β–„β–„β–ˆ β–ˆβ–€β–„ β–€β–„β–„β–„β–ˆ β–ˆβ–„β–„β–„β–ˆ β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆβ–„β–„β–„β–„β–„β–„β–„β–ˆβ–„β–€ β–€β–„β–€β–„β–ˆβ–„β–„β–„β–„β–„β–„β–„β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆβ–ˆβ–€β–€β–€ β–ˆβ–„β–„β–ˆ β–€β–„ β–„β–€β–„β–ˆ β–ˆβ–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆβ–„β–ˆβ–ˆβ–„β–„β–ˆβ–„β–„β–€β–€β–ˆβ–ˆβ–„β–€ β–„β–„β–„ β–„β–€β–ˆβ–€β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆ β–„β–„β–„β–„β–„ β–ˆβ–„β–„β–„β–„ β–ˆ β–ˆβ–„β–ˆ β–ˆβ–€ β–ˆβ–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆ β–ˆ β–ˆ β–ˆ β–ˆ β–ˆ β–„β–„β–„ β–„β–€β–€ β–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆ β–ˆβ–„β–„β–„β–ˆ β–ˆ β–„ β–„ β–„ β–€β–ˆ β–„β–ˆβ–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆβ–„β–„β–„β–„β–„β–„β–„β–ˆβ–„β–„β–„β–„β–„β–„β–ˆβ–„β–„β–„β–„β–„β–ˆβ–„β–ˆβ–ˆβ–ˆβ”‚ β”‚ +β”‚ β”‚β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚Root password: cheesy-capital-unwell # password (2) β”‚ β”‚ +β”‚ β”‚Local network addresses: β”‚ β”‚ +β”‚ β”‚enp1s0 UP 192.168.178.169/24 metric 1024 fe80::21e:6ff:fe45:3c92/64 β”‚ β”‚ +β”‚ β”‚enp2s0 DOWN β”‚ β”‚ +β”‚ β”‚wlan0 DOWN # connect to wlan (3) β”‚ β”‚ +β”‚ β”‚Onion address: 6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion β”‚ β”‚ +β”‚ β”‚Multicast DNS: nixos-installer.local β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ Press 'Ctrl-C' for console access β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +1. This is not an actual QR code, because it is displayed rather poorly on text sites. + This would be the actual content of this specific QR code prettified: + ```json + { + "pass": "cheesy-capital-unwell", + "tor": "6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion", + "addrs": [ + "2001:9e8:347:ca00:21e:6ff:fe45:3c92" + ] + } + ``` + + To generate the actual QR code, that would be displayed use: + ```shellSession + echo '{"pass":"cheesy-capital-unwell","tor":"6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion","addrs":["2001:9e8:347:ca00:21e:6ff:fe45:3c92"]}' | nix run nixpkgs#qrencode -- -s 2 -m 2 -t utf8 + ``` +2. The root password for the installer medium. + This password is autogenerated and meant to be easily typeable. +3. See how to connect the installer medium to wlan [here](./create-installer.md). + +:::tip +For easy sharing of deployment information via QR code, we highly recommend using [KDE Connect](https://apps.kde.org/de/kdeconnect/). +::: + +There are two ways to deploy your machine: + +### Generating a Hardware Report + +The following command will generate a hardware report with [nixos-facter](https://github.com/nix-community/nixos-facter) and writes it back into your machine folder. The `--phases kexec` flag makes sure we are not yet formatting anything, instead if the target system is not a NixOS machine it will use [kexec](https://wiki.archlinux.org/title/Kexec) to switch to a NixOS kernel. + +=== "Password" + **Password** + + ```terminal + clan machines install [MACHINE] \ + --update-hardware-config nixos-facter \ + --phases kexec \ + --target-host root@192.168.178.169 + ``` + +=== "QR Code" + **QR Code** + + **Using a JSON String or File Path**: + + Copy the JSON string contained in the QR Code and provide its path or paste it directly: + ```terminal + clan machines install [MACHINE] --json [JSON] \ + --update-hardware-config nixos-facter \ + --phases kexec + ``` + + **Using an Image Containing the QR Code**: + + Provide the path to an image file containing the QR code displayed by the installer: + ```terminal + clan machines install [MACHINE] --png [PATH] \ + --update-hardware-config nixos-facter \ + --phases kexec + ``` + + +If you are using our template `[MACHINE]` would be `jon` + +[Next Step (Choose Disk Format)](./choose-disk.md){ .md-button .md-button--primary } \ No newline at end of file diff --git a/tested-trappist/src/content/docs/getting-started/hardware-report-virtual.md b/tested-trappist/src/content/docs/getting-started/hardware-report-virtual.md new file mode 100644 index 000000000..0e6dd25de --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/hardware-report-virtual.md @@ -0,0 +1,36 @@ +--- +title: Generate a VM Hardware Report +--- + +Now that you have created a machine, added some services, and set up secrets, this guide will walk you through how to deploy it. + + +## Prerequisites +- [x] RAM > 2GB +- [x] **Two Computers**: You need one computer that you're getting ready (we'll call this the Target Computer) and another one to set it up from (we'll call this the Setup Computer). Make sure both can talk to each other over the network using SSH. +- [x] **Machine configuration**: See our basic [adding and configuring machine guide](./add-machines.md) + + +Clan supports any cloud machine if it is reachable via SSH and supports `kexec`. + + +:::tip +NixOS can cause strange issues when booting in certain cloud environments. + +If on Linode: Make sure that the system uses "Direct Disk boot kernel" (found in the configuration panel) +::: + + +The following command will generate a hardware report with [nixos-facter](https://github.com/nix-community/nixos-facter) and writes it back into your machine folder. The `--phases kexec` flag makes sure we are not yet formatting anything, instead if the target system is not a NixOS machine it will use [kexec](https://wiki.archlinux.org/title/Kexec) to switch to a NixOS kernel. + + +```terminal +clan machines install [MACHINE] \ + --update-hardware-config nixos-facter \ + --phases kexec \ + --target-host myuser@ +``` + +:::caution +After running the above command, be aware that the SSH login user changes from `myuser` to `root`. For subsequent SSH connections to the target machine, use `root` as the login user. This change occurs because the system switches to the NixOS kernel using `kexec`. +::: diff --git a/tested-trappist/src/content/docs/getting-started/update.md b/tested-trappist/src/content/docs/getting-started/update.md new file mode 100644 index 000000000..e983ba87f --- /dev/null +++ b/tested-trappist/src/content/docs/getting-started/update.md @@ -0,0 +1,133 @@ +--- +title: Update Machines +--- + +The Clan command line interface enables you to update machines remotely over SSH. +In this guide we will teach you how to set a `targetHost` in Nix, +and how to define a remote builder for your machine closures. + + +## Setting `targetHost` + +Set the machine’s `targetHost` to the reachable IP address of the new machine. +This eliminates the need to specify `--target-host` in CLI commands. + +```{.nix title="clan.nix" hl_lines="9"} +{ +# Ensure this is unique among all clans you want to use. +meta.name = "my-clan"; + +inventory.machines = { + # Define machines here. + # The machine name will be used as the hostname. + jon = { + deploy.targetHost = "root@192.168.192.4"; # (1) + }; +}; +# [...] +} +``` + +The use of `root@` in the target address implies SSH access as the `root` user. +Ensure that the root login is secured and only used when necessary. + +## Multiple Target Hosts + +You can now experiment with a new interface that allows you to define multiple `targetHost` addresses for different VPNs. Learn more and try it out in our [networking guide](../networking/networking.md). + +## Updating Machine Configurations + +Execute the following command to update the specified machine: + +```bash +clan machines update jon +``` + +All machines can be updated simultaneously by omitting the machine name: + +```bash +clan machines update +``` + +--- + +## Advanced Usage + +The following options are only needed for special cases, such as limited resources, mixed environments, or private flakes. + +### Setting `buildHost` + +If the machine does not have enough resources to run the NixOS **evaluation** or **build** itself, +it is also possible to specify a `buildHost` instead. +During an update, clan will ssh into the `buildHost` and run `nixos-rebuild` from there. + +:::note +The `buildHost` option should be set directly within your machine’s Nix configuration, **not** under `inventory.machines`. +::: + + +```{.nix hl_lines="5" .no-copy} +clan { + # ... + machines = { + "jon" = { + clan.core.networking.buildHost = "root@"; + }; + }; +}; +``` + +### Overriding configuration with CLI flags + +`buildHost` / `targetHost`, and other network settings can be temporarily overridden for a single command: + +For the full list of flags refer to the [Clan CLI](../../reference/cli/index.md) + +```bash +# Build on a remote host +clan machines update jon --build-host root@192.168.1.10 + +# Build locally (useful for testing or when the target has limited resources) +clan machines update jon --build-host local +``` + +:::note +Make sure the CPU architecture of the `buildHost` matches that of the `targetHost` + +For example, if deploying to a macOS machine with an ARM64-Darwin architecture, you need a second macOS machine with the same architecture to build it. +::: + + +### Excluding a machine from `clan machine update` + +To exclude machines from being updated when running `clan machines update` without any machines specified, +one can set the `clan.deployment.requireExplicitUpdate` option to true: + +```{.nix hl_lines="5" .no-copy} +clan { + # ... + machines = { + "jon" = { + clan.deployment.requireExplicitUpdate = true; + }; + }; +}; +``` + +This is useful for machines that are not always online or are not part of the regular update cycle. + +### Uploading Flake Inputs + +When updating remote machines, flake inputs are usually fetched by the build host. +However, if flake inputs require authentication (e.g., private repositories), + +Use the `--upload-inputs` flag to upload all inputs from your local machine: + +```bash +clan machines update jon --upload-inputs +``` + +This is particularly useful when: +- The flake references private Git repositories +- Authentication credentials are only available on local machine +- The build host doesn't have access to certain network resources diff --git a/tested-trappist/src/content/docs/guides/vars/age-plugins.md b/tested-trappist/src/content/docs/guides/vars/age-plugins.md new file mode 100644 index 000000000..d7177ba87 --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/age-plugins.md @@ -0,0 +1,89 @@ +--- +title: Using Age Plugins with Clan Vars +sidebar: + order: 99 +--- + +This guide explains how to set up YubiKey and other plugins for `clan vars` secrets. + +By default the `clan vars` subcommand uses the `age` encryption tool, which supports various plugins. + +--- + +## Supported Age Plugins + +Below is a [list of popular `age` plugins](https://github.com/FiloSottile/awesome-age?tab=readme-ov-file#plugins) you can use with Clan. (Last updated: **September 12, 2025**) + +- ⭐️ [**age-plugin-yubikey**](https://github.com/str4d/age-plugin-yubikey): YubiKey (and other PIV tokens) plugin. +- [**age-plugin-se**](https://github.com/remko/age-plugin-se): Apple Secure Enclave plugin. +- πŸ§ͺ [**age-plugin-tpm**](https://github.com/Foxboron/age-plugin-tpm): TPM 2.0 plugin. +- πŸ§ͺ [**age-plugin-tkey**](https://github.com/quite/age-plugin-tkey): Tillitis TKey plugin. + [**age-plugin-trezor**](https://github.com/romanz/trezor-agent/blob/master/doc/README-age.md): Hardware wallet plugin (TREZOR, Ledger, etc.). +- πŸ§ͺ [**age-plugin-sntrup761x25519**](https://github.com/keisentraut/age-plugin-sntrup761x25519): Post-quantum hybrid plugin (NTRU Prime + X25519). +- πŸ§ͺ [**age-plugin-fido**](https://github.com/riastradh/age-plugin-fido): Prototype symmetric encryption plugin for FIDO2 keys. +- πŸ§ͺ [**age-plugin-fido2-hmac**](https://github.com/olastor/age-plugin-fido2-hmac): FIDO2 plugin with PIN support. +- πŸ§ͺ [**age-plugin-sss**](https://github.com/olastor/age-plugin-sss): Shamir's Secret Sharing (SSS) plugin. +- πŸ§ͺ [**age-plugin-amnesia**](https://github.com/cedws/amnesia/blob/master/README.md#age-plugin-experimental): Adds Q&A-based identity wrapping. + +> **Note:** Plugins marked with πŸ§ͺ are experimental. Plugins marked with ⭐️ are official. + +--- + +## Using Plugin-Generated Keys + +If you want to use `fido2 tokens` to encrypt your secret instead of the normal age secret key then you need to prefix your age secret key with the corresponding plugin name. In our case we want to use the `age-plugin-fido2-hmac` plugin so we replace `AGE-SECRET-KEY` with `AGE-PLUGIN-FIDO2-HMAC`. + +:::tip + - On Linux the age secret key is located at `~/.config/sops/age/keys.txt` + - On macOS it is located at `/Users/admin/Library/Application Support/sops/age/keys.txt` + +**Before**: + ```hl_lines="2" + # public key: age1zdy49ek6z60q9r34vf5mmzkx6u43pr9haqdh5lqdg7fh5tpwlfwqea356l + AGE-SECRET-KEY-1QQPQZRFR7ZZ2WCV... + ``` + + **After**: +```hl_lines="2" +# public key: age1zdy49ek6z60q9r34vf5mmzkx6u43pr9haqdh5lqdg7fh5tpwlfwqea356l +AGE-PLUGIN-FIDO2-HMAC-1QQPQZRFR7ZZ2WCV... +``` + + + +## Configuring Plugins in `flake.nix` + +To use `age` plugins with Clan, you need to configure them in your `flake.nix` file. Here’s an example: + +```nix title="flake.nix" +{ + inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; + inputs.nixpkgs.follows = "clan-core/nixpkgs"; + + outputs = { self, clan-core, ... }: + let + # Define Clan configuration + clan = clan-core.lib.clan { + inherit self; + + meta.name = "myclan"; + + # Add YubiKey and FIDO2 HMAC plugins + # Note: Plugins must be available in nixpkgs. + secrets.age.plugins = [ + "age-plugin-yubikey" + "age-plugin-fido2-hmac" + ]; + + machines = { + # Machine configurations (elided for brevity) + }; + }; + in + { + inherit (clan) nixosConfigurations nixosModules clanInternals; + + # Additional configurations (elided for brevity) + }; +} +``` diff --git a/tested-trappist/src/content/docs/guides/vars/vars-advanced-examples.md b/tested-trappist/src/content/docs/guides/vars/vars-advanced-examples.md new file mode 100644 index 000000000..7de548f3a --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/vars-advanced-examples.md @@ -0,0 +1,292 @@ +--- +title: Advanced Vars Examples +--- + +This guide demonstrates complex, real-world patterns for the vars system. + + +## Certificate Authority with Intermediate Certificates + +This example shows how to create a complete certificate authority with root and intermediate certificates using dependencies. + +```nix +{ + # Generate root CA (not deployed to machines) + clan.core.vars.generators.root-ca = { + files."ca.key" = { + secret = true; + deploy = false; # Keep root key offline + }; + files."ca.crt".secret = false; + runtimeInputs = [ pkgs.step-cli ]; + script = '' + step certificate create "My Root CA" \ + $out/ca.crt $out/ca.key \ + --profile root-ca \ + --no-password \ + --not-after 87600h + ''; + }; + + # Generate intermediate key + clan.core.vars.generators.intermediate-key = { + files."intermediate.key" = { + secret = true; + deploy = true; + }; + runtimeInputs = [ pkgs.step-cli ]; + script = '' + step crypto keypair \ + $out/intermediate.pub \ + $out/intermediate.key \ + --no-password + ''; + }; + + # Generate intermediate certificate signed by root + clan.core.vars.generators.intermediate-cert = { + files."intermediate.crt".secret = false; + dependencies = [ + "root-ca" + "intermediate-key" + ]; + runtimeInputs = [ pkgs.step-cli ]; + script = '' + step certificate create "My Intermediate CA" \ + $out/intermediate.crt \ + $in/intermediate-key/intermediate.key \ + --ca $in/root-ca/ca.crt \ + --ca-key $in/root-ca/ca.key \ + --profile intermediate-ca \ + --not-after 8760h \ + --no-password + ''; + }; + + # Use the certificates in services + services.nginx.virtualHosts."example.com" = { + sslCertificate = config.clan.core.vars.generators.intermediate-cert.files."intermediate.crt".value; + sslCertificateKey = config.clan.core.vars.generators.intermediate-key.files."intermediate.key".path; + }; +} +``` + +## Multi-Service Secret Sharing + +Generate secrets that multiple services can use: + +```nix +{ + # Generate database credentials + clan.core.vars.generators.database = { + share = true; # Share across machines + files."password" = { }; + files."connection-string" = { }; + prompts.dbname = { + description = "Database name"; + type = "line"; + }; + script = '' + # Generate password + tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32 > $out/password + + # Create connection string + echo "postgresql://app:$(cat $out/password)@localhost/$prompts/dbname" \ + > $out/connection-string + ''; + }; + + # PostgreSQL uses the password + services.postgresql = { + enable = true; + initialScript = pkgs.writeText "init.sql" '' + CREATE USER app WITH PASSWORD '${ + builtins.readFile config.clan.core.vars.generators.database.files."password".path + }'; + ''; + }; + + # Application uses the connection string + systemd.services.myapp = { + serviceConfig.EnvironmentFile = + config.clan.core.vars.generators.database.files."connection-string".path; + }; +} +``` + +## SSH Host Keys with Certificates + +Generate SSH host keys and sign them with a CA: + +```nix +{ + # SSH Certificate Authority (shared) + clan.core.vars.generators.ssh-ca = { + share = true; + files."ca" = { secret = true; deploy = false; }; + files."ca.pub" = { secret = false; }; + runtimeInputs = [ pkgs.openssh ]; + script = '' + ssh-keygen -t ed25519 -N "" -f $out/ca + mv $out/ca.pub $out/ca.pub + ''; + }; + + # Host-specific SSH keys + clan.core.vars.generators.ssh-host = { + files."ssh_host_ed25519_key" = { + secret = true; + owner = "root"; + group = "root"; + mode = "0600"; + }; + files."ssh_host_ed25519_key.pub" = { secret = false; }; + files."ssh_host_ed25519_key-cert.pub" = { secret = false; }; + dependencies = [ "ssh-ca" ]; + runtimeInputs = [ pkgs.openssh ]; + script = '' + # Generate host key + ssh-keygen -t ed25519 -N "" -f $out/ssh_host_ed25519_key + + # Sign with CA + ssh-keygen -s $in/ssh-ca/ca \ + -I "host:${config.networking.hostName}" \ + -h \ + -V -5m:+365d \ + $out/ssh_host_ed25519_key.pub + ''; + }; + + # Configure SSH to use the generated keys + services.openssh = { + hostKeys = [{ + path = config.clan.core.vars.generators.ssh-host.files."ssh_host_ed25519_key".path; + type = "ed25519"; + }]; + }; +} +``` + +## WireGuard Mesh Network + +Create a WireGuard configuration with pre-shared keys: + +```nix +{ + # Generate WireGuard keys for this host + clan.core.vars.generators.wireguard = { + files."privatekey" = { + secret = true; + owner = "systemd-network"; + mode = "0400"; + }; + files."publickey" = { secret = false; }; + files."preshared" = { secret = true; }; + runtimeInputs = [ pkgs.wireguard-tools ]; + script = '' + # Generate key pair + wg genkey > $out/privatekey + wg pubkey < $out/privatekey > $out/publickey + + # Generate pre-shared key + wg genpsk > $out/preshared + ''; + }; + + # Configure WireGuard + networking.wireguard.interfaces.wg0 = { + privateKeyFile = config.clan.core.vars.generators.wireguard.files."privatekey".path; + + peers = [{ + publicKey = "peer-public-key-here"; + presharedKeyFile = config.clan.core.vars.generators.wireguard.files."preshared".path; + allowedIPs = [ "10.0.0.2/32" ]; + }]; + }; +} +``` + +## Conditional Generation Based on Machine Role + +Generate different secrets based on machine configuration: + +```nix +{ + clan.core.vars.generators = lib.mkMerge [ + # All machines get basic auth + { + basic-auth = { + files."htpasswd" = { }; + prompts.username = { + description = "Username for basic auth"; + type = "line"; + }; + prompts.password = { + description = "Password for basic auth"; + type = "hidden"; + }; + runtimeInputs = [ pkgs.apacheHttpd ]; + script = '' + htpasswd -nbB "$prompts/username" "$prompts/password" > $out/htpasswd + ''; + }; + } + + # Only servers get API tokens + (lib.mkIf config.services.myapi.enable { + api-tokens = { + files."admin-token" = { }; + files."readonly-token" = { }; + runtimeInputs = [ pkgs.openssl ]; + script = '' + openssl rand -hex 32 > $out/admin-token + openssl rand -hex 16 > $out/readonly-token + ''; + }; + }) + ]; +} +``` + +## Backup Encryption Keys + +Generate and manage backup encryption keys: + +```nix +{ + clan.core.vars.generators.backup = { + share = true; # Same key for all backup sources + files."encryption.key" = { + secret = true; + deploy = true; + }; + files."encryption.pub" = { secret = false; }; + runtimeInputs = [ pkgs.age ]; + script = '' + # Generate age key pair + age-keygen -o $out/encryption.key 2>/dev/null + + # Extract public key + grep "public key:" $out/encryption.key | cut -d: -f2 | tr -d ' ' \ + > $out/encryption.pub + ''; + }; + + # Use in backup service + services.borgbackup.jobs.system = { + encryption = { + mode = "repokey-blake2"; + passCommand = "cat ${config.clan.core.vars.generators.backup.files."encryption.key".path}"; + }; + }; +} +``` + +## Tips and Best Practices + +1. **Use dependencies** to build complex multi-stage generations +2. **Share generators** when the same secret is needed across machines +3. **Set appropriate permissions** for service-specific secrets +4. **Use prompts** for user-specific values that shouldn't be generated +5. **Combine secret and non-secret files** in the same generator when they're related +6. **Use conditional generation** with `lib.mkIf` for role-specific secrets \ No newline at end of file diff --git a/tested-trappist/src/content/docs/guides/vars/vars-backend.md b/tested-trappist/src/content/docs/guides/vars/vars-backend.md new file mode 100644 index 000000000..351bc5008 --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/vars-backend.md @@ -0,0 +1,142 @@ +--- +title: Diving deeper +--- + +The `clan vars` subcommand is a powerful tool for managing machine-specific variables in a declarative and reproducible way. This guide will walk you through its usage, from setting up a generator to sharing and updating variables across machines. + +For a detailed API reference, see the [vars module documentation](../../reference/clan.core/vars.md). + +In this guide, you will learn how to: + +1. Declare a `generator` in the machine's NixOS configuration. +2. Inspect the status of variables using the Clan CLI. +3. Generate variables interactively. +4. Observe the changes made to your repository. +5. Update the machine configuration. +6. Share the root password between multiple machines. +7. Change the root password when needed. + +By the end of this guide, you will have a clear understanding of how to use `clan vars` to manage sensitive data, such as passwords, in a secure and efficient manner. + + +## Declare the generator + +In this example, a `vars` `generator` is used to: + +- prompt the user for the password +- run the required `mkpasswd` command to generate the hash +- store the hash in a file +- expose the file path to the nixos configuration + +Create a new nix file `root-password.nix` with the following content and import it into your `configuration.nix` +```nix +{config, pkgs, ...}: { + + clan.core.vars.generators.root-password = { + # prompt the user for a password + # (`password-input` being an arbitrary name) + prompts.password-input.description = "the root user's password"; + prompts.password-input.type = "hidden"; + # don't store the prompted password itself + prompts.password-input.persist = false; + # define an output file for storing the hash + files.password-hash.secret = false; + # define the logic for generating the hash + script = '' + cat $prompts/password-input | mkpasswd -m sha-512 > $out/password-hash + ''; + # the tools required by the script + runtimeInputs = [ pkgs.mkpasswd ]; + }; + + # ensure users are immutable (otherwise the following config might be ignored) + users.mutableUsers = false; + # set the root password to the file containing the hash + users.users.root.hashedPasswordFile = + # clan will make sure, this path exists + config.clan.core.vars.generators.root-password.files.password-hash.path; +} +``` + +## Inspect the status + +Executing `clan vars list`, you should see the following: +```shellSession +$ clan vars list my_machine +root-password/password-hash: +``` + +...indicating that the value `password-hash` for the generator `root-password` is not set yet. + +## Generate the values + +This step is not strictly necessary, as deploying the machine via `clan machines update` would trigger the generator as well. + +To run the generator, execute `clan vars generate` for your machine +```shellSession +$ clan vars generate my_machine +Enter the value for root-password/password-input (hidden): +``` + +After entering the value, the updated status is reported: +```shellSession +Updated var root-password/password-hash + old: + new: $6$RMats/YMeypFtcYX$DUi... +``` + +## Observe the changes + +With the last step, a new file was created in your repository: +`vars/per-machine/my-machine/root-password/password-hash/value` + +If the repository is a git repository, a commit was created automatically: +```shellSession +$ git log -n1 +commit ... (HEAD -> master) +Author: ... +Date: ... + + Update vars via generator root-password for machine grmpf-nix +``` + +## Update the machine + +```shell +clan machines update my_machine +``` + +## Share root password between machines + +If we just imported the `root-password.nix` from above into more machines, clan would ask for a new password for each additional machine. + +If the root password instead should only be entered once and shared across all machines, the generator defined above needs to be declared as `shared`, by adding `share = true` to it: +```nix +{config, pkgs, ...}: { + clan.core.vars.generators.root-password = { + share = true; + # ... + } +} +``` + +Importing that shared generator into each machine, will ensure that the password is only asked once the first machine gets updated and then re-used for all subsequent machines. + +## Change the root password + +Changing the password can be done via this command. +Replace `my-machine` with your machine. +If the password is shared, just pick any machine that has the generator declared. + +```shellSession +$ clan vars generate my-machine --generator root-password --regenerate +... +Enter the value for root-password/password-input (hidden): +Input received. Processing... +... +Updated var root-password/password-hash + old: $6$tb27m6EOdff.X9TM$19N... + + new: $6$OyoQtDVzeemgh8EQ$zRK... +``` + diff --git a/tested-trappist/src/content/docs/guides/vars/vars-concepts.md b/tested-trappist/src/content/docs/guides/vars/vars-concepts.md new file mode 100644 index 000000000..97c93a77c --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/vars-concepts.md @@ -0,0 +1,125 @@ +--- +title: Understanding Clan Vars +--- + +This guide explains the architecture and design principles behind the vars system. + +## Architecture Overview + +The vars system provides a declarative, reproducible way to manage generated files (especially secrets) in NixOS configurations. + +## Data Flow + +```mermaid +graph LR + A[Generator Script] --> B[Output Files] + C[User Prompts] --> A + D[Dependencies] --> A + B --> E[Secret Storage
sops/password-store] + B --> F[Nix Store
public files] + E --> G[Machine Deployment] + F --> G +``` + +## Key Design Principles + +### 1. Declarative Generation + +Unlike imperative secret management, vars are declared in your NixOS configuration and generated deterministically. This ensures reproducibility across deployments. + +### 2. Separation of Concerns + +- **Generation logic**: Defined in generator scripts +- **Storage**: Handled by pluggable backends (sops, password-store, etc.) +- **Deployment**: Managed by NixOS activation scripts +- **Access control**: Enforced through file permissions and ownership + +### 3. Composability Through Dependencies + +Generators can depend on outputs from other generators, enabling complex workflows: + +```nix +# Dependencies create a directed acyclic graph (DAG) +A β†’ B β†’ C + ↓ + D +``` + +This allows building sophisticated systems like certificate authorities where intermediate certificates depend on root certificates. + +### 4. Type Safety + +The vars system distinguishes between: +- **Secret files**: Only accessible via `.path`, deployed to `/run/secrets/` +- **Public files**: Accessible via `.value`, stored in nix store + +This prevents accidental exposure of secrets in the nix store. + +## Storage Backend Architecture + +The vars system uses pluggable storage backends: + +- **sops** (default): Integrates with clan's existing sops encryption +- **password-store**: For users already using pass + +Each backend handles encryption/decryption transparently, allowing the same generator definitions to work across different security models. + +## Timing and Lifecycle + +### Generation Phases + +1. **Pre-deployment**: `clan vars generate` creates vars before deployment +2. **During deployment**: Missing vars are generated automatically +3. **Regeneration**: Explicit regeneration with `--regenerate` flag + +### The `neededFor` Option + +Control when vars are available during system activation: + +```nix +files."early-secret" = { + secret = true; + neededFor = [ "users" "groups" ]; # Available early in activation +}; +``` + +## Advanced Patterns + +### Multi-Machine Coordination + +The `share` option enables cross-machine secret sharing: + +```mermaid +graph LR + A[Shared Generator] --> B[Machine 1] + A --> C[Machine 2] + A --> D[Machine 3] +``` + +This is useful for: +- Shared certificate authorities +- Mesh VPN pre-shared keys +- Cluster join tokens + +### Generator Composition + +Complex systems can be built by composing simple generators: + +``` +root-ca β†’ intermediate-ca β†’ service-cert + ↓ + ocsp-responder +``` + +Each generator focuses on one task, making the system modular and testable. + +## Key Advantages + +Compared to manual secret management, vars provides: + +- **Declarative configuration**: Define once, generate consistently +- **Dependency management**: Build complex systems with generator dependencies +- **Type safety**: Separate handling of secret and public files +- **User prompts**: Gather input when needed +- **Easy regeneration**: Update secrets with a single command + diff --git a/tested-trappist/src/content/docs/guides/vars/vars-overview.md b/tested-trappist/src/content/docs/guides/vars/vars-overview.md new file mode 100644 index 000000000..8b1207e60 --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/vars-overview.md @@ -0,0 +1,147 @@ +--- +title: Introduction to Vars +--- + +The vars system is clan's declarative solution for managing generated files, secrets, and dynamic configuration in your NixOS deployments. It eliminates the manual steps of generating credentials, certificates, and other dynamic values by automating these processes within your infrastructure-as-code workflow. + +## What Problems Does Vars Solve? + +### Before Vars: Manual Secret Management + +Traditional NixOS deployments require manual steps for secrets and generated files: + +```bash +# Generate password hash manually +mkpasswd -m sha-512 > /tmp/root-password-hash +# Copy hash into configuration +users.users.root.hashedPasswordFile = "/tmp/root-password-hash"; +``` + +This approach has several problems: + +- **Not reproducible**: Manual steps vary between team members + +- **Hard to maintain**: Updating secrets requires remembering manual commands + +- **Deployment friction**: Secrets must be managed outside of your configuration + +- **Team collaboration issues**: Sharing credentials securely is complex + +### After Vars: Declarative Generation + +With vars, the same process becomes declarative and automated: + +```nix +clan.core.vars.generators.root-password = { + prompts.password.description = "Root password"; + prompts.password.type = "hidden"; + files.hash.secret = false; + script = "mkpasswd -m sha-512 < $prompts/password > $out/hash"; + runtimeInputs = [ pkgs.mkpasswd ]; +}; + +users.users.root.hashedPasswordFile = + config.clan.core.vars.generators.root-password.files.hash.path; +``` + +## Core Benefits + +- **πŸ”„ Reproducible**: Same inputs always produce the same outputs +- **πŸ“ Declarative**: Defined alongside your NixOS configuration +- **πŸ” Secure**: Automatic secret storage and encrypted deployment +- **πŸ‘₯ Collaborative**: Built-in sharing for team environments +- **πŸš€ Automated**: No manual intervention required for deployments +- **πŸ”— Integrated**: Works seamlessly with clan's deployment workflow + +## How It Works + +```mermaid +graph TB + A[Generator Declaration] --> B[clan vars generate] + B --> C{Prompts User} + C --> D[Execute Script] + D --> E[Output Files] + E --> F{Secret?} + F -->|Yes| G[Encrypted Storage] + F -->|No| H[Git Repository] + G --> I[Deploy to Machine] + H --> I + I --> J[Available in NixOS] +``` + +1. **Declare generators** in your NixOS configuration +2. **Generate values** using `clan vars generate` (or automatically during deployment) +3. **Store securely** in encrypted backends or version control +4. **Deploy seamlessly** to your machines where they're accessible as file paths + +## Common Use Cases + +| Use Case | What Gets Generated | Benefits | +|----------|-------------------|----------| +| **User passwords** | Password hashes | No plaintext in config | +| **SSH keys** | Host/user keypairs | Automated key rotation | +| **TLS certificates** | Certificates + private keys | Automated PKI | +| **Database credentials** | Passwords + connection strings | Secure service communication | +| **API tokens** | Random tokens | Service authentication | +| **Configuration files** | Complex configs with secrets | Dynamic config generation | + +## Architecture Overview + +The vars system has three main components: + +### 1. **Generators** +Define how to create files from inputs: + +- **Prompts**: Values requested from users + +- **Scripts**: Generation logic + +- **Dependencies**: Other generators this depends on + +- **Outputs**: Files that get created + +### 2. **Storage Backends** +Handle secret storage and deployment: + +- **sops**: Encrypted files in git (recommended) + +- **password-store**: GPG/age-based secret storage + +## Quick Start Example + +Here's a complete example showing password generation and usage: + +```nix +# generator.nix +{ config, pkgs, ... }: { + clan.core.vars.generators.user-password = { + prompts.password = { + description = "User password"; + type = "hidden"; + }; + files.hash = { secret = false; }; + script = '' + mkpasswd -m sha-512 < $prompts/password > $out/hash + ''; + runtimeInputs = [ pkgs.mkpasswd ]; + }; + + users.users.myuser = { + hashedPasswordFile = + config.clan.core.vars.generators.user-password.files.hash.path; + }; +} +``` + +```bash +# Generate the password +clan vars generate my-machine + +# Deploy to machine +clan machines update my-machine +``` + +## Migration from Facts + +If you're currently using the legacy facts system, see our [Migration Guide](../migrations/migration-facts-vars.md) for step-by-step instructions on upgrading to vars. + diff --git a/tested-trappist/src/content/docs/guides/vars/vars-troubleshooting.md b/tested-trappist/src/content/docs/guides/vars/vars-troubleshooting.md new file mode 100644 index 000000000..ce2f1be2e --- /dev/null +++ b/tested-trappist/src/content/docs/guides/vars/vars-troubleshooting.md @@ -0,0 +1,274 @@ +--- +title: Troubleshooting Vars +--- + +Quick reference for diagnosing and fixing vars issues. + +## Common Issues + +### Generator Script Fails + +**Symptom**: Error during `clan vars generate` or deployment + +**Possible causes and solutions**: + +1. **Missing runtime inputs** + ```nix + # Wrong - missing required tool + runtimeInputs = [ ]; + script = '' + openssl rand -hex 32 > $out/secret # openssl not found! + ''; + + # Correct + runtimeInputs = [ pkgs.openssl ]; + ``` + +2. **Wrong output path** + ```nix + # Wrong - must use $out + script = '' + echo "secret" > ./myfile + ''; + + # Correct + script = '' + echo "secret" > $out/myfile + ''; + ``` + +3. **Missing declared files** + ```nix + files."config" = { }; + files."key" = { }; + script = '' + # Wrong - only generates one file + echo "data" > $out/config + ''; + + # Correct - must generate all declared files + script = '' + echo "data" > $out/config + echo "key" > $out/key + ''; + ``` + +### Cannot Access Generated Files + +**Symptom**: "attribute 'value' missing" or file not found + +**Solutions**: + +1. **Secret files don't have `.value`** + ```nix + # Wrong - secret files can't use .value + files."secret" = { secret = true; }; + # ... + environment.etc."app.conf".text = + config.clan.core.vars.generators.app.files."secret".value; + + # Correct - use .path for secrets + environment.etc."app.conf".source = + config.clan.core.vars.generators.app.files."secret".path; + ``` + +2. **Public files should use `.value`** + ```nix + # Better for non-secrets + files."cert.pem" = { secret = false; }; + # ... + sslCertificate = + config.clan.core.vars.generators.ca.files."cert.pem".value; + ``` + +### Dependencies Not Available + +**Symptom**: "No such file or directory" when accessing `$in/...` + +**Solution**: Declare dependencies correctly +```nix +clan.core.vars.generators.child = { + # Wrong - missing dependency + script = '' + cat $in/parent/file > $out/newfile + ''; + + # Correct + dependencies = [ "parent" ]; + script = '' + cat $in/parent/file > $out/newfile + ''; +}; +``` + +### Permission Denied + +**Symptom**: Service cannot read generated secret file + +**Solution**: Set correct ownership and permissions +```nix +files."service.key" = { + secret = true; + owner = "myservice"; # Match service user + group = "myservice"; + mode = "0400"; # Read-only for owner +}; +``` + +### Vars Not Regenerating + +**Symptom**: Changes to generator script don't trigger regeneration + +**Solution**: Use `--regenerate` flag +```bash +clan vars generate my-machine --generator my-generator --regenerate +``` + +### Prompts Not Working + +**Symptom**: Script fails with "No such file or directory" for prompts + +**Solution**: Access prompts correctly +```nix +# Wrong +script = '' + echo $password > $out/file +''; + +# Correct +prompts.password.type = "hidden"; +script = '' + cat $prompts/password > $out/file +''; +``` + +## Debugging Techniques + +### 1. Check Generator Status + +See what vars are set: +```bash +clan vars list my-machine +``` + +### 2. Inspect Generated Files + +For shared vars: +```bash +ls -la vars/shared/my-generator/ +``` + +For per-machine vars: +```bash +ls -la vars/per-machine/my-machine/my-generator/ +``` + +### 3. Test Generators Locally + +Create a test script to debug: +```nix +# test-generator.nix +{ pkgs ? import {} }: +pkgs.stdenv.mkDerivation { + name = "test-generator"; + buildInputs = [ pkgs.openssl ]; # Your runtime inputs + buildCommand = '' + # Your generator script here + mkdir -p $out + openssl rand -hex 32 > $out/secret + ls -la $out/ + ''; +} +``` + +Run with: +```bash +nix-build test-generator.nix +``` + +### 4. Enable Debug Logging + +Set debug mode: +```bash +clan --debug vars generate my-machine +``` + +### 5. Check File Permissions + +Verify generated secret permissions: +```bash +# On the target machine +ls -la /run/secrets/ +``` + +## Recovery Procedures + +### Regenerate All Vars + +If vars are corrupted or need refresh: +```bash +# Regenerate all for a machine +clan vars generate my-machine --regenerate + +# Regenerate specific generator +clan vars generate my-machine --generator my-generator --regenerate +``` + +### Manual Secret Injection + +For recovery or testing: +```bash +# Set a var manually (bypass generator) +echo "temporary-secret" | clan vars set my-machine my-generator/my-file +``` + +### Restore from Backup + +Vars are stored in the repository: +```bash +# Restore previous version +git checkout HEAD~1 -- vars/ + +# Check and regenerate if needed +clan vars list my-machine +``` + +## Storage Backend Issues + +### SOPS Decryption Fails + +**Symptom**: "Failed to decrypt" or permission errors + +**Solution**: Ensure your user/machine has the correct age keys configured. Clan manages encryption keys automatically based on the configured users and machines in your flake. + +Check that: + +1. Your machine is properly configured in the flake + +2. Your user has access to the machine's secrets + +3. The age key is available in the expected location + +### Password Store Issues + +**Symptom**: "pass: store not initialized" + +**Solution**: Initialize password store: +```bash +export PASSWORD_STORE_DIR=/path/to/clan/vars +pass init your-gpg-key +``` + +## Getting Help + +If these solutions don't resolve your issue: + +1. Check the [clan-core issue tracker](https://git.clan.lol/clan/clan-core/issues) +2. Ask in the Clan community channels +3. Provide: + + - The generator configuration + + - The exact error message + + - Output of `clan --debug vars generate` \ No newline at end of file diff --git a/tested-trappist/src/content/docs/index.md b/tested-trappist/src/content/docs/index.md new file mode 100644 index 000000000..1de55106f --- /dev/null +++ b/tested-trappist/src/content/docs/index.md @@ -0,0 +1,148 @@ +--- +title: Welcome to Clan +--- + +## What is Clan? + + + +

+ +
+

Clan is a peer-to-peer computer management framework that empowers you to selfhost in a reliable and scalable way.

+

Built on NixOS, Clan provides a declarative interface for managing machines with automated secret management, easy mesh VPN connectivity, and automated backups.

+

Whether you're running a homelab or maintaining critical computing infrastructure, Clan will help reduce maintenance burden by allowing a git repository to define your whole network of computers.

+

In combination with sops-nix, nixos-anywhere and disko, Clan makes it possible to have collaborative infrastructure.

+

At the heart of Clan are Clan Services - the core concept that enables you to add functionality across multiple machines in your network. While Clan ships with essential core services, you can create custom services tailored to your specific needs.

+
+ +
+ +--- + +[Get started](./guides/getting-started/index.md) +[View on Gitea](https://git.clan.lol/clan/clan-core) + +## Guides + +
+ +- [Inventory](./guides/inventory/inventory.md) + + *** + + Learn how about inventory + +- [Vars](./guides/vars/vars-overview.md) + + *** + + Learn how to use vars + +- [macOS](./guides/macos.md) + + *** + + Using Clan to manage your macOS machines + +
+ +## Reference + +
+ +- [CLI](./reference/cli/index.md) + + *** + + command line interface + +- [Clan Options](/options) + + *** + + Search all options + +- [Services](./reference/clanServices/index.md) + + *** + + Discover services + +
+ +## Blog + +
+ +- [Clan Blog](https://clan.lol/blog/) + + *** + + For the latest updates, tutorials, and community stories. + +
diff --git a/tested-trappist/src/content/docs/reference/clanServices/admin.md b/tested-trappist/src/content/docs/reference/clanServices/admin.md new file mode 100644 index 000000000..6c24ac65e --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/admin.md @@ -0,0 +1,107 @@ +--- +title: admin +description: Convenient Administration for the Clan App +--- + +*Convenient Administration for the Clan App* + + +--- + +## Roles +The admin module has the following roles: + +- default +## Options for the `default` role +#### allowedKeys + + + + + + +The allowed public keys for ssh access to the admin user + + +**Type**: `attribute set of string` + + +**Default**: + +```nix +{ } +``` + + +```nix title="example" +{ + key_1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD..."; +} +``` + + +πŸ“ƒ Declared in: [clanServices/admin/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/admin/default.nix) + + + +#### certificateSearchDomains + + + + + + +List of domains to include in the certificate. +This option will prepend the machine name in front of each domain before adding it to the certificate. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "mydomain.com" +] +``` + + +πŸ“ƒ Declared in: [clanServices/admin/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/admin/default.nix) + + + +#### rsaHostKey.enable + + + + + + +Whether to enable Generate RSA host key. + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + + +```nix title="example" +true +``` + + +πŸ“ƒ Declared in: [clanServices/admin/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/admin/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/borgbackup.md b/tested-trappist/src/content/docs/reference/clanServices/borgbackup.md new file mode 100644 index 000000000..829aa1eb2 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/borgbackup.md @@ -0,0 +1,218 @@ +--- +title: borgbackup +description: Efficient, deduplicating backup program with optional compression and secure encryption. +--- + +*Efficient, deduplicating backup program with optional compression and secure encryption.* +## Usage + +```nix +inventory.instances = { + borgbackup = { + module = { + name = "borgbackup"; + input = "clan-core"; + }; + roles.client.machines."jon".settings = { + destinations."storagebox" = { + repo = "username@$hostname:/./borgbackup"; + rsh = ''ssh -oPort=23 -i /run/secrets/vars/borgbackup/borgbackup.ssh''; + }; + }; + roles.server.machines = { }; + }; +}; +``` + +The input should be named according to your flake input. Jon is configured as a +client machine with a destination pointing to a Hetzner Storage Box. + +## Overview + +This guide explains how to set up and manage +[BorgBackup](https://borgbackup.readthedocs.io/) for secure, efficient backups +in a clan network. BorgBackup provides: + +- Space efficient storage of backups with deduplication +- Secure, authenticated encryption +- Compression: lz4, zstd, zlib, lzma or none +- Mountable backups with FUSE +- Easy installation on multiple platforms: Linux, macOS, BSD, … +- Free software (BSD license). +- Backed by a large and active open-source community. + +## Roles + +### 1. Client + +Clients are machines that create and send backups to various destinations. Each +client can have multiple backup destinations configured. + +### 2. Server + +Servers act as backup repositories, receiving and storing backups from client +machines. They can be dedicated backup servers within your clan network. + +## Backup destinations + +This service allows you to perform backups to multiple `destinations`. +Destinations can be: + +- **Local**: Local disk storage +- **Server**: Your own borgbackup server (using the `server` role) +- **Third-party services**: Such as Hetzner's Storage Box + +For a more comprehensive guide on backups look into the guide section. + + +--- + +## Roles +The borgbackup module has the following roles: + +- client +- server +## Options for the `client` role +#### destinations + + + + + + +external destinations where the machine should be backuped to + + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + + +#### destinations..name + + + + + + +the name of the backup job + + +**Type**: `string matching the pattern ^[a-zA-Z0-9._-]+$` + + +**Default**: + +```nix +"β€Ήnameβ€Ί" +``` + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + + +#### destinations..repo + + + + + + +the borgbackup repository to backup to + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + + +#### destinations..rsh + + + + + + +the rsh to use for the backup + + +**Type**: `string` + + +**Default**: + +```nix +"ssh -i \${config.clan.core.vars.generators.borgbackup.files.\"borgbackup.ssh\".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" +``` + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + + +#### exclude + + + + + + +Directories/Files to exclude from the backup. +Use * as a wildcard. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "*.pyc" +] +``` + + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + +## Options for the `server` role +#### directory + + + + + + +The directory where the borgbackup repositories are stored. + + + +**Type**: `string` + + +**Default**: + +```nix +"/var/lib/borgbackup" +``` + +πŸ“ƒ Declared in: [clanServices/borgbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/borgbackup/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/certificates.md b/tested-trappist/src/content/docs/reference/clanServices/certificates.md new file mode 100644 index 000000000..a44c28a6a --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/certificates.md @@ -0,0 +1,145 @@ +--- +title: certificates +description: Sets up a certificates internal to your Clan +--- + +*Sets up a certificates internal to your Clan* +This service sets up a certificate authority (CA) that can issue certificates to +other machines in your clan. For this the `ca` role is used. +It additionally provides a `default` role, that can be applied to all machines +in your clan and will make sure they trust your CA. + +## Example Usage + +The following configuration would add a CA for the top level domain `.foo`. If +the machine `server` now hosts a webservice at `https://something.foo`, it will +get a certificate from `ca` which is valid inside your clan. The machine +`client` will trust this certificate if it makes a request to +`https://something.foo`. + +This clan service can be combined with the `coredns` service for easy to deploy, +SSL secured clan-internal service hosting. + +```nix +inventory = { + machines.ca = { }; + machines.client = { }; + machines.server = { }; + + instances."certificates" = { + module.name = "certificates"; + module.input = "self"; + + roles.ca.machines.ca.settings.tlds = [ "foo" ]; + roles.default.machines.client = { }; + roles.default.machines.server = { }; + }; +}; +``` + + +--- + +## Roles +The certificates module has the following roles: + +- ca +- default +## Options for the `ca` role +#### acmeEmail + + + + + + +Email address for account creation and correspondence from the CA. +It is recommended to use the same email for all certs to avoid account +creation limits. + + + +**Type**: `string` + + +**Default**: + +```nix +"none@none.tld" +``` + +πŸ“ƒ Declared in: [clanServices/certificates/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/certificates/default.nix) + + + +#### expire + + + + + + +When the certificate should expire. + + +**Type**: `null or string` + + +**Default**: + +```nix +"8760h" +``` + + +```nix title="example" +"8760h" +``` + + +πŸ“ƒ Declared in: [clanServices/certificates/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/certificates/default.nix) + + + +#### tlds + + + + + + +Top level domain for this CA. Certificates will be issued and trusted for *. + + +**Type**: `list of string` + + +πŸ“ƒ Declared in: [clanServices/certificates/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/certificates/default.nix) + + +## Options for the `default` role +#### acmeEmail + + + + + + +Email address for account creation and correspondence from the CA. +It is recommended to use the same email for all certs to avoid account +creation limits. + + + +**Type**: `string` + + +**Default**: + +```nix +"none@none.tld" +``` + +πŸ“ƒ Declared in: [clanServices/certificates/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/certificates/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/coredns.md b/tested-trappist/src/content/docs/reference/clanServices/coredns.md new file mode 100644 index 000000000..79aabea6f --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/coredns.md @@ -0,0 +1,213 @@ +--- +title: coredns +description: Clan-internal DNS and service exposure +--- + +*Clan-internal DNS and service exposure* +This module enables hosting clan-internal services easily, which can be resolved +inside your VPN. This allows defining a custom top-level domain (e.g. `.clan`) +and exposing endpoints from a machine to others, which will be +accessible under `http://.clan` in your browser. + +The service consists of two roles: + +- A `server` role: This is the DNS-server that will be queried when trying to + resolve clan-internal services. It defines the top-level domain. +- A `default` role: This does two things. First, it sets up the nameservers so + that clan-internal queries are resolved via the `server` machine, while + external queries are resolved as normal via DHCP. Second, it allows exposing + services (see example below). + +## Example Usage + +Here the machine `dnsserver` is designated as internal DNS-server for the TLD +`.foo`. `server01` will host an application that shall be reachable at +`http://one.foo` and `server02` is going to be reachable at `http://two.foo`. +`client` is any other machine that is part of the clan but does not host any +services. + +When `client` tries to resolve `http://one.foo`, the DNS query will be +routed to `dnsserver`, which will answer with `192.168.1.3`. If it tries to +resolve some external domain (e.g. `https://clan.lol`), the query will not be +routed to `dnsserver` but resolved as before, via the nameservers advertised by +DHCP. + +```nix +inventory = { + + machines = { + dnsserver = { }; # 192.168.1.2 + server01 = { }; # 192.168.1.3 + server02 = { }; # 192.168.1.4 + client = { }; # 192.168.1.5 + }; + + instances = { + coredns = { + + module.name = "@clan/coredns"; + module.input = "self"; + + # Add the default role to all machines, including `client` + roles.default.tags.all = { }; + + # DNS server + roles.server.machines."dnsserver".settings = { + ip = "192.168.1.2"; + tld = "foo"; + }; + + # First service + roles.default.machines."server01".settings = { + ip = "192.168.1.3"; + services = [ "one" ]; + }; + + # Second service + roles.default.machines."server02".settings = { + ip = "192.168.1.4"; + services = [ "two" ]; + }; + }; + }; +}; +``` + + +--- + +## Roles +The coredns module has the following roles: + +- default +- server +## Options for the `default` role +#### dnsPort + + + + + + +Port of the clan-internal DNS server + + +**Type**: `signed integer` + + +**Default**: + +```nix +1053 +``` + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + + +#### ip + + + + + + +IP on which the services will listen + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + + +#### services + + + + + + +Service endpoints this host exposes (without TLD). Each entry will +be resolved to . using the configured top-level domain. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + +## Options for the `server` role +#### dnsPort + + + + + + +Port of the clan-internal DNS server + + +**Type**: `signed integer` + + +**Default**: + +```nix +1053 +``` + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + + +#### ip + + + + + + +IP for the DNS to listen on + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + + +#### tld + + + + + + +Top-level domain for this instance. All services below this will be +resolved internally. + + + +**Type**: `string` + + +**Default**: + +```nix +"clan" +``` + +πŸ“ƒ Declared in: [clanServices/coredns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/coredns/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/data-mesher.md b/tested-trappist/src/content/docs/reference/clanServices/data-mesher.md new file mode 100644 index 000000000..a961b9750 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/data-mesher.md @@ -0,0 +1,337 @@ +--- +title: data-mesher +description: Set up data-mesher +--- + +*Set up data-mesher* +This service will set up data-mesher. + +## Usage + +```nix +inventory.instances = { + data-mesher = { + module = { + name = "data-mesher"; + input = "clan-core"; + }; + roles.admin.machines.server0 = { + settings = { + bootstrapNodes = { + node1 = "192.168.1.1:7946"; + node2 = "192.168.1.2:7946"; + }; + + network = { + hostTTL = "24h"; + interface = "tailscale0"; + }; + }; + }; + roles.peer.machines.server1 = { }; + roles.signer.machines.server2 = { }; + }; +} +``` + + +--- + +## Roles +The data-mesher module has the following roles: + +- admin +- peer +- signer +## Options for the `admin` role +#### bootstrapNodes + + + + + + +A list of bootstrap nodes that act as an initial gateway when joining +the cluster. + + + +**Type**: `null or (list of string)` + + + +```nix title="example" +[ + "192.168.1.1:7946" + "192.168.1.2:7946" +] +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.hostTTL + + + + + + +The TTL for hosts in the network, in the form of a Go time.Duration + + +**Type**: `string` + + +**Default**: + +```nix +"672h" +``` + + +```nix title="example" +"24h" +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.interface + + + + + + +The interface over which cluster communication should be performed. +All the ip addresses associate with this interface will be part of +our host claim, including both ipv4 and ipv6. + +This should be set to an internal/VPN interface. + + + +**Type**: `string` + + + +```nix title="example" +"tailscale0" +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.port + + + + + + +Port to listen on for cluster communication. + + + +**Type**: `16 bit unsigned integer; between 0 and 65535 (both inclusive)` + + +**Default**: + +```nix +7946 +``` + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.tld + + + + + + +Top level domain to use for the network + + +**Type**: `string` + + +**Default**: + +```nix +"clan" +``` + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + +## Options for the `peer` role +#### bootstrapNodes + + + + + + +A list of bootstrap nodes that act as an initial gateway when joining +the cluster. + + + +**Type**: `null or (list of string)` + + + +```nix title="example" +[ + "192.168.1.1:7946" + "192.168.1.2:7946" +] +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.interface + + + + + + +The interface over which cluster communication should be performed. +All the ip addresses associate with this interface will be part of +our host claim, including both ipv4 and ipv6. + +This should be set to an internal/VPN interface. + + + +**Type**: `string` + + + +```nix title="example" +"tailscale0" +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.port + + + + + + +Port to listen on for cluster communication. + + + +**Type**: `16 bit unsigned integer; between 0 and 65535 (both inclusive)` + + +**Default**: + +```nix +7946 +``` + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + +## Options for the `signer` role +#### bootstrapNodes + + + + + + +A list of bootstrap nodes that act as an initial gateway when joining +the cluster. + + + +**Type**: `null or (list of string)` + + + +```nix title="example" +[ + "192.168.1.1:7946" + "192.168.1.2:7946" +] +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.interface + + + + + + +The interface over which cluster communication should be performed. +All the ip addresses associate with this interface will be part of +our host claim, including both ipv4 and ipv6. + +This should be set to an internal/VPN interface. + + + +**Type**: `string` + + + +```nix title="example" +"tailscale0" +``` + + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + + +#### network.port + + + + + + +Port to listen on for cluster communication. + + + +**Type**: `16 bit unsigned integer; between 0 and 65535 (both inclusive)` + + +**Default**: + +```nix +7946 +``` + +πŸ“ƒ Declared in: [clanServices/data-mesher/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/data-mesher/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/dyndns.md b/tested-trappist/src/content/docs/reference/clanServices/dyndns.md new file mode 100644 index 000000000..d39342e5e --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/dyndns.md @@ -0,0 +1,335 @@ +--- +title: dyndns +description: A dynamic DNS service to update domain IPs +--- + +*A dynamic DNS service to update domain IPs* + +A Dynamic-DNS (DDNS) service continuously keeps one or more DNS records in sync with the current public IP address of your machine. +In *clan* this service is backed by [qdm12/ddns-updater](https://github.com/qdm12/ddns-updater). + +> Info +> ddns-updater itself is **heavily opinionated and version-specific**. Whenever you need the exhaustive list of flags or +> provider-specific fields refer to its *versioned* documentation – **not** the GitHub README +--- + +# 1. Configuration model + +Internally ddns-updater consumes a single file named `config.json`. +A minimal configuration for the registrar *Namecheap* looks like: + +```json +{ + "settings": [ + { + "provider": "namecheap", + "domain": "sub.example.com", + "password": "e5322165c1d74692bfa6d807100c0310" + } + ] +} +``` + +Another example for *Porkbun*: + +```json +{ + "settings": [ + { + "provider": "porkbun", + "domain": "domain.com", + "api_key": "sk1_…", + "secret_api_key": "pk1_…", + "ip_version": "ipv4", + "ipv6_suffix": "" + } + ] +} +``` + +When you write a `clan.nix` the **common** fields (`provider`, `domain`, `period`, …) are already exposed as typed +*Nix options*. +Registrar-specific or very new keys can be passed through an open attribute set called **extraSettings**. + +--- + +# 2. Full Porkbun example + +Manage three records – `@`, `home` and `test` – of the domain +`jon.blog` and refresh them every 15 minutes: + +```nix title="clan.nix" hl_lines="10-11" +inventory.instances = { + dyndns = { + roles.default.machines."jon" = { }; + roles.default.settings = { + period = 15; # minutes + settings = { + "all-jon-blog" = { + provider = "porkbun"; + domain = "jon.blog"; + + # (1) tell the secret-manager which key we are going to store + secret_field_name = "secret_api_key"; + + # everything below is copied verbatim into config.json + extraSettings = { + host = "@,home,test"; # (2) comma-separated list of sub-domains + ip_version = "ipv4"; + ipv6_suffix = ""; + api_key = "pk1_4bb2b231275a02fdc23b7e6f3552s01S213S"; # (3) public – safe to commit + }; + }; + }; + }; + }; +}; +``` + +1. `secret_field_name` tells the *vars-generator* to store the entered secret under the specified JSON field name in the configuration. +2. ddns-updater allows multiple hosts by separating them with a comma. +3. The `api_key` above is *public*; the corresponding **private key** is retrieved through `secret_field_name`. + + + +--- + +## Roles +The dyndns module has the following roles: + +- default +## Options for the `default` role +#### period + + + + + + +Domain update period in minutes + + +**Type**: `signed integer` + + +**Default**: + +```nix +5 +``` + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### server.acmeEmail + + + + + + +Email address for account creation and correspondence from the CA. +It is recommended to use the same email for all certs to avoid account +creation limits. + + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### server.domain + + + + + + +Domain to serve the webservice on + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### server.enable + + + + + + +Whether to enable dyndns webserver. + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + + +```nix title="example" +true +``` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### server.port + + + + + + +Port to listen on + + +**Type**: `signed integer` + + +**Default**: + +```nix +54805 +``` + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### settings + + + + + + +Configuration for which domains to update + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### settings..domain + + + + + + +The top level domain to update. + + +**Type**: `string` + + + +```nix title="example" +"example.com" +``` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### settings..extraSettings + + + + + + +Extra settings for the provider. +Provider specific settings: https://github.com/qdm12/ddns-updater#configuration + + + +**Type**: `attribute set of string` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### settings..provider + + + + + + +The dyndns provider to use + + +**Type**: `string` + + + +```nix title="example" +"namecheap" +``` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + + +#### settings..secret_field_name + + + + + + +The field name for the secret + + +**Type**: `one of "password", "token", "api_key", "secret_api_key"` + + +**Default**: + +```nix +"password" +``` + + +```nix title="example" +"api_key" +``` + + +πŸ“ƒ Declared in: [clanServices/dyndns/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/dyndns/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/emergency-access.md b/tested-trappist/src/content/docs/reference/clanServices/emergency-access.md new file mode 100644 index 000000000..ea7e001ab --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/emergency-access.md @@ -0,0 +1,31 @@ +--- +title: emergency-access +description: Set recovery password for emergency access to machine +--- + +*Set recovery password for emergency access to machine* +This service will automatically set the emergency access password if your system fails to boot. + +## Usage + +```nix +inventory.instances = { + emergency-access = { + module = { + name = "emergency-access"; + input = "clan-core"; + }; + + roles.default.tags.nixos = { }; + }; +} +``` + + +--- + +## Roles +The emergency-access module has the following roles: + +- default +This role has no configuration \ No newline at end of file diff --git a/tested-trappist/src/content/docs/reference/clanServices/garage.md b/tested-trappist/src/content/docs/reference/clanServices/garage.md new file mode 100644 index 000000000..769d323c9 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/garage.md @@ -0,0 +1,15 @@ +--- +title: garage +description: S3-compatible object store for small self-hosted geo-distributed deployments +--- + +*S3-compatible object store for small self-hosted geo-distributed deployments* + + +--- + +## Roles +The garage module has the following roles: + +- default +This role has no configuration \ No newline at end of file diff --git a/tested-trappist/src/content/docs/reference/clanServices/hello-world.md b/tested-trappist/src/content/docs/reference/clanServices/hello-world.md new file mode 100644 index 000000000..d79e8b7e1 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/hello-world.md @@ -0,0 +1,61 @@ +--- +title: hello-world +description: This is a test +--- + +*This is a test* + + +--- + +## Roles +The hello-world module has the following roles: + +- evening +- morning +## Options for the `evening` role +#### greeting + + + + + + +The greeting to use + + +**Type**: `string` + + +**Default**: + +```nix +"Good evening" +``` + +πŸ“ƒ Declared in: [clanServices/hello-world/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/hello-world/default.nix) + + +## Options for the `morning` role +#### greeting + + + + + + +The greeting to use + + +**Type**: `string` + + +**Default**: + +```nix +"Good morning" +``` + +πŸ“ƒ Declared in: [clanServices/hello-world/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/hello-world/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/importer.md b/tested-trappist/src/content/docs/reference/clanServices/importer.md new file mode 100644 index 000000000..93f90b41a --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/importer.md @@ -0,0 +1,41 @@ +--- +title: importer +description: Convenient, structured module imports for hosts. +--- + +*Convenient, structured module imports for hosts.* +The importer module allows users to configure importing modules in a flexible and structured way. +It exposes the `extraModules` functionality of the inventory, without any added configuration. + +## Usage + +```nix +inventory.instances = { + + zone1 = { + module.name = "@clan/importer"; + roles.default.tags.zone1 = {}; + roles.default.extraModules = [ "modules/zone1.nix" ]; + }; + + base = { + module.name = "@clan/importer"; + roles.default.tags.all = {}; + roles.default.extraModules = [ "modules/base.nix" ]; + }; + +}; +``` + +This will import the module `modules/base.nix` to all machines that have the `all` tag, +which by default is every machine managed by the clan. +And also import for all machines tagged with `zone1` the module at `modules/zone1.nix`. + + +--- + +## Roles +The importer module has the following roles: + +- default +This role has no configuration \ No newline at end of file diff --git a/tested-trappist/src/content/docs/reference/clanServices/localbackup.md b/tested-trappist/src/content/docs/reference/clanServices/localbackup.md new file mode 100644 index 000000000..57aebed25 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/localbackup.md @@ -0,0 +1,290 @@ +--- +title: localbackup +description: Automatically backups current machine to local directory. +--- + +*Automatically backups current machine to local directory.* +## Features + +- Creates incremental snapshots using rsnapshot +- Supports multiple backup targets +- Mount/unmount hooks for external storage +- Pre/post backup hooks for custom scripts +- Configurable snapshot retention +- Automatic state folder detection + +## Usage + +Enable the localbackup service and configure backup targets: + +```nix +instances = { + localbackup = { + module.name = "@clan/localbackup"; + module.input = "self"; + roles.default.machines."machine".settings = { + targets.external= { + directory = "/mnt/backup"; + mountpoint = "/mnt/backup"; + }; + }; + }; +}; +``` + +## Commands + +The service provides these commands: + +- `localbackup-create`: Create a new backup +- `localbackup-list`: List available backups +- `localbackup-restore`: Restore from backup (requires NAME and FOLDERS environment variables) + + +--- + +## Roles +The localbackup module has the following roles: + +- default +## Options for the `default` role +#### snapshots + + + + + + +Number of snapshots to keep + + +**Type**: `signed integer` + + +**Default**: + +```nix +20 +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets + + + + + + +List of directories where backups are stored + + +**Type**: `attribute set of (submodule)` + + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..directory + + + + + + +the directory to backup + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..mountpoint + + + + + + +mountpoint of the directory to backup. If set, the directory will be mounted before the backup and unmounted afterwards + + +**Type**: `null or string` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..name + + + + + + +the name of the backup job + + +**Type**: `string matching the pattern ^[a-zA-Z0-9._-]+$` + + +**Default**: + +```nix +"β€Ήnameβ€Ί" +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..postBackupHook + + + + + + +Shell commands to run after the backup + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..postMountHook + + + + + + +Shell commands to run after the directory is mounted + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..postUnmountHook + + + + + + +Shell commands to run after the directory is unmounted + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..preBackupHook + + + + + + +Shell commands to run before the backup + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..preMountHook + + + + + + +Shell commands to run before the directory is mounted + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + + +#### targets..preUnmountHook + + + + + + +Shell commands to run before the directory is unmounted + + +**Type**: `null or strings concatenated with "\n"` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/localbackup/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/localbackup/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/matrix-synapse.md b/tested-trappist/src/content/docs/reference/clanServices/matrix-synapse.md new file mode 100644 index 000000000..a9bc2347c --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/matrix-synapse.md @@ -0,0 +1,176 @@ +--- +title: matrix-synapse +description: A federated messaging server with end-to-end encryption. +--- + +*A federated messaging server with end-to-end encryption.* + + +--- + +## Roles +The matrix-synapse module has the following roles: + +- default +## Options for the `default` role +#### acmeEmail + + + + + + +Email address for account creation and correspondence from the CA. +It is recommended to use the same email for all certs to avoid account +creation limits. + + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### app_domain + + + + + + +The matrix server hostname also serves the element client + + +**Type**: `string` + + + +```nix title="example" +"matrix.example.com" +``` + + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### server_tld + + + + + + +The address that is suffixed after your username i.e @alice:example.com + + +**Type**: `string` + + + +```nix title="example" +"example.com" +``` + + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### services.matrix-synapse.package + + + + + + +Package to use for matrix-synapse + + +**Type**: `unspecified value` + + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### users + + + + + + +A list of users. Not that only new users will be created and existing ones are not modified. + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + + +```nix title="example" +{ + alice = { + admin = true; + }; +} +``` + + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### users..admin + + + + + + +Whether the user should be an admin + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + + +#### users..name + + + + + + +The name of the user + + +**Type**: `string` + + +**Default**: + +```nix +"β€Ήnameβ€Ί" +``` + +πŸ“ƒ Declared in: [clanServices/matrix-synapse/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/matrix-synapse/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/monitoring.md b/tested-trappist/src/content/docs/reference/clanServices/monitoring.md new file mode 100644 index 000000000..50d75fe36 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/monitoring.md @@ -0,0 +1,79 @@ +--- +title: monitoring +description: Monitoring service for the nodes in your clan +--- + +*Monitoring service for the nodes in your clan* +## Usage + +``` +inventory.instances = { + monitoring = { + module.name = "monitoring"; + roles.telegraf.tags.all = { + settings.interfaces = [ "wg-clan" ]; + }; + }; + }; +``` + +This service will eventually set up a monitoring stack for your clan. For now, +only a telegraf role is implemented, which exposes the currently deployed +version of your configuration, so it can be used to check for required updates. + + + +--- + +## Roles +The monitoring module has the following roles: + +- telegraf +## Options for the `telegraf` role +#### allowAllInterfaces + + + + + + +If true, Telegraf will listen on all interfaces. Otherwise, it will only listen on the interfaces specified in `interfaces` + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + +πŸ“ƒ Declared in: [clanServices/monitoring/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/monitoring/default.nix) + + + +#### interfaces + + + + + + +List of interfaces to expose the metrics to + + +**Type**: `list of string` + + +**Default**: + +```nix +[ + "zt+" +] +``` + +πŸ“ƒ Declared in: [clanServices/monitoring/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/monitoring/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/mycelium.md b/tested-trappist/src/content/docs/reference/clanServices/mycelium.md new file mode 100644 index 000000000..bca110aeb --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/mycelium.md @@ -0,0 +1,60 @@ +--- +title: mycelium +description: End-2-end encrypted IPv6 overlay network +--- + +*End-2-end encrypted IPv6 overlay network* + + +--- + +## Roles +The mycelium module has the following roles: + +- peer +## Options for the `peer` role +#### addHostedPublicNodes + + + + + + +Add hosted Public nodes + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + +πŸ“ƒ Declared in: [clanServices/mycelium/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/mycelium/default.nix) + + + +#### openFirewall + + + + + + +Open the firewall for mycelium + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + +πŸ“ƒ Declared in: [clanServices/mycelium/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/mycelium/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/packages.md b/tested-trappist/src/content/docs/reference/clanServices/packages.md new file mode 100644 index 000000000..9f991566a --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/packages.md @@ -0,0 +1,45 @@ +--- +title: packages +description: Define package sets from nixpkgs and install them on one or more machines +--- + +*Define package sets from nixpkgs and install them on one or more machines* + + +--- + +## Roles +The packages module has the following roles: + +- default +## Options for the `default` role +#### packages + + + + + + +The packages to install on the machine + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "cowsay" +] +``` + + +πŸ“ƒ Declared in: [clanServices/packages/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/packages/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/sshd.md b/tested-trappist/src/content/docs/reference/clanServices/sshd.md new file mode 100644 index 000000000..3730a92f3 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/sshd.md @@ -0,0 +1,148 @@ +--- +title: sshd +description: Enables secure remote access to the machine over SSH +--- + +*Enables secure remote access to the machine over SSH* +The `sshd` Clan service manages SSH to make it easy to securely access your machines over the internet. The service uses `vars` to store the SSH host keys for each machine to ensure they remain stable across deployments. + +`sshd` also generates SSH certificates for both servers and clients allowing for certificate-based authentication for SSH. + +The service also disables password-based authentication over SSH, to access your machines you'll need to use public key authentication or certificate-based authentication. + +## Usage + +```nix +{ + inventory.instances = { + # By default this service only generates ed25519 host keys + sshd-basic = { + module = { + name = "sshd"; + input = "clan-core"; + }; + roles.server.tags.all = { }; + roles.client.tags.all = { }; + }; + + # Also generate RSA host keys for all servers + sshd-with-rsa = { + module = { + name = "sshd"; + input = "clan-core"; + }; + roles.server.tags.all = { }; + roles.server.settings = { + hostKeys.rsa.enable = true; + }; + roles.client.tags.all = { }; + }; + }; +} +``` + + +--- + +## Roles +The sshd module has the following roles: + +- client +- server +## Options for the `client` role +#### certificate.searchDomains + + + + + + +List of domains to include in the certificate. +This option will prepend the machine name in front of each domain +before adding it to the certificate. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "mydomain.com" +] +``` + + +πŸ“ƒ Declared in: [clanServices/sshd/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/sshd/default.nix) + + +## Options for the `server` role +#### certificate.searchDomains + + + + + + +List of domains to include in the certificate. This option will +prepend the machine name in front of each domain before adding +it to the certificate. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "mydomain.com" +] +``` + + +πŸ“ƒ Declared in: [clanServices/sshd/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/sshd/default.nix) + + + +#### hostKeys.rsa.enable + + + + + + +Whether to enable Generate RSA host key. + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + + +```nix title="example" +true +``` + + +πŸ“ƒ Declared in: [clanServices/sshd/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/sshd/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/syncthing.md b/tested-trappist/src/content/docs/reference/clanServices/syncthing.md new file mode 100644 index 000000000..79c70b1fd --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/syncthing.md @@ -0,0 +1,369 @@ +--- +title: syncthing +description: Syncthing is a continuous file synchronization program with automatic peer discovery +--- + +*Syncthing is a continuous file synchronization program with automatic peer discovery* +## Usage + +```nix +{ + instances.syncthing = { + roles.peer.tags.all = { }; + roles.peer.settings.folders = { + documents = { + path = "~/syncthing/documents"; + }; + }; + }; +} +``` + +Now the folder `~/syncthing/documents` will be shared with all your machines. + + +## Documentation +Extensive documentation is available on the [Syncthing](https://docs.syncthing.net/) website. + + +--- + +## Roles +The syncthing module has the following roles: + +- peer +## Options for the `peer` role +#### extraDevices + + + + + + +External syncthing devices not managed by clan (e.g., mobile phones) + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + + +```nix title="example" +{ + phone = { + id = "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"; + name = "My Phone"; + addresses = [ "dynamic" ]; + }; +} + +``` + + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### extraDevices..addresses + + + + + + +List of addresses for the device + + +**Type**: `list of string` + + +**Default**: + +```nix +[ + "dynamic" +] +``` + + +```nix title="example" +[ + "dynamic" + "tcp://192.168.1.100:22000" +] +``` + + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### extraDevices..id + + + + + + +Device ID of the external syncthing device + + +**Type**: `string` + + + +```nix title="example" +"P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" +``` + + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### extraDevices..name + + + + + + +Human readable name for the device + + +**Type**: `string` + + +**Default**: + +```nix +"" +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders + + + + + + +Folders to synchronize between all peers + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..devices + + + + + + +List of device names to share this folder with. Empty list means all peers and extraDevices. + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..ignorePerms + + + + + + +Ignore permission changes + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..path + + + + + + +Path to the folder to sync + + +**Type**: `string` + + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..rescanIntervalS + + + + + + +Rescan interval in seconds + + +**Type**: `signed integer` + + +**Default**: + +```nix +3600 +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..type + + + + + + +Folder type + + +**Type**: `one of "sendreceive", "sendonly", "receiveonly"` + + +**Default**: + +```nix +"sendreceive" +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..versioning + + + + + + +Versioning configuration + + +**Type**: `null or (submodule)` + + +**Default**: + +```nix +null +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..versioning.params + + + + + + +Versioning parameters + + +**Type**: `attribute set of string` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### folders..versioning.type + + + + + + +Versioning type + + +**Type**: `one of "external", "simple", "staggered", "trashcan"` + + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + + +#### openDefaultPorts + + + + + + +Whether to open the default syncthing ports in the firewall. + + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + +πŸ“ƒ Declared in: [clanServices/syncthing/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/syncthing/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/trusted-nix-caches.md b/tested-trappist/src/content/docs/reference/clanServices/trusted-nix-caches.md new file mode 100644 index 000000000..1769ba085 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/trusted-nix-caches.md @@ -0,0 +1,30 @@ +--- +title: trusted-nix-caches +description: This module sets the `clan.lol` and `nix-community` cache up as a trusted cache. +--- + +*This module sets the `clan.lol` and `nix-community` cache up as a trusted cache.* +Sets up nix to trust and use the clan cache + +## Usage + +```nix +inventory.instances = { + clan-cache = { + module = { + name = "trusted-nix-caches"; + input = "clan-core"; + }; + roles.default.machines.draper = { }; + }; +} +``` + + +--- + +## Roles +The trusted-nix-caches module has the following roles: + +- default +This role has no configuration \ No newline at end of file diff --git a/tested-trappist/src/content/docs/reference/clanServices/users.md b/tested-trappist/src/content/docs/reference/clanServices/users.md new file mode 100644 index 000000000..82a4b707f --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/users.md @@ -0,0 +1,242 @@ +--- +title: users +description: An instance of this module will create a user account on the added machines, along with a generated password that is constant across machines and user settings. +--- + +*An instance of this module will create a user account on the added machines, +along with a generated password that is constant across machines and user settings. +* +## Usage + +```nix +{ + inventory.instances = { + # Deploy user alice on all machines. Don't prompt for password (will be + # auto-generated). + user-alice = { + module = { + name = "users"; + input = "clan-core"; + }; + roles.default.tags.all = { }; + roles.default.settings = { + user = "alice"; + prompt = false; + }; + }; + + # Deploy user Carol on all machines. Prompt only once and use the + # same password on all machines. (`share = true`) + user-carol = { + module = { + name = "users"; + input = "clan"; + }; + roles.default.tags.all = { }; + roles.default.settings = { + user = "carol"; + share = true; + }; + }; + + # Deploy user bob only on his laptop. Prompt for a password. + user-bob = { + module = { + name = "users"; + input = "clan-core"; + }; + roles.default.machines.bobs-laptop = { }; + roles.default.settings.user = "bob"; + }; + }; +} +``` + +## Migration from `root-password` module + +The deprecated `clan.root-password` module has been replaced by the `users` module. Here's how to migrate: + +### 1. Update your flake configuration + +Replace the `root-password` module import with a `users` service instance: + +```nix +# OLD - Remove this from your nixosModules: +imports = [ + self.inputs.clan-core.clanModules.root-password +]; + +# NEW - Add to inventory.instances or machines/flake-module.nix: +instances = { + users-root = { + module.name = "users"; + module.input = "clan-core"; + roles.default.tags.nixos = { }; + roles.default.settings = { + user = "root"; + prompt = false; # Set to true if you want to be prompted + groups = [ ]; + }; + }; +}; +``` + +### 2. Migrate vars + +The vars structure has changed from `root-password` to `user-password-root`: + +```bash +# For each machine, rename the vars directories: +cd vars/per-machine// +mv root-password user-password-root +mv user-password-root/password-hash user-password-root/user-password-hash +mv user-password-root/password user-password-root/user-password +``` + + +--- + +## Roles +The users module has the following roles: + +- default +## Options for the `default` role +#### groups + + + + + + +Additional groups the user should be added to. +You can add any group that exists on your system. +Make sure these group exists on all machines where the user is enabled. + +Commonly used groups: + +- "wheel" - Allows the user to run commands as root using `sudo`. +- "networkmanager" - Allows the user to manage network connections. +- "video" - Allows the user to access video devices. +- "input" - Allows the user to access input devices. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +[ + "wheel" + "networkmanager" + "video" + "input" +] +``` + + +πŸ“ƒ Declared in: [clanServices/users/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/users/default.nix) + + + +#### prompt + + + + + + +Whether the user should be prompted for a password. + +Effects: + +- *enabled* (`true`) - Prompt for a password during the machine installation or update workflow. +- *disabled* (`false`) - Generate a password during the machine installation or update workflow. + +The password can be shown in two steps: + +- `clan vars list ` +- `clan vars get ` + + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + + +```nix title="example" +false +``` + + +πŸ“ƒ Declared in: [clanServices/users/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/users/default.nix) + + + +#### share + + + + + + +Weather the user should have the same password on all machines. + +By default, you will be prompted for a new password for every host. +Unless `generate` is set to `true`. + + + +**Type**: `boolean` + + +**Default**: + +```nix +false +``` + + +```nix title="example" +true +``` + + +πŸ“ƒ Declared in: [clanServices/users/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/users/default.nix) + + + +#### user + + + + + + +The user the password should be generated for. + + +**Type**: `string` + + + +```nix title="example" +"alice" +``` + + +πŸ“ƒ Declared in: [clanServices/users/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/users/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/wifi.md b/tested-trappist/src/content/docs/reference/clanServices/wifi.md new file mode 100644 index 000000000..363c4e01a --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/wifi.md @@ -0,0 +1,109 @@ +--- +title: wifi +description: No description +--- + +*No description* + + +--- + +## Roles +The wifi module has the following roles: + +- default +## Options for the `default` role +#### networks + + + + + + +Wifi networks to predefine + + +**Type**: `attribute set of (submodule)` + + +**Default**: + +```nix +{ } +``` + +πŸ“ƒ Declared in: [clanServices/wifi/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wifi/default.nix) + + + +#### networks..autoConnect + + + + + + +Automatically try to join this wifi network + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + +πŸ“ƒ Declared in: [clanServices/wifi/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wifi/default.nix) + + + +#### networks..enable + + + + + + +Enable this wifi network + + +**Type**: `boolean` + + +**Default**: + +```nix +true +``` + +πŸ“ƒ Declared in: [clanServices/wifi/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wifi/default.nix) + + + +#### networks..keyMgmt + + + + + + +Key management used for the connection. +One of "none" (WEP or no password protection), "ieee8021x" (Dynamic WEP), "owe" (Opportunistic Wireless Encryption), "wpa-psk" (WPA2 + WPA3 personal), +"sae" (WPA3 personal only), "wpa-eap" (WPA2 + WPA3 enterprise) or "wpa-eap-suite-b-192" (WPA3 enterprise only). + + + +**Type**: `string` + + +**Default**: + +```nix +"wpa-psk" +``` + +πŸ“ƒ Declared in: [clanServices/wifi/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wifi/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/wireguard.md b/tested-trappist/src/content/docs/reference/clanServices/wireguard.md new file mode 100644 index 000000000..ecf87ae74 --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/wireguard.md @@ -0,0 +1,390 @@ +--- +title: wireguard +description: Wireguard-based VPN mesh network with automatic IPv6 address allocation +--- + +*Wireguard-based VPN mesh network with automatic IPv6 address allocation* +# Wireguard VPN Service + +This service provides a Wireguard-based VPN mesh network with automatic IPv6 address allocation and routing between clan machines. + +## Overview + +The wireguard service creates a secure mesh network between clan machines using two roles: +- **Controllers**: Machines with public endpoints that act as connection points and routers +- **Peers**: Machines that connect through controllers to access the network + +## Requirements + +- Controllers must have a publicly accessible endpoint (domain name or static IP) +- Peers must be in networks where UDP traffic is not blocked (uses port 51820 by default, configurable) + +## Features + +- Automatic IPv6 address allocation using ULA (Unique Local Address) prefixes +- Full mesh connectivity between all machines +- Automatic key generation and distribution +- IPv6 forwarding on controllers for inter-peer communication +- Support for multiple controllers for redundancy + +## Network Architecture + +### IPv6 Address Allocation +- Base network: `/40` ULA prefix (deterministically generated from instance name) +- Controllers: Each gets a `/56` subnet from the base `/40` +- Peers: Each gets a unique 64-bit host suffix that is used in ALL controller subnets + +### Addressing Design +- Each peer generates a unique host suffix (e.g., `:8750:a09b:0:1`) +- This suffix is appended to each controller's `/56` prefix to create unique addresses +- Example: peer1 with suffix `:8750:a09b:0:1` gets: + - `fd51:19c1:3b:f700:8750:a09b:0:1` in controller1's subnet + - `fd51:19c1:c1:aa00:8750:a09b:0:1` in controller2's subnet +- Controllers allow each peer's `/96` subnet for routing flexibility + +### Connectivity +- Peers use a single WireGuard interface with multiple IPs (one per controller subnet) +- Controllers connect to ALL other controllers and ALL peers on a single interface +- Controllers have IPv6 forwarding enabled to route traffic between peers +- All traffic between peers flows through controllers +- Symmetric routing is maintained as each peer has consistent IPs across all controllers + +### Example Network Topology + +```mermaid +graph TB + subgraph Controllers + C1[controller1
endpoint: vpn1.example.com
fd51:19c1:3b:f700::/56] + C2[controller2
endpoint: vpn2.example.com
fd51:19c1:c1:aa00::/56] + end + + subgraph Peers + P1[peer1
designated: controller1] + P2[peer2
designated: controller2] + P3[peer3
designated: controller1] + end + + %% Controllers connect to each other + C1 <--> C2 + + %% All peers connect to all controllers + P1 <--> C1 + P1 <--> C2 + P2 <--> C1 + P2 <--> C2 + P3 <--> C1 + P3 <--> C2 + + %% Peer-to-peer traffic flows through controllers + P1 -.->|via controllers| P3 + P1 -.->|via controllers| P2 + P2 -.->|via controllers| P3 + + classDef controller fill:#f9f,stroke:#333,stroke-width:4px + classDef peer fill:#bbf,stroke:#333,stroke-width:2px + class C1,C2 controller + class P1,P2,P3 peer +``` + +## Configuration + +### Basic Setup with Single Controller + +```nix +# In your flake.nix or inventory +{ + services.wireguard.server1 = { + roles.controller = { + # Public endpoint where this controller can be reached + endpoint = "vpn.example.com"; + # Optional: Change the UDP port (default: 51820) + port = 51820; + }; + }; + + services.wireguard.laptop1 = { + roles.peer = { + # No configuration needed if only one controller exists + }; + }; +} +``` + +### Multiple Controllers Setup + +```nix +{ + services.wireguard.server1 = { + roles.controller = { + endpoint = "vpn1.example.com"; + }; + }; + + services.wireguard.server2 = { + roles.controller = { + endpoint = "vpn2.example.com"; + }; + }; + + services.wireguard.laptop1 = { + roles.peer = { + # Must specify which controller subnet is exposed as the default in /etc/hosts, when multiple controllers exist + controller = "server1"; + }; + }; +} +``` + +### Advanced Options + + +### Automatic Hostname Resolution + +The wireguard service automatically adds entries to `/etc/hosts` for all machines in the network. Each machine is accessible via its hostname in the format `.`. + +For example, with an instance named `vpn`: +- `server1.vpn` - resolves to server1's IPv6 address +- `laptop1.vpn` - resolves to laptop1's IPv6 address + +This allows machines to communicate using hostnames instead of IPv6 addresses: + +```bash +# Ping another machine by hostname +ping6 server1.vpn + +# SSH to another machine +ssh user@laptop1.vpn +``` + +## Troubleshooting + +### Check Wireguard Status +```bash +sudo wg show +``` + +### Verify IP Addresses +```bash +ip addr show dev +``` + +### Check Routing +```bash +ip -6 route show dev +``` + +### Interface Fails to Start: "Address already in use" + +If you see this error in your logs: +``` +wireguard: Could not bring up interface, ignoring: Address already in use +``` + +This means the configured port (default: 51820) is already in use by another service or wireguard instance. Solutions: + +1. **Check for conflicting wireguard instances:** + ```bash + sudo wg show + sudo ss -ulnp | grep 51820 + ``` + +2. **Use a different port:** + ```nix + services.wireguard.myinstance = { + roles.controller = { + endpoint = "vpn.example.com"; + port = 51821; # Use a different port + }; + }; + ``` + +3. **Ensure unique ports across multiple instances:** + If you have multiple wireguard instances on the same machine, each must use a different port. + +### Key Management + +Keys are automatically generated and stored in the clan vars system. To regenerate keys: + +```bash +# Regenerate keys for a specific machine and instance +clan vars generate --service wireguard-keys- --regenerate --machine + +# Apply the new keys +clan machines update +``` + +## Security Considerations + +- All traffic is encrypted using Wireguard's modern cryptography +- Private keys never leave the machines they're generated on +- Public keys are distributed through the clan vars system +- Controllers must have publicly accessible endpoints +- Firewall rules are automatically configured for the Wireguard ports + + + +--- + +## Roles +The wireguard module has the following roles: + +- controller +- peer +## Options for the `controller` role +#### domain + + + + + + +Domain suffix to use for hostnames in /etc/hosts. +Defaults to the instance name. + + + +**Type**: `null or string` + + +**Default**: + +```nix +instanceName +``` + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + + +#### endpoint + + + + + + +Endpoint where the controller can be reached + + + +**Type**: `string` + + + +```nix title="example" +"vpn.clan.lol" +``` + + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + + +#### port + + + + + + +Port for the wireguard interface + + + +**Type**: `signed integer` + + +**Default**: + +```nix +51820 +``` + + +```nix title="example" +51820 +``` + + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + +## Options for the `peer` role +#### controller + + + + + + +Machinename of the controller to attach to + + + +**Type**: `string` + + + +```nix title="example" +"controller1" +``` + + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + + +#### domain + + + + + + +Domain suffix to use for hostnames in /etc/hosts. +Defaults to the instance name. + + + +**Type**: `null or string` + + +**Default**: + +```nix +instanceName +``` + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + + +#### port + + + + + + +Port for the wireguard interface + + + +**Type**: `signed integer` + + +**Default**: + +```nix +51820 +``` + + +```nix title="example" +51820 +``` + + +πŸ“ƒ Declared in: [clanServices/wireguard/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/wireguard/default.nix) + + diff --git a/tested-trappist/src/content/docs/reference/clanServices/zerotier.md b/tested-trappist/src/content/docs/reference/clanServices/zerotier.md new file mode 100644 index 000000000..aab243f9f --- /dev/null +++ b/tested-trappist/src/content/docs/reference/clanServices/zerotier.md @@ -0,0 +1,131 @@ +--- +title: zerotier +description: Configuration of the secure and efficient Zerotier VPN +--- + +*Configuration of the secure and efficient Zerotier VPN* +## Usage + +``` +inventory.instances = { + zerotier = { + module = { + name = "zerotier"; + input = "clan-core"; + }; + roles.peer.tags.all = { }; + roles.controller.machines.jon = { }; + roles.moon.machines.sara.settings.stableEndpoints = [ "77.52.165.46" ]; + }; +``` + +The input should be named according to your flake input. +All machines will be peers and connected to the zerotier network. +Jon is the controller machine, which will will accept other machines into the network. +Sara is a moon and sets the `stableEndpoint` setting with a publicly reachable IP, the moon is optional. + +## Overview + +This guide explains how to set up and manage a [ZeroTier VPN](https://zerotier.com) for a clan network. Each VPN requires a single controller and can support multiple peers and optional moons for better connectivity. + +## Roles + +### 1. Controller + +The [Controller](https://docs.zerotier.com/controller/) manages network membership and is responsible for admitting new peers. +When a new node is added to the clan, the controller must be updated to ensure it has the latest member list. + +- **Key Points:** + - Must be online to admit new machines to the VPN. + - Existing nodes can continue to communicate even when the controller is offline. + +### 2. Moons + +[Moons](https://docs.zerotier.com/roots) act as relay nodes, +providing direct connectivity to peers via their public IP addresses. +They enable devices that are not publicly reachable to join the VPN by routing through these nodes. + +- **Configuration Notes:** + - Each moon must define its public IP address. + - Ensures connectivity for devices behind NAT or restrictive firewalls. + +### 3. Peers + +Peers are standard nodes in the VPN. +They connect to other peers, moons, and the controller as needed. + +- **Purpose:** + - General role for all machines that are neither controllers nor moons. + - Ideal for most clan members devices. + + +--- + +## Roles +The zerotier module has the following roles: + +- controller +- moon +- peer +## Options for the `controller` role +#### allowedIps + + + + + + +Extra machines by their zerotier ip that the zerotier controller +should accept. These could be external machines. + + + +**Type**: `list of string` + + +**Default**: + +```nix +[ ] +``` + + +```nix title="example" +'' + [ "fd5d:bbe3:cbc5:fe6b:f699:935d:bbe3:cbc5" ] +'' +``` + + +πŸ“ƒ Declared in: [clanServices/zerotier/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/zerotier/default.nix) + + +## Options for the `moon` role +#### stableEndpoints + + + + + + +Make this machine a moon. +Other machines can join this moon by adding this moon in their config. +It will be reachable under the given stable endpoints. + + + +**Type**: `list of string` + + + +```nix title="example" +'' + [ "1.2.3.4" "10.0.0.3/9993" "2001:abcd:abcd::3/9993" ] +'' +``` + + +πŸ“ƒ Declared in: [clanServices/zerotier/default.nix](https://git.clan.lol/clan/clan-core/src/branch/main//clanServices/zerotier/default.nix) + + +This role has no configuration \ No newline at end of file diff --git a/tested-trappist/tsconfig.json b/tested-trappist/tsconfig.json new file mode 100644 index 000000000..8bf91d3bb --- /dev/null +++ b/tested-trappist/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +}