From 66562f532ff884a1ef5cb74bcad1eaca2cd0aeaa Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Mon, 19 May 2025 17:32:01 -0400 Subject: [PATCH 01/79] update private DNS --- .../private-net/cloudflared/private-dns.mdx | 33 +++++++++++-------- .../gateway/resolver-policies-intro.mdx | 6 ++++ .../learning-paths/zero-trust/private-dns.mdx | 4 +-- 3 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 src/content/partials/cloudflare-one/gateway/resolver-policies-intro.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx index 7ba2feb7061b386..75b2da0bcefebf7 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx @@ -1,31 +1,38 @@ --- pcx_content_type: how-to -title: Private DNS +title: Resolve private DNS sidebar: - order: 1 + order: 4 --- -By default, the WARP client sends DNS requests to [1.1.1.1](/1.1.1.1/), Cloudflare's public DNS resolver, for resolution. With Cloudflare Tunnel, you can connect an internal DNS resolver to Cloudflare and use it to resolve non-publicly routed domains. +import { Render } from "~/components" + +By default, all DNS requests on the user device are resolved by Cloudflare's [public DNS resolver](/1.1.1.1/) except for common top level domains used for local resolution (such as `localhost`). You can connect an internal DNS resolver to Cloudflare and use it to resolve non-publicly routed domains. ## Configure private DNS +To resolve private DNS queries: + 1. [Connect your private network](/cloudflare-one/connections/connect-networks/get-started/) with Cloudflare Tunnel. 2. Under **Networks** > **Routes**, verify that the IP address of your internal DNS resolver is included in the tunnel. -3. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#turn-on-the-gateway-proxy) for TCP and UDP. + :::note + + Ensure that **Split Tunnels** are configured to [include traffic to private IPs and hostnames](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#3-route-private-network-ips-through-warp). -4. Next, [create a Local Domain Fallback entry](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) that points to the internal DNS resolver. For example, you can instruct the WARP client to resolve all requests for `myorg.privatecorp` through an internal resolver at `10.0.0.25` rather than attempting to resolve this publicly. + ::: -:::note +3. Route specific DNS queries to your internal DNS resolver using one of the following options: -Ensure that **Split Tunnels** are configured to [include traffic to private IPs and hostnames](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#3-route-private-network-ips-through-warp). + - [Create a Local Domain Fallback entry](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) that points to the internal DNS resolver. For example, you can instruct the WARP client to resolve all requests for `myorg.privatecorp` through an internal resolver at `10.0.0.25` rather than attempting to resolve this publicly. + - Alternatively, [create a resolver policy](/cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that points to the internal DNS resolver. -::: +4. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#turn-on-the-gateway-proxy) for TCP and UDP. 5. Finally, ensure that your tunnel uses QUIC as the default [transport protocol](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#protocol). This will enable `cloudflared` to proxy UDP-based traffic which is required in most cases to resolve DNS queries. -The WARP client will now resolve requests through the internal DNS server you set up in your private network. +The WARP client will now send DNS requests to your internal DNS resolver for resolution. To learn more, refer to [How the WARP client handles DNS requests](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/#how-the-warp-client-handles-dns-requests). ## Test the setup @@ -45,7 +52,7 @@ Both `dig` commands will fail if the WARP client is disabled on your end user's ## Troubleshooting -Use the following troubleshooting strategies if you are running into issues while configuring your private network with Cloudflare Tunnel. +Use the following troubleshooting strategies if you are running into issues while configuring private DNS with Cloudflare Tunnel. - Ensure that `cloudflared` is connected to Cloudflare by visiting **Networks** > **Tunnels** in Zero Trust. @@ -55,10 +62,10 @@ Use the following troubleshooting strategies if you are running into issues whil - Ensure that end-user devices are enrolled into WARP by visiting [https://help.teams.cloudflare.com](https://help.teams.cloudflare.com). -- Double-check the precedence of your application policies in the Gateway Network policies tab. Ensure that a more global Block or Allow policy will not supersede the application policies. +- Double-check the [order of precedence](/cloudflare-one/policies/gateway/order-of-enforcement/#order-of-precedence) for your [Gateway network policies](/cloudflare-one/policies/gateway/network-policies/). Ensure that a more global Block or Allow policy will not supersede application-specific policies. -- Check the Gateway Audit Logs Network tab to see whether your UDP DNS resolutions are being allowed or blocked. +- Check your [Gateway network logs](/cloudflare-one/insights/logs/gateway-logs/#network-logs) to see whether your UDP DNS resolutions are being allowed or blocked. -- Ensure that your Private DNS resolver is available over a routable private IP address. You can check that by trying the `dig` commands on your machine running `cloudflared`. +- Ensure that your internal DNS resolver is available over a routable private IP address. You can check that by trying the `dig` commands on your machine running `cloudflared`. - Check your set up by using `dig ... +tcp` to force the DNS resolution to use TCP instead of UDP. diff --git a/src/content/partials/cloudflare-one/gateway/resolver-policies-intro.mdx b/src/content/partials/cloudflare-one/gateway/resolver-policies-intro.mdx new file mode 100644 index 000000000000000..18e26f0da22632d --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/resolver-policies-intro.mdx @@ -0,0 +1,6 @@ +--- +{} + +--- + +[Resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) provide similar functionality to Local Domain Fallback but occur in Cloudflare Gateway rather than on the local device. This option is recommended if you want more granular control over private DNS resolution. For example, you can ensure that all users in a specific geography use the private DNS server closest to them, ensure that specific conditions are met before resolving private DNS traffic, and apply [Gateway DNS policies](/cloudflare-one/policies/gateway/dns-policies/) to private DNS traffic. diff --git a/src/content/partials/learning-paths/zero-trust/private-dns.mdx b/src/content/partials/learning-paths/zero-trust/private-dns.mdx index ac2d5705bf43f05..dae616e92395775 100644 --- a/src/content/partials/learning-paths/zero-trust/private-dns.mdx +++ b/src/content/partials/learning-paths/zero-trust/private-dns.mdx @@ -12,7 +12,7 @@ By default, all DNS requests on the user device are resolved by Cloudflare's [pu ## Local Domain Fallback -Local Domain Fallback tells the WARP client to send specific DNS requests to your private DNS resolver instead of to Cloudflare’s public DNS resolver. This method was the primary delivery mechanism for private DNS for a long time, and is the simplest option, but it has two shortcomings: you cannot deterministically route private DNS queries to different resolvers based on specific attributes, and you cannot apply Gateway DNS policies to this traffic because Cloudflare is not resolving it. +Local Domain Fallback tells the WARP client to send specific DNS requests to your private DNS resolver instead of to Cloudflare's public DNS resolver. This method was the primary delivery mechanism for private DNS for a long time, and is the simplest option, but it has two shortcomings: you cannot deterministically route private DNS queries to different resolvers based on specific attributes, and you cannot apply Gateway DNS policies to this traffic because Cloudflare is not resolving it. To learn more about how Local Domain Fallback works, refer to [How the WARP client handles DNS requests](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/#how-the-warp-client-handles-dns-requests). @@ -27,7 +27,7 @@ To learn more about how Local Domain Fallback works, refer to [How the WARP clie Only available on Enterprise plans. ::: -[Custom resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) provide similar functionality to Local Domain Fallback but occur in Cloudflare Gateway rather than on the local device. This option is recommended if you want more granular control over private DNS resolution. For example, you can ensure that all users in a specific geography use the private DNS server closest to them, ensure that specific conditions are met before resolving private DNS traffic, and apply [Gateway DNS policies](/cloudflare-one/policies/gateway/dns-policies/) to private DNS traffic. + ### Create a resolver policy From 64d7cef8418130cdce17e04559faa0acf9e82b6f Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Mon, 19 May 2025 18:09:53 -0400 Subject: [PATCH 02/79] Private networks overview and IA --- .../private-net/cloudflared/connect-cidr.mdx | 62 +++++++++++++++++ .../cloudflared/connect-hostname.mdx | 9 +++ .../private-net/cloudflared/index.mdx | 69 +++---------------- .../cloudflared/load-balancing.mdx | 2 +- .../cloudflared/tunnel-virtual-networks.mdx | 2 +- 5 files changed, 82 insertions(+), 62 deletions(-) create mode 100644 src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx create mode 100644 src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx new file mode 100644 index 000000000000000..e21e4c439bfb5eb --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -0,0 +1,62 @@ +--- +pcx_content_type: how-to +title: Connect an IP/CIDR +sidebar: + order: 3 +--- + +import { Render } from "~/components"; + +This guide covers how to enable secure remote access to private IP addresses using `cloudflared`. You can connect an entire private network, a subnet, or an application defined by a static IP. + +## 1. Connect the server to Cloudflare + +To connect your infrastructure with Cloudflare Tunnel: + + + +2. In the **Private Networks** tab for the tunnel, enter the IP/CIDR range that you wish to route through the tunnel (for example `10.0.0.0/8`). + +## 2. Set up the client + + + +## 3. Route private network IPs through WARP + + + +## 4. (Recommended) Filter network traffic with Gateway + +By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway inspect your network traffic and either block or allow access based on user identity and device posture. + +### Enable the Gateway proxy + + + +### Zero Trust policies + +Cloudflare Zero Trust allows you to configure security policies using either Access or Gateway. If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway [network and DNS policies](/learning-paths/replace-vpn/build-policies/) for IP ranges and domains. + +## 5. Connect as a user + +End users can now reach HTTP or TCP-based services on your network by visiting any IP address in the range you have specified. + +### Troubleshooting + +#### Device configuration + +To check that their device is properly configured, the user can visit `https://help.teams.cloudflare.com/` to ensure that: + +- The page returns **Your network is fully protected**. +- In **HTTP filtering**, both **WARP** and **Gateway Proxy** are enabled. +- The **Team name** matches the Zero Trust organization from which you created the tunnel. + +#### Router configuration + +Check the local IP address of the device and ensure that it does not fall within the IP/CIDR range of your private network. For example, some home routers will make DHCP assignments in the `10.0.0.0/24` range, which overlaps with the `10.0.0.0/8` range used by most corporate private networks. When a user's home network shares the same IP addresses as the routes in your tunnel, their device will be unable to connect to your application. + +To resolve the IP conflict, you can either: + +- Reconfigure the user's router to use a non-overlapping IP range. Compatible routers typically use `192.168.1.0/24`, `192.168.0.0/24` or `172.16.0.0/24`. +- Tighten the IP range in your Split Tunnel configuration to exclude the `10.0.0.0/24` range. This will only work if your private network does not have any hosts within `10.0.0.0/24`. +- Change the IP/CIDR of your private network so that it does not overlap with a range commonly used by home networks. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx new file mode 100644 index 000000000000000..4821316f7e36dc8 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: how-to +title: Connect a hostname +sidebar: + order: 2 +--- + +import { Render } from "~/components"; + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx index 090c5ce74af8888..660d5e6abf40a7b 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx @@ -1,68 +1,17 @@ --- -pcx_content_type: how-to -title: Connect private networks +pcx_content_type: concept +title: Connect with cloudflared +hidden: false sidebar: order: 1 --- -import { Render } from "~/components"; +`cloudflared` is a daemon service that can run on nearly any host machine in your private network and proxies local traffic once validated from the Cloudflare network. The Cloudflare Tunnel created by `cloudflared` is outbound-only, meaning that it will only proxy requests initiated from a user to your private network. Requests made by a service or application running behind the tunnel will use the server's default routing table. -A private network has two primary components: the server and the client. The server's infrastructure (whether that is a single application, multiple applications, or a network segment) is connected to Cloudflare's global network by Cloudflare Tunnel. This is done by running the `cloudflared` daemon on the server. +On the client side, end users connect to Cloudflare's global network using the Cloudflare WARP client. The WARP client can be rolled out to your entire organization in just a few minutes using your in-house MDM tooling. When users connect to an IP address or hostname made available through Cloudflare Tunnel, WARP sends their connection through Cloudflare's network and down the corresponding tunnel to the internal service. Traffic to services behind the tunnel will carry the local source IP address of the host machine running the `cloudflared` daemon. -On the client side, end users connect to Cloudflare's global network using the Cloudflare WARP client. The WARP client can be rolled out to your entire organization in just a few minutes using your in-house MDM tooling. When users connect to an IP made available through Cloudflare Tunnel, WARP sends their connection through Cloudflare's network to the corresponding tunnel. +![Diagram displaying connections between a device, Cloudflare, and a private network.](~/assets/images/cloudflare-one/connections/private-ips-diagram.png) -![Diagram displaying connections between a device, Cloudflare, and a public cloud.](~/assets/images/cloudflare-one/connections/private-ips-diagram.png) - -To enable remote access to your private network, follow the guide below. - -## 1. Connect the server to Cloudflare - -To connect your infrastructure with Cloudflare Tunnel: - - - -2. In the **Private Networks** tab for the tunnel, enter the IP/CIDR range that you wish to route through the tunnel (for example `10.0.0.0/8`). - -## 2. Set up the client - - - -## 3. Route private network IPs through WARP - - - -## 4. (Recommended) Filter network traffic with Gateway - -By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway inspect your network traffic and either block or allow access based on user identity and device posture. - -### Enable the Gateway proxy - - - -### Zero Trust policies - -Cloudflare Zero Trust allows you to configure security policies using either Access or Gateway. If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway [network and DNS policies](/learning-paths/replace-vpn/build-policies/) for IP ranges and domains. - -## 5. Connect as a user - -End users can now reach HTTP or TCP-based services on your network by visiting any IP address in the range you have specified. - -### Troubleshooting - -#### Device configuration - -To check that their device is properly configured, the user can visit `https://help.teams.cloudflare.com/` to ensure that: - -- The page returns **Your network is fully protected**. -- In **HTTP filtering**, both **WARP** and **Gateway Proxy** are enabled. -- The **Team name** matches the Zero Trust organization from which you created the tunnel. - -#### Router configuration - -Check the local IP address of the device and ensure that it does not fall within the IP/CIDR range of your private network. For example, some home routers will make DHCP assignments in the `10.0.0.0/24` range, which overlaps with the `10.0.0.0/8` range used by most corporate private networks. When a user's home network shares the same IP addresses as the routes in your tunnel, their device will be unable to connect to your application. - -To resolve the IP conflict, you can either: - -- Reconfigure the user's router to use a non-overlapping IP range. Compatible routers typically use `192.168.1.0/24`, `192.168.0.0/24` or `172.16.0.0/24`. -- Tighten the IP range in your Split Tunnel configuration to exclude the `10.0.0.0/24` range. This will only work if your private network does not have any hosts within `10.0.0.0/24`. -- Change the IP/CIDR of your private network so that it does not overlap with a range commonly used by home networks. +To enable remote access to your private network, refer to the following guides: +- [**Connect a hostname**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname/): Route network traffic to an internal application using its private or public hostname. +- [**Connect an IP/CIDR**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/): Route traffic to an internal IP address or CIDR range. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/load-balancing.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/load-balancing.mdx index 936b304dd35c4eb..d78a6ec8c81771f 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/load-balancing.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/load-balancing.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: Load balancing sidebar: - order: 3 + order: 6 --- diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx index d0fd5414cb44bc9..edd22e0d3567a19 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx @@ -2,7 +2,7 @@ pcx_content_type: how-to title: Virtual networks sidebar: - order: 2 + order: 5 --- import { Details, Render, Tabs, TabItem } from "~/components"; From 8c3e2cff19c8141a091f1a72a7d9e0100e2f09fc Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 20 May 2025 21:53:50 -0400 Subject: [PATCH 03/79] diagrams and concepts --- .../connections/private-hostname-route-1.png | Bin 0 -> 42512 bytes .../connections/private-hostname-route-2.png | Bin 0 -> 35973 bytes .../private-net/cloudflared/connect-cidr.mdx | 2 +- .../cloudflared/connect-hostname.mdx | 9 ---- .../cloudflared/connect-private-hostname.mdx | 49 ++++++++++++++++++ .../private-net/cloudflared/index.mdx | 2 +- .../private-net/cloudflared/private-dns.mdx | 2 +- .../egress-policies/egress-cloudflared.mdx | 31 +++++++++++ 8 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 src/assets/images/cloudflare-one/connections/private-hostname-route-1.png create mode 100644 src/assets/images/cloudflare-one/connections/private-hostname-route-2.png delete mode 100644 src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx create mode 100644 src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx create mode 100644 src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx diff --git a/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png b/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png new file mode 100644 index 0000000000000000000000000000000000000000..27656cd29c49d5d39039579f139abf06f571a75a GIT binary patch literal 42512 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 literal 0 HcmV?d00001 diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index e21e4c439bfb5eb..990ae34fa5b6d74 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -7,7 +7,7 @@ sidebar: import { Render } from "~/components"; -This guide covers how to enable secure remote access to private IP addresses using `cloudflared`. You can connect an entire private network, a subnet, or an application defined by a static IP. +This guide covers how to enable secure remote access to private IP addresses using `cloudflared` and WARP. You can connect an entire private network, a subnet, or an application defined by a static IP. ## 1. Connect the server to Cloudflare diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx deleted file mode 100644 index 4821316f7e36dc8..000000000000000 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: how-to -title: Connect a hostname -sidebar: - order: 2 ---- - -import { Render } from "~/components"; - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx new file mode 100644 index 000000000000000..bec9205c9af98e5 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -0,0 +1,49 @@ +--- +pcx_content_type: how-to +title: Connect a private hostname +sidebar: + order: 2 +--- + +import { Render } from "~/components"; + +`cloudflared` can route to non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. + +:::note[Availability] +Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr) and [configure Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/) to resolve its private hostname. +::: + +## Limitations + +### Supported user traffic + +### Supported network on-ramps + +## How private hostname routing works + +Private hostname routing with Cloudflare Tunnel consists of three main components: + +- The WARP client installs on the user device and forwards network and DNS traffic from the device to Cloudflare Gateway. +- Gateway resolver policies instruct Gateway to resolve the private hostname using your internal DNS resolver instead of the default public resolver. +- `cloudflared` installs on a host machine in your private network and proxies traffic from Cloudflare to your internal DNS resolver and internal applications. + +Figures 1 and 2 illustrate what happens when a user connects to a private hostname (`wiki.internal.local`) from a WARP device. + +![Figure 1: DNS resolution for a private hostname](~/assets/images/cloudflare-one/connections/private-hostname-route-1.png "Figure 1: DNS resolution for private hostname") + +1. The WARP client sends the DNS query to the Gateway resolver for resolution. +2. Based on the configured resolver policies, Gateway determines that `wiki.internal.local` should be resolved by a custom DNS resolver. Therefore, Gateway sends the DNS request down Cloudflare Tunnel to the private network where the custom DNS resolver is located. +3. `cloudflared` does a DNS lookup to figure out what the origin IP is for `wiki.internal.local`. +4. The Gateway resolver now knows that the origin IP is `10.0.0.5`. +5. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the CGNAT range `100.80.0.0/16` (for example, `100.80.0.1`). This CGNAT IP is called the initial resolved IP. +6. Gateway stores the mapping between the private hostname, CGNAT initial resolved IP, and the actual IP. +7. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response for `wiki.internal.local`. + +As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP through Gateway. Because the destination IP falls within the designated CGNAT range, Gateway knows how it maps to the actual origin IP. Traffic that passes your network policies will now route through Cloudflare Tunnel to the private application. + +![Figure 2: Network traffic flow for a private hostname route](~/assets/images/cloudflare-one/connections/private-hostname-route-2.png "Figure 1: Network traffic flow for a private hostname route") + +To learn more about the initial resolved IP mechanism, refer to the [Cloudflare blog](). + +## Configure a private hostname route + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx index 660d5e6abf40a7b..bc2f77c7634e3ac 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx @@ -13,5 +13,5 @@ On the client side, end users connect to Cloudflare's global network using the C ![Diagram displaying connections between a device, Cloudflare, and a private network.](~/assets/images/cloudflare-one/connections/private-ips-diagram.png) To enable remote access to your private network, refer to the following guides: -- [**Connect a hostname**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname/): Route network traffic to an internal application using its private or public hostname. +- [**Connect a private hostname**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname/): Route network traffic to an internal application using its hostname. - [**Connect an IP/CIDR**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/): Route traffic to an internal IP address or CIDR range. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx index 75b2da0bcefebf7..ad777d3b0ea49dd 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -title: Resolve private DNS +title: Private DNS sidebar: order: 4 --- diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx new file mode 100644 index 000000000000000..18bdd3abd2a4a8e --- /dev/null +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -0,0 +1,31 @@ +--- +pcx_content_type: how-to +title: Egress through Cloudflare Tunnel +sidebar: + order: 2 +--- + +import { Details } from "~/components"; + +Cloudflare Tunnel can be used for source IP anchoring when you want to use existing egress IPs instead of purchasing [Cloudflare dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Some third-party websites may have an Access Control List (ACL) that only allow connections from certain source IPs. If you already a non-Cloudflare IP on their allowlist (such an egress IP provided by an ISP or a cloud provider like AWS), you can configure `cloudflared` to anchor user traffic to the same IPs that you use today. + +For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS envirionment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will route their traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. + +```mermaid + flowchart LR + subgraph aws["AWS VPC"] + cloudflared["cloudflared"]--> rules["Egress rules"] + end + subgraph cloudflare[Cloudflare] + resolver["Gateway + resolver"] + end + warp["WARP + clients"]--"app.bank.com"-->resolver + resolver-->cloudflared + rules--AWS egress IP -->I{Internet} +``` + +## Prerequisites + +## Configure a public hostname route From 41961ee9e24bfbee246b213115d326988bee846e Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 21 May 2025 16:58:34 -0400 Subject: [PATCH 04/79] outline steps --- .../cloudflared/connect-private-hostname.mdx | 92 ++++++++++++++++--- .../egress-policies/egress-cloudflared.mdx | 14 ++- 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index bec9205c9af98e5..f8a7b4347da5cab 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -5,7 +5,7 @@ sidebar: order: 2 --- -import { Render } from "~/components"; +import { Render, Details } from "~/components"; `cloudflared` can route to non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. @@ -13,12 +13,6 @@ import { Render } from "~/components"; Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr) and [configure Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/) to resolve its private hostname. ::: -## Limitations - -### Supported user traffic - -### Supported network on-ramps - ## How private hostname routing works Private hostname routing with Cloudflare Tunnel consists of three main components: @@ -27,7 +21,7 @@ Private hostname routing with Cloudflare Tunnel consists of three main component - Gateway resolver policies instruct Gateway to resolve the private hostname using your internal DNS resolver instead of the default public resolver. - `cloudflared` installs on a host machine in your private network and proxies traffic from Cloudflare to your internal DNS resolver and internal applications. -Figures 1 and 2 illustrate what happens when a user connects to a private hostname (`wiki.internal.local`) from a WARP device. +Figures 1 and 2 illustrate the flow of DNS and network traffic when a user connects to a private hostname (`wiki.internal.local`): ![Figure 1: DNS resolution for a private hostname](~/assets/images/cloudflare-one/connections/private-hostname-route-1.png "Figure 1: DNS resolution for private hostname") @@ -36,14 +30,88 @@ Figures 1 and 2 illustrate what happens when a user connects to a private hostna 3. `cloudflared` does a DNS lookup to figure out what the origin IP is for `wiki.internal.local`. 4. The Gateway resolver now knows that the origin IP is `10.0.0.5`. 5. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the CGNAT range `100.80.0.0/16` (for example, `100.80.0.1`). This CGNAT IP is called the initial resolved IP. -6. Gateway stores the mapping between the private hostname, CGNAT initial resolved IP, and the actual IP. +6. Gateway's network engine stores the mapping between the private hostname, initial resolved IP, and the actual IP. 7. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response for `wiki.internal.local`. -As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP through Gateway. Because the destination IP falls within the designated CGNAT range, Gateway knows how it maps to the actual origin IP. Traffic that passes your network policies will now route through Cloudflare Tunnel to the private application. +As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP. The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. Because the packet's destination IP falls within the designated CGNAT range, Gateway knows that it corresponds to a hostname route and can apply hostname-based policies. Traffic that passes your Gateway policies will route through Cloudflare Tunnel to the application's actual origin IP. ![Figure 2: Network traffic flow for a private hostname route](~/assets/images/cloudflare-one/connections/private-hostname-route-2.png "Figure 1: Network traffic flow for a private hostname route") -To learn more about the initial resolved IP mechanism, refer to the [Cloudflare blog](). +To learn more about hostname routing, refer to the [Cloudflare blog](). + +## Connect to a private hostname + +This section covers how to enable remote access to a private hostname application using `cloudflared` and WARP. + +### 1. Connect the server to Cloudflare + +### 2. Set up the client + +
+ +| [WARP modes](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | +| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| Gateway with WARP | Enterprise | + +| System | Availability | Minimum WARP version | +| -------- | ------------ | -------------------- | +| Windows | βœ… | 2025.4.929.0 | +| macOS | βœ… | 2025.4.929.0 | +| Linux | βœ… | 2025.4.929.0 | +| iOS | ❌ | | +| Android | ❌ | | +| ChromeOS | ❌ | | + +
+ + +### 3. Route private network IPs through WARP + +- Initial resolved IP CGNAT range: `100.80.0.0/16` +- Private network CIDR where the application is located, e.g. `10.0.0.0/8`. (Still need to know the IP range of the network. Do not need to know the specific IP of the application) +- Internal DNS resolver IP + +### 4. Create a resolver policy + +### 5. (Recommended) Filter network traffic with Gateway + +#### Enable Gateway proxy for TCP and UDP +#### Zero Trust policies + +If you're running a private app on port 443: + +Option 1: create an Access self-hosted private app https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/ + +Option 2: create a Gateway network policy using the SNI selector https://developers.cloudflare.com/cloudflare-one/policies/gateway/network-policies/#sni + +Self-hosted private apps and Gateway network policies are not currently supported for services on non-443 ports. You can only create a Gateway DNS policy. + + +### 6. Connect as a user + + + +## Supported on-ramps/off-ramps + +### Device connectivity + +End users can connect to private hostnames from the following device on-ramps: + +| On-ramp method | Compatibility | +| ------------------------------------------------------------------------------------------ | ------------- | +| [WARP client](/cloudflare-one/connections/connect-devices/warp/) | βœ… | +| [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | +| [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | +| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | + +### Private network connectivity -## Configure a private hostname route +To route to private applications using hostnames instead of IPs, connect your infrastructure to Cloudflare using a supported traffic off-ramp: +| Connector | Compatibility | +| ------------------------------------------------------------------------------------------ | ------------- | +| [cloudflared](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) | βœ… | +| [WARP-to-WARP](/cloudflare-one/connections/connect-networks/private-net/warp-to-warp/) | ❌ | +| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 18bdd3abd2a4a8e..678009973c41a4b 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -28,4 +28,16 @@ For example, assume that your organization's banking service, `app.bank.com`, ex ## Prerequisites -## Configure a public hostname route +## 1. Connect private network to Cloudflare + +## 2. Add a public hostname route + +## 3. Route private network IPs through WARP + +## 4. (Optional) Filter network traffic with Gateway + +## 5. Create an egress policy + +Create an egress policy that points traffic to Cloudflare Tunnel. + +## 6. Test the connection \ No newline at end of file From 82637c71d8c324a08230c91fb9c601e47f62d93c Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 21 May 2025 17:20:29 -0400 Subject: [PATCH 05/79] fix relative links --- .../private-net/cloudflared/connect-private-hostname.mdx | 2 +- .../connect-networks/private-net/cloudflared/index.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index f8a7b4347da5cab..897c35eaac9ce06 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -10,7 +10,7 @@ import { Render, Details } from "~/components"; `cloudflared` can route to non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. :::note[Availability] -Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr) and [configure Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/) to resolve its private hostname. +Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) and [configure Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/) to resolve its private hostname. ::: ## How private hostname routing works diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx index bc2f77c7634e3ac..d1ff3a987cda3c5 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx @@ -13,5 +13,5 @@ On the client side, end users connect to Cloudflare's global network using the C ![Diagram displaying connections between a device, Cloudflare, and a private network.](~/assets/images/cloudflare-one/connections/private-ips-diagram.png) To enable remote access to your private network, refer to the following guides: -- [**Connect a private hostname**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-hostname/): Route network traffic to an internal application using its hostname. +- [**Connect a private hostname**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname/): Route network traffic to an internal application using its hostname. - [**Connect an IP/CIDR**](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/): Route traffic to an internal IP address or CIDR range. \ No newline at end of file From 5ae3372501bf7e957af0a326ad4f42712dfa6237 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 13:42:08 -0400 Subject: [PATCH 06/79] update get started pages --- .../get-started/create-remote-tunnel-api.mdx | 10 +++++----- .../get-started/create-remote-tunnel.mdx | 19 ++++++++++--------- .../tunnel/add-public-hostname.mdx | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx index 7f07697ce9e311c..1a5ebc87ead1f88 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx @@ -63,16 +63,16 @@ curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel' \ Copy the `id` and `token` values shown in the output. You will need these values to configure and run the tunnel. -The next steps depend on whether you want to [connect an application](#3a-connect-an-application) or [connect a network](#3b-connect-a-network). +The next steps depend on whether you want to [publish an application to the Internet](#3a-publish-an-application) or [connect a private network](#3b-connect-a-network). -## 3a. Connect an application +## 3a. Publish an application -Before you connect an application through your tunnel, you must: +Before you publish an application through your tunnel, you must: - [Add a website to Cloudflare](/fundamentals/setup/manage-domains/add-site/). - [Change your domain nameservers to Cloudflare](/dns/zone-setups/full-setup/setup/). -Follow these steps to connect an application through your tunnel. If you are looking to connect a network, skip to the [Connect a network section](#3b-connect-a-network). +Follow these steps to publish an application to the Internet. If you are looking to connect a private resource, skip to the [Connect a network](#3b-connect-a-network) section. 1. Make a [`PUT` request](/api/resources/zero_trust/subresources/tunnels/subresources/cloudflared/subresources/configurations/methods/update/) to route your local service URL to a public hostname. For example, @@ -136,7 +136,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/routes \ }' ``` -To configure Zero Trust policies and connect as a user, refer to [Connect private networks](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). +`cloudflared` can now route traffic to these destination IPs. To configure Zero Trust policies and connect as a user, refer to [Connect private networks](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). ## 4. Install and run the tunnel diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx index 8c551ce43d0d918..963d519dfb8cb76 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx @@ -13,30 +13,31 @@ Follow this step-by-step guide to create your first [remotely-managed tunnel](/c -The next steps depend on whether you want to [connect an application](#2a-connect-an-application) or [connect a network](#2b-connect-a-network). +The next steps depend on whether you want to [publish an application to the Internet](#2a-publish-an-application) or [connect a private network](#2b-connect-a-network). -## 2a. Connect an application +## 2a. Publish an application -Before you connect an application through your tunnel, you must: +Before you publish an application through your tunnel, you must: - [Add a website to Cloudflare](/fundamentals/setup/manage-domains/add-site/). - [Change your domain nameservers to Cloudflare](/dns/zone-setups/full-setup/setup/). -Follow these steps to connect an application through your tunnel. If you are looking to connect a network, skip to the [Connect a network section](#2b-connect-a-network). +Follow these steps to publish an application to the Internet. If you are looking to connect a private resource, skip to the [Connect a network](#2b-connect-a-network) section. -The application is now publicly available on the Internet. To allow or block specific users, [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). +Anyone on the Internet can now access the application at the specified hostname. To allow or block specific users, [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). ## 2b. Connect a network -Follow these steps to connect a private network through your tunnel. +To connect a private network through your tunnel: -1. In the **Private Networks** tab, add the IP or CIDR of your service. +1. Go to the **Private networks** tab. +2. In **CIDR**, enter the private IP address or CIDR range of your service (for example, `10.0.0.1` or `10.0.0.0/8`). -2. Select **Save tunnel**. +`cloudflared` can now route traffic to these destination IPs. To configure Zero Trust policies and connect as a user, refer to [Connect an IP/CIDR](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). -To configure Zero Trust policies and connect as a user, refer to [Connect private networks](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). +If you would like to route to a private application using its hostname instead of its IP, refer to [Connect a private hostname](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname/). ## 3. View your tunnel diff --git a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx index b609f6b251b3eda..f32ef243e38c918 100644 --- a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx @@ -3,7 +3,7 @@ --- -1. In the **Public Hostnames** tab, select **Add a public hostname**. +1. Go to the **Published applications** tab. 2. Enter a subdomain and select a **Domain** from the dropdown menu. Specify any subdomain or path information. :::note @@ -14,4 +14,4 @@ 4. Under **Additional application settings**, specify any [parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/) you would like to add to your tunnel configuration. -5. Select **Save hostname**. \ No newline at end of file +5. Select **Complete setup**. \ No newline at end of file From 6269d44ef3b9f4d1ba1cb7ecb675e966a68e3a5e Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 15:21:47 -0400 Subject: [PATCH 07/79] public hostnames --> published applications --- .../configure-apps/self-hosted-public-app.mdx | 2 +- .../non-http/short-lived-certificates-legacy.mdx | 2 +- .../configure-tunnels/cloudflared-parameters/index.mdx | 6 +++--- .../cloudflared-parameters/origin-parameters.mdx | 2 +- .../connect-networks/deployment-guides/ansible.mdx | 2 +- .../connect-networks/deployment-guides/terraform.mdx | 4 ++-- .../connections/connect-networks/private-net/index.mdx | 2 +- .../private-net/warp-connector/index.mdx | 2 +- .../connect-networks/routing-to-tunnel/index.mdx | 2 +- .../use-cases/rdp/rdp-cloudflared-authentication.mdx | 4 ++-- .../connections/connect-networks/use-cases/smb.mdx | 10 ++++++---- .../docs/cloudflare-one/tutorials/s3-buckets.mdx | 6 +++--- src/content/docs/data-localization/compatibility.mdx | 2 +- .../configuration/connect-to-private-database.mdx | 4 ++-- .../clientless-access/alternative-onramps/index.mdx | 2 +- .../connect-private-applications/create-tunnel.mdx | 4 ++-- .../terraform/publish-apps-with-terraform.mdx | 6 +++--- .../additional-options/cloudflare-tunnel.mdx | 2 +- .../design-guides/zero-trust-for-startups.mdx | 2 +- .../cloudflare-one/ssh/tunnel-public-hostname.mdx | 4 ++-- .../cloudflare-one/tunnel/cloud-public-hostname.mdx | 6 +++--- .../tunnel/troubleshoot-private-networks.mdx | 2 +- 22 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx index ea8ebd5dde64737..3febe3a0eb7874d 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx @@ -24,7 +24,7 @@ You can securely publish internal tools and applications by adding Cloudflare Ac [Set up a Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) to publish your internal application. Only users who match your Access policies will be granted access. :::note -We recommend [creating an Access application](#1-add-your-application-to-access) before setting up the tunnel route. If you do not have an Access application in place, public hostname routes in Tunnel are available to anyone on the Internet. +We recommend [creating an Access application](#1-add-your-application-to-access) before setting up the tunnel route. If you do not have an Access application in place, the published application will be available to anyone on the Internet. ::: If your application is already publicly routable, a Tunnel is not strictly required. However, you will then need to protect your origin IP using [other methods](/fundamentals/security/protect-your-origin-server/). diff --git a/src/content/docs/cloudflare-one/applications/non-http/short-lived-certificates-legacy.mdx b/src/content/docs/cloudflare-one/applications/non-http/short-lived-certificates-legacy.mdx index 4ecb63ee444fe8a..86ed223c0826d69 100644 --- a/src/content/docs/cloudflare-one/applications/non-http/short-lived-certificates-legacy.mdx +++ b/src/content/docs/cloudflare-one/applications/non-http/short-lived-certificates-legacy.mdx @@ -23,7 +23,7 @@ Cloudflare Access short-lived certificates can work with any modern SSH server, To secure your server behind Cloudflare Access: -1. [Connect the server to Cloudflare](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) as a public hostname route. +1. [Connect the server to Cloudflare](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) as a published application. 2. Create a [self-hosted Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) for the server. :::note diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx index 026c1fc2c39a35f..b49c34756684033 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx @@ -140,11 +140,11 @@ On Windows, Cloudflare Tunnel installs itself as a system service using the Regi ## Update origin configuration -To configure how `cloudflared` sends requests to your [public hostname](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) services: +To configure how `cloudflared` sends requests to your [published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/): 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. 2. Choose a tunnel and select **Configure**. -3. Select the **Public Hostname** tab. -4. Choose a route and select **Edit**. +3. Select the **Published applications** tab. +4. Choose an application and select **Edit**. 5. Under **Additional application settings**, modify one or more [origin configuration parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). 6. Select **Save hostname**. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx index 554fa22b40f6d32..f8f6b6071dd4b99 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx @@ -171,7 +171,7 @@ The timeout after which a TCP keepalive packet is sent on a connection between C | ------- | ------------------- | | `""` | Protect with Access | -Requires `cloudflared` to validate the [Cloudflare Access JWT](/cloudflare-one/identity/authorization-cookie/validating-json/) prior to proxying traffic to your origin. You can enforce this check on public hostname routes that are protected by an Access application. For all L7 requests to these hostnames, Access will send the JWT to `cloudflared` as a `Cf-Access-Jwt-Assertion` request header. +Requires `cloudflared` to validate the [Cloudflare Access JWT](/cloudflare-one/identity/authorization-cookie/validating-json/) prior to proxying traffic to your origin. You can enforce this check on public hostname services that are protected by an Access application. For all L7 requests to these hostnames, Access will send the JWT to `cloudflared` as a `Cf-Access-Jwt-Assertion` request header. To enable this security control in a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#origin-configuration), [get the AUD tag](/cloudflare-one/identity/authorization-cookie/validating-json/#get-your-aud-tag) for your Access application and add the following rule to `originRequest`: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx index 4c8e50e32b3981c..629c3a5499a5d24 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx @@ -113,7 +113,7 @@ The following configuration will modify settings in your Cloudflare account. proxied = true } - # Configures tunnel with a public hostname route for clientless access. + # Configures tunnel with a published application for clientless access. resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" { tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id account_id = var.cloudflare_account_id diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx index 3fafbd41f78d1da..68272bc20e5327a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx @@ -156,7 +156,7 @@ The following configuration will modify settings in your Cloudflare account. proxied = true } - # Configures tunnel with a public hostname route for clientless access. + # Configures tunnel with a published application for clientless access. resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" { tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id account_id = var.cloudflare_account_id @@ -240,7 +240,7 @@ The following configuration will modify settings in your Cloudflare account. proxied = true } - # Configures tunnel with a public hostname route for clientless access. + # Configures tunnel with a published application for clientless access. resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" { tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id account_id = var.cloudflare_account_id diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx index 554f09cc4b6775e..991bdfe977ced5a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx @@ -5,7 +5,7 @@ sidebar: order: 7 --- -With Cloudflare Zero Trust, you can connect private networks and the services running in those networks to Cloudflare's global network. This involves installing a [connector](#connectors) on the private network, and then [setting up routes](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#2b-connect-a-network) which define the IP addresses available in that environment. Unlike [public hostname routes](/cloudflare-one/connections/connect-networks/routing-to-tunnel/), private network routes can expose both HTTP and non-HTTP resources. +With Cloudflare Zero Trust, you can connect private networks and the services running in those networks to Cloudflare's global network. This involves installing a [connector](#connectors) on the private network, and then [setting up routes](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#2b-connect-a-network) which define the IP addresses available in that environment. Unlike [published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/), private network routes can expose both HTTP and non-HTTP resources. To reach private network IPs, end users must connect their device to Cloudflare and enroll in your Zero Trust organization. The most common method is to install the [WARP client](/cloudflare-one/connections/connect-devices/warp/) on their device, or you can onboard their network traffic to Cloudflare using our [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) or [Magic WAN](/magic-wan/zero-trust/cloudflare-tunnel/). diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx index 74ef08215e0c926..bfb98ca433fb08a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx @@ -48,6 +48,6 @@ To set up WARP Connector, refer to the guide for your use case: - **[Site-to-Internet](/cloudflare-one/connections/connect-networks/private-net/warp-connector/site-to-internet/)**: Send requests from your private network to the Internet. - **[Site-to-site](/cloudflare-one/connections/connect-networks/private-net/warp-connector/site-to-site/)**: Send requests between two or more private networks. - **[User-to-site](/cloudflare-one/connections/connect-networks/private-net/warp-connector/user-to-site/)**: Allow WARP client devices to send requests to your private network. -- **Internet-to-site**: Not supported by WARP Connector. To provide clientless access to applications on your private network, set up a [Cloudflare Tunnel with `cloudflared`](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) and configure a [public hostname route](/cloudflare-one/connections/connect-networks/routing-to-tunnel/). +- **Internet-to-site**: Not supported by WARP Connector. To provide clientless access to applications on your private network, set up a [Cloudflare Tunnel with `cloudflared`](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) and configure a [published application](/cloudflare-one/connections/connect-networks/routing-to-tunnel/). [^1]: WARP Connector is an extension of the [WARP client](/cloudflare-one/connections/connect-devices/warp/). diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx index 64bc9606108510f..5ca265958d08424 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -title: Public hostnames +title: Published applications sidebar: order: 8 diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx index 586c6147dd6535a..15abfdb0c199aa4 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx @@ -16,11 +16,11 @@ Client-side `cloudflared` can be used in conjunction with [routing over WARP](/c 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Public Hostnames** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). +2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). 3. For **Service**, select _RDP_ and enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server (for example, `localhost:3389`). It will likely be port `3389`. -4. Select **Save hostname**. +4. Save the configuration. ## 2. (Recommended) Create an Access application diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx index deb7934716b6050..56515c9f1983446 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx @@ -67,15 +67,17 @@ The public hostname method can be implemented in conjunction with routing over W 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Public Hostnames** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `smb.example.com`). +2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `smb.example.com`). 3. For **Service**, select _TCP_ and enter the SMB listening port (for example, `localhost:445`). SMB drives listen on port `139` or `445` by default. -4. Select **Save hostname**. +4. Save the configuration. -5. (Recommended) Add a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to Cloudflare Access in order to manage access to your server. +## 2. (Recommended) Create an Access application -### 2. Connect as a user +By default, anyone on the Internet can connect to the server using its public hostname. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. + +### 3. Connect as a user 1. [Install `cloudflared`](/cloudflare-one/connections/connect-networks/downloads/) on the client machine. diff --git a/src/content/docs/cloudflare-one/tutorials/s3-buckets.mdx b/src/content/docs/cloudflare-one/tutorials/s3-buckets.mdx index 24f8e4a90d471f2..63e9dfcccd0328a 100644 --- a/src/content/docs/cloudflare-one/tutorials/s3-buckets.mdx +++ b/src/content/docs/cloudflare-one/tutorials/s3-buckets.mdx @@ -92,11 +92,11 @@ Your bucket policy will allow your VPC to access your S3 bucket. A bucket website endpoint will be available at `http://.s3-website..amazonaws.com`. Because of the bucket policy, this website endpoint will only be accessible from the VPC with the VPC endpoint configured. -### 4. Add a new public hostname to the Cloudflare Tunnel +### 4. Add a published application to the Cloudflare Tunnel -1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Access** > **Tunnels** +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels** 2. Select your Tunnel, then select **Configure**. -3. Go to **Public Hostname**, then select **Add a public hostname**. +3. Go to **Published applications**, then select **Add a public hostname**. 4. Enter a subdomain your organization will use to access the S3 bucket. For example, `s3-bucket..com`. 5. Under **Service**, choose _HTTP_ for **Type**. In **URL**, enter `.s3-website..amazonaws.com`. 6. In **Additional application settings** > **HTTP Settings**, input the **HTTP Host Header** as `.s3-website..amazonaws.com`. diff --git a/src/content/docs/data-localization/compatibility.mdx b/src/content/docs/data-localization/compatibility.mdx index ca8defd271f6c91..f4ecdcaab0a352d 100644 --- a/src/content/docs/data-localization/compatibility.mdx +++ b/src/content/docs/data-localization/compatibility.mdx @@ -131,7 +131,7 @@ The table below provides a summary of the Data Localization Suite product's beha [^15]: Can be localized to US FedRAMP Moderate Domestic region only. [^16]: Customer Metadata Boundary can be used to limit data transfer outside region, but Access User Logs will not be available outside US region. [^17]: Currently may only be used with US FedRAMP region. -[^18]: The only connectivity option is [US FedRAMP Moderate Domestic region](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region). Regional Services only applies when using [Public Hostnames](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) set to a region. +[^18]: The only connectivity option is [US FedRAMP Moderate Domestic region](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region). Regional Services only applies when using [Published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) set to a region. [^19]: Uses Gateway HTTP and CASB. [^20]: You can [bring your own certificate](https://blog.cloudflare.com/bring-your-certificates-cloudflare-gateway/) to Gateway but these cannot yet be restricted to a specific region. [^21]: Gateway HTTP supports Regional Services. Gateway DNS does not yet support regionalization.
ICMP proxy and WARP-to-WARP proxy are not available to Regional Services users. diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx index 94533499ae63807..a08b4c4eac401da 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -46,9 +46,9 @@ First, create a [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks ### 1.2. Connect your database using a public hostname -Your tunnel must be configured to use a public hostname so that Hyperdrive can route requests to it. If you don't have a hostname on Cloudflare yet, you will need to [register a new hostname](/registrar/get-started/register-domain/) or [add a zone](/dns/zone-setups/) to Cloudflare to proceed. +Your tunnel must be configured to use a public hostname on Cloudflare so that Hyperdrive can route requests to it. If you don't have a hostname on Cloudflare yet, you will need to [register a new hostname](/registrar/get-started/register-domain/) or [add a zone](/dns/zone-setups/) to Cloudflare to proceed. -1. In the **Public Hostnames** tab, choose a **Domain** and specify any subdomain or path information. This will be used in your Hyperdrive configuration to route to this tunnel. +1. In the **Published applications** tab, choose a **Domain** and specify any subdomain or path information. This will be used in your Hyperdrive configuration to route to this tunnel. 2. In the **Service** section, specify **Type** `TCP` and the URL and configured port of your database, such as `localhost:5432` or `my-database-host.database-provider.com:5432`. This address will be used by the tunnel to route requests to your database. diff --git a/src/content/docs/learning-paths/clientless-access/alternative-onramps/index.mdx b/src/content/docs/learning-paths/clientless-access/alternative-onramps/index.mdx index a059f15734c6db9..f33c92ddf8b5ecc 100644 --- a/src/content/docs/learning-paths/clientless-access/alternative-onramps/index.mdx +++ b/src/content/docs/learning-paths/clientless-access/alternative-onramps/index.mdx @@ -6,7 +6,7 @@ sidebar: --- -As discussed in the previous modules, almost everything you do with the Cloudflare reverse proxy requires [adding a site](/learning-paths/clientless-access/initial-setup/add-site/) to Cloudflare. That public DNS record (or its subdomains) becomes the domain on which your users access your private applications. This method is exceptionally secure and transparent; each domain and subdomain has access to the Cloudflare web security portfolio, are inherently DDoS protected, and receive an obfuscated origin IP. For these reasons, [public hostname routing](/learning-paths/clientless-access/connect-private-applications/) is the recommended method to onboard applications for clientless user access. However, there may be times in which a public DNS record cannot be created, or other situations that prevent administrators from using this method. +As discussed in the previous modules, almost everything you do with the Cloudflare reverse proxy requires [adding a site](/learning-paths/clientless-access/initial-setup/add-site/) to Cloudflare. That public DNS record (or its subdomains) becomes the domain on which your users access your private applications. This method is exceptionally secure and transparent; each domain and subdomain has access to the Cloudflare web security portfolio, are inherently DDoS protected, and receive an obfuscated origin IP. For these reasons, using a [public hostname on Cloudflare](/learning-paths/clientless-access/connect-private-applications/) is the recommended method to onboard applications for clientless user access. However, there may be times in which a public DNS record cannot be created, or other situations that prevent administrators from using this method. ## Objectives diff --git a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx index 7fe37db7dd75a42..0dfcf3fc1986084 100644 --- a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx +++ b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx @@ -8,7 +8,7 @@ sidebar: import { Render } from "~/components" -To enable clientless access to your applications, you will need to create a Cloudflare Tunnel that contains public hostname routes. A public hostname route creates a public DNS record that routes traffic to a specific address, protocol, and port associated with a private application. For example, you can define a public hostname (`mywebapp.example.com`) to provide access to a web server running on `https://localhost:8080`. When a user goes to `mywebapp.example.com` in their browser, their request will first route to a Cloudflare data center where it is inspected against your configured security policies. Cloudflare will then forward validated requests down your tunnel to the web server. +To enable clientless access to your applications, you will need to create a Cloudflare Tunnel that publishes applications to a domain on Cloudflare. A published application creates a public DNS record that routes traffic to a specific address, protocol, and port associated with a private application. For example, you can define a public hostname (`mywebapp.example.com`) to provide access to a web server running on `https://localhost:8080`. When a user goes to `mywebapp.example.com` in their browser, their request will first route to a Cloudflare data center where it is inspected against your configured security policies. Cloudflare will then forward validated requests down your tunnel to the web server. ![How an HTTP request reaches a private application connected with Cloudflare Tunnel](~/assets/images/cloudflare-one/connections/connect-apps/handshake.jpg) @@ -20,7 +20,7 @@ To create a Cloudflare Tunnel: ## Connect an application -To add a public hostname route to the tunnel: +To add a published application to the tunnel: diff --git a/src/content/docs/learning-paths/clientless-access/terraform/publish-apps-with-terraform.mdx b/src/content/docs/learning-paths/clientless-access/terraform/publish-apps-with-terraform.mdx index 60d0bcf31f48457..449633a6b4ad3a4 100644 --- a/src/content/docs/learning-paths/clientless-access/terraform/publish-apps-with-terraform.mdx +++ b/src/content/docs/learning-paths/clientless-access/terraform/publish-apps-with-terraform.mdx @@ -7,7 +7,7 @@ sidebar: import { Details, Render } from "~/components"; -This guide covers how to use the [Cloudflare Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs) to quickly publish and secure a private application. In the following example, we will add a new public hostname route to an existing Cloudflare Tunnel, configure how `cloudflared` proxies traffic to the application, and secure the application with Cloudflare Access. +This guide covers how to use the [Cloudflare Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs) to quickly publish and secure a private application. In the following example, we will add a new published application to an existing Cloudflare Tunnel, configure how `cloudflared` proxies traffic to the application, and secure the application with Cloudflare Access. ## Prerequisites @@ -73,7 +73,7 @@ To prevent accidentally exposing your Cloudflare credentials, do not save this f Add the following resources to your Terraform configuration. -### Add public hostname route to Cloudflare Tunnel +### Add published application to Cloudflare Tunnel Using the [`cloudflare_tunnel_config`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/tunnel_config) resource, create an ingress rule that maps your application to a public DNS record. This example makes `localhost:8080` available on `app.mycompany.com`, sets the [Connect Timeout](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#connecttimeout), and enables [Access JWT validation](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#access). @@ -105,7 +105,7 @@ resource "cloudflare_tunnel_config" "example_config" { :::note -Public hostname configurations must include a catch-all ingress rule at the bottom of the file. +Published application configurations must include a catch-all ingress rule at the bottom of the file. ::: ### Create an Access application diff --git a/src/content/docs/load-balancing/additional-options/cloudflare-tunnel.mdx b/src/content/docs/load-balancing/additional-options/cloudflare-tunnel.mdx index 3cc8dff4d7d4a09..bfd06ddd84588b5 100644 --- a/src/content/docs/load-balancing/additional-options/cloudflare-tunnel.mdx +++ b/src/content/docs/load-balancing/additional-options/cloudflare-tunnel.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: navigation -title: Cloudflare Tunnel (public hostnames) +title: Cloudflare Tunnel (published applications) sidebar: order: 2 head: diff --git a/src/content/docs/reference-architecture/design-guides/zero-trust-for-startups.mdx b/src/content/docs/reference-architecture/design-guides/zero-trust-for-startups.mdx index 5390445619cf542..826c9c7ec973780 100644 --- a/src/content/docs/reference-architecture/design-guides/zero-trust-for-startups.mdx +++ b/src/content/docs/reference-architecture/design-guides/zero-trust-for-startups.mdx @@ -264,7 +264,7 @@ We recommend using our Cloudflare Access product for remote access to your inter In a lot of cases, you may even use both products for application access. For example, if you're self-hosting [Sentry](https://sentry.io/) β€” which is not currently available on the public Internet β€” follow these steps: 1. Set up a public hostname with Cloudflare Access (which your users would navigate to Sentry on). -2. Install a Cloudflare Tunnel with an associated Public Hostname route to point to your local Sentry service. +2. Install a Cloudflare Tunnel with an associated **Published application** to point to your local Sentry service. 3. Integrate Sentry with Access for SaaS as the SSO provider. Now, users reaching the application from outside your network will already carry the Cloudflare JWT, and will be seamlessly authenticated into your application. diff --git a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx index ac1790edaa43f53..d29454442b74f45 100644 --- a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx @@ -4,10 +4,10 @@ 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Public Hostnames** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `ssh.example.com`). +2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `ssh.example.com`). 3. For **Service**, select _SSH_ and enter `localhost:22`. If the SSH server is on a different machine from where you installed the tunnel, enter `:22`. -4. Select **Save hostname**. +4. Save the configuration. 5. (Recommended) Add a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to Cloudflare Access in order to manage access to your server. diff --git a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx index e80fa2c455286fd..75ecc2d4cea1282 100644 --- a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx @@ -3,11 +3,11 @@ --- -[Public hostname routes](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) allow anyone on the Internet to connect to HTTP resources hosted on your virtual private cloud (VPC). To add a public hostname route for your Cloudflare Tunnel: +[Published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) allow anyone on the Internet to connect to HTTP resources hosted on your virtual private cloud (VPC). To add a published application for your Cloudflare Tunnel: -1. In the **Public Hostname** tab, enter a hostname for the application (for example, `hellocloudflare..com`). +1. In the **Published applications** tab, enter a hostname for the application (for example, `hellocloudflare..com`). 2. Under **Service**, enter `http://localhost:80`. -3. Select **Save hostname**. +3. Save the configuration. 4. To test, open a browser and go to `http://hellocloudflare..com`. You should see the **Hello Cloudflare!** test page. You can optionally [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to control who can access the service. diff --git a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx index d3c0ea1b1bcd830..0823ed9d3573923 100644 --- a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx +++ b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx @@ -124,4 +124,4 @@ To troubleshoot TLS inspection: - **Option 1:** Create a permanent [`Do Not Inspect` HTTP policy](/cloudflare-one/policies/gateway/http-policies/#do-not-inspect) for this application. - **Option 2:** Customers who use their [own certificate infrastructure](/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/) for inspection can opt to create an [Allow _Pass Through_ policy](/cloudflare-one/policies/gateway/http-policies/#untrusted-certificates) which enables our proxy to accept the TLS negotiation from your application. This will allow requests to flow correctly without the need for a `Do Not Inspect` policy. - - **Option 3:** If your application uses `HTTPS` or other common protocols, you can add a [public hostname route](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) to your Cloudflare Tunnel and set [noTLSVerify](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#notlsverify) to `true`. This will allow `cloudflared` to trust your self-signed certificate. + - **Option 3:** If your application uses `HTTPS` or other common protocols, you can add a [published application](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) to your Cloudflare Tunnel and set [noTLSVerify](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#notlsverify) to `true`. This will allow `cloudflared` to trust your self-signed certificate. From 5684e59feebc3f8d88d039379f8943ebcbaa1445 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 16:32:17 -0400 Subject: [PATCH 08/79] hostname format restrictions --- .../cloudflared/connect-private-hostname.mdx | 11 +++++++++++ .../partials/cloudflare-one/access/add-target.mdx | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 897c35eaac9ce06..3e1ece92f25f55e 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -45,6 +45,17 @@ This section covers how to enable remote access to a private hostname applicatio ### 1. Connect the server to Cloudflare +Hostname must be unique for an account (1:M mapping from hostname to Tunnel) + +
+ - Less than 255 characters + - Leading wildcards (`*`) and dots (`.`) are allowed but trimmed off. For example, `*.internal.local` becomes `internal.local`. + - Ending dots (`.`) are allowed but trimmed off. + - No wildcards (`*`) in the middle. For example, `foo*bar.internal.local` is not allowed. + - Hostnames with non-Latin characters must be Punycode encoded and include the [ACE prefix](https://en.wikipedia.org/wiki/Punycode#ACE_prefix_for_internationalized_domain_names). For example, to represent `δΎ‹.internal.local`, enter `xn--fsq.internal.local`. +
+ + ### 2. Set up the client
diff --git a/src/content/partials/cloudflare-one/access/add-target.mdx b/src/content/partials/cloudflare-one/access/add-target.mdx index b4746a37622d083..6d1e4abab86ee11 100644 --- a/src/content/partials/cloudflare-one/access/add-target.mdx +++ b/src/content/partials/cloudflare-one/access/add-target.mdx @@ -19,7 +19,7 @@ To create a new target:

) : 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Targets**. 2. Select **Add a target**. 3. In **Target hostname**, enter a user-friendly name for the target resource. We recommend using the server hostname, for example `production-server`. The hostname does not need to be unique and can be reused for multiple targets. Hostnames are used to define the subset of targets included in an infrastructure application and are not used in DNS address resolution. -
+
- Case insensitive - Contain no more than 253 characters - Contain only alphanumeric characters, `-`, or `.` (no spaces allowed) From 2a0b473e36ef41baed4d682f390bbf19a52f7560 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 17:20:39 -0400 Subject: [PATCH 09/79] connect server --- .../connections/connect-networks/deployment-guides/aws.mdx | 2 +- .../deployment-guides/google-cloud-platform.mdx | 2 +- .../private-net/cloudflared/connect-private-hostname.mdx | 5 ++++- .../private-net/cloudflared/tunnel-virtual-networks.mdx | 2 +- .../cloudflare-one/tutorials/user-selectable-egress-ips.mdx | 2 +- .../docs/load-balancing/private-network/tunnels-setup.mdx | 2 +- .../partials/cloudflare-one/tunnel/cloud-create-tunnel.mdx | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx index 0d3ee64de4a84e4..9c03b1283974d22 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx @@ -98,7 +98,7 @@ EOF [Private network routes](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) allow users to connect to your virtual private cloud (VPC) using the WARP client. To add a private network route for your Cloudflare Tunnel: -1. In the **Private Network** tab, enter the **Private IPv4 address** of your AWS instance (for example, `172.31.19.0`). You can expand the IP range later if necessary. +1. In the **Private Networks** tab, enter the **Private IPv4 address** of your AWS instance (for example, `172.31.19.0`). You can expand the IP range later if necessary. 2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the private IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `172.16.0.0/12`. We recommend re-adding the IPs that are not explicitly used by your AWS instance. To determine which IP addresses to re-add, subtract your AWS instance IPs from `172.16.0.0/12`: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx index cc0742d11a8b9ec..229ea71e0191fe0 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx @@ -77,7 +77,7 @@ To complete the following procedure, you will need to: To configure a private network route for your Cloudflare Tunnel: -1. In the **Private Network** tab, enter the **Internal IP** of your GCP VM instance (for example, `10.0.0.2`). You can expand the IP range later if necessary. +1. In the **Private Networsk** tab, enter the **Internal IP** of your GCP VM instance (for example, `10.0.0.2`). You can expand the IP range later if necessary. 2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the internal IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `10.0.0.0/8`. We recommend re-adding the IPs that are not explicitly used by your GCP VM. To determine which IP addresses to re-add, subtract your GCP instance IPs from `10.0.0.0/8`: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 3e1ece92f25f55e..72918c05ce099bc 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -45,7 +45,9 @@ This section covers how to enable remote access to a private hostname applicatio ### 1. Connect the server to Cloudflare -Hostname must be unique for an account (1:M mapping from hostname to Tunnel) + + +9. In the **Hostname routes** tab, enter the fully qualified domain name (FDQN) that represents your application (for example, `wiki.internal.local`).
- Less than 255 characters @@ -55,6 +57,7 @@ Hostname must be unique for an account (1:M mapping from hostname to Tunnel) - Hostnames with non-Latin characters must be Punycode encoded and include the [ACE prefix](https://en.wikipedia.org/wiki/Punycode#ACE_prefix_for_internationalized_domain_names). For example, to represent `δΎ‹.internal.local`, enter `xn--fsq.internal.local`.
+10. Select **Complete setup**. ### 2. Set up the client diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx index edd22e0d3567a19..67705af0a366f55 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx @@ -60,7 +60,7 @@ The following example demonstrates how to add two overlapping IP routes to Cloud 2. Select **Create a tunnel**. 3. Name your tunnel `Staging tunnel` and select **Save tunnel**. 4. Install the connector within your staging environment. - 5. In the **Private Network** tab, add `10.128.0.1/32`. + 5. In the **Private Networks** tab, add `10.128.0.1/32`. 6. Select **Additional settings**. Under **Virtual networks**, select *staging-vnet*. 7. Save the tunnel. 8. Repeat Steps 2a-2g to create another tunnel called `Production tunnel`. Be sure to install the connector within your production environment and assign the route to *production-vnet*. diff --git a/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx b/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx index f02c4aff27e28fc..f33a5e6779782c5 100644 --- a/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx +++ b/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx @@ -73,7 +73,7 @@ After creating your virtual networks, route your private network CIDRs over each 1. Go to **Networks** > **Tunnels**. 2. Select your tunnel routing `10.0.0.0/8`, then select **Configure**. -3. Go to **Private Network**. Select the `10.0.0.0/8` route. +3. Go to **Private Networks**. Select the `10.0.0.0/8` route. 4. In **Additional settings**, choose your first virtual network. For example, `vnet-AMER`. 5. Select **Save private network**. 6. To route `10.0.0.0/8` over another virtual network, select **Add a private network**. diff --git a/src/content/docs/load-balancing/private-network/tunnels-setup.mdx b/src/content/docs/load-balancing/private-network/tunnels-setup.mdx index 559a30ed32cd325..2ec9b2b97c5a1d2 100644 --- a/src/content/docs/load-balancing/private-network/tunnels-setup.mdx +++ b/src/content/docs/load-balancing/private-network/tunnels-setup.mdx @@ -28,7 +28,7 @@ To assign the virtual network to the tunnel: 1. Go to **Networks** > **Tunnels**. 2. Select the tunnel you created in the previous steps and select **Configure**. -3. Under **Private Network**, select **Add a private network**. +3. Under **Private Networks**, select **Add a private network**. 4. Specify an IP range under **CIDR** and select the virtual network under **Additional settings**. 5. Select **Save private network**. diff --git a/src/content/partials/cloudflare-one/tunnel/cloud-create-tunnel.mdx b/src/content/partials/cloudflare-one/tunnel/cloud-create-tunnel.mdx index 473e2e17196246c..68ebb4ec9c8c204 100644 --- a/src/content/partials/cloudflare-one/tunnel/cloud-create-tunnel.mdx +++ b/src/content/partials/cloudflare-one/tunnel/cloud-create-tunnel.mdx @@ -5,7 +5,7 @@ inputParameters: param1;;param2 import { Markdown } from "~/components" -Next, we will create a Cloudflare Tunnel in Zero Trust and run the tunnel on the {props.one}. +Create a Cloudflare Tunnel in Zero Trust and run the tunnel on the {props.one}. 1. Log in to [Zero Trust](https://one.dash.cloudflare.com) and go to **Networks** > **Tunnels**. From ef75afb7ce08e4c3ab2e3aa233bbd3f5a1d4c190 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 17:24:59 -0400 Subject: [PATCH 10/79] set up client --- .../private-net/cloudflared/connect-private-hostname.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 72918c05ce099bc..7df9d298be20c5b 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -78,6 +78,7 @@ This section covers how to enable remote access to a private hostname applicatio
+ ### 3. Route private network IPs through WARP From cc27929754b06e8283767f42aca8df2907cc49d1 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 17:28:05 -0400 Subject: [PATCH 11/79] account limits --- src/content/docs/cloudflare-one/account-limits.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/account-limits.mdx b/src/content/docs/cloudflare-one/account-limits.mdx index f895913839d1b6a..d334bf3251b82bc 100644 --- a/src/content/docs/cloudflare-one/account-limits.mdx +++ b/src/content/docs/cloudflare-one/account-limits.mdx @@ -60,7 +60,7 @@ This page lists the default account limits for rules, applications, fields, and | Feature | Limit | | ---------------------------------------- | ----- | | Tunnels per account | 1,000 | -| IP routes per account | 1,000 | +| Combined hostname and IP routes per tunnel | 1,000 | | Active `cloudflared` replicas per tunnel | 25 | ## Digital Experience Monitoring (DEX) From d461be960f9be741d6f7866d3556505b9d407601 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 22 May 2025 18:19:33 -0400 Subject: [PATCH 12/79] create resolver policy, add IPv6 --- .../cloudflared/connect-private-hostname.mdx | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 7df9d298be20c5b..9d0723184d2bd47 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -29,9 +29,13 @@ Figures 1 and 2 illustrate the flow of DNS and network traffic when a user conne 2. Based on the configured resolver policies, Gateway determines that `wiki.internal.local` should be resolved by a custom DNS resolver. Therefore, Gateway sends the DNS request down Cloudflare Tunnel to the private network where the custom DNS resolver is located. 3. `cloudflared` does a DNS lookup to figure out what the origin IP is for `wiki.internal.local`. 4. The Gateway resolver now knows that the origin IP is `10.0.0.5`. -5. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the CGNAT range `100.80.0.0/16` (for example, `100.80.0.1`). This CGNAT IP is called the initial resolved IP. -6. Gateway's network engine stores the mapping between the private hostname, initial resolved IP, and the actual IP. -7. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response for `wiki.internal.local`. +5. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the following CGNAT range: + - **IPv4**: `100.80.0.0/16` + - **IPv6**: `2606:4700:0cf1:4000::/64` + + The selected CGNAT IP is called the initial resolved IP. +6. Gateway's network engine stores the mapping between the private hostname (`wiki.internal.local`), initial resolved IP (`100.80.0.1`), and the actual IP (`10.0.0.5`). +7. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response. As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP. The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. Because the packet's destination IP falls within the designated CGNAT range, Gateway knows that it corresponds to a hostname route and can apply hostname-based policies. Traffic that passes your Gateway policies will route through Cloudflare Tunnel to the application's actual origin IP. @@ -43,7 +47,7 @@ To learn more about hostname routing, refer to the [Cloudflare blog](). This section covers how to enable remote access to a private hostname application using `cloudflared` and WARP. -### 1. Connect the server to Cloudflare +### 1. Connect the application to Cloudflare @@ -59,7 +63,23 @@ This section covers how to enable remote access to a private hostname applicatio 10. Select **Complete setup**. -### 2. Set up the client +### 2. Connect the DNS server to Cloudflare + +Route the IP address of your internal DNS resolver through the tunnel. + +### 3. Create a resolver policy + +1. [Create a Gateway resolver policy](cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the following traffic: + + | Selector | Operator | Value | + | -------- | -------- | ---------------------- | + | Host | in | `wiki.internal.local` | + +2. Under **Configure custom DNS resolvers**, enter the IPv4 and/or IPv6 address of your internal DNS resolver. The dropdown menu will not populate until you type in the full IP address. + +3. From the dropdown menu, select the `- Private` routing option and the [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) where the DNS resolver is located. + +### 4. Set up the client
@@ -80,15 +100,13 @@ This section covers how to enable remote access to a private hostname applicatio -### 3. Route private network IPs through WARP +### 5. Route private network IPs through WARP - Initial resolved IP CGNAT range: `100.80.0.0/16` - Private network CIDR where the application is located, e.g. `10.0.0.0/8`. (Still need to know the IP range of the network. Do not need to know the specific IP of the application) - Internal DNS resolver IP -### 4. Create a resolver policy - -### 5. (Recommended) Filter network traffic with Gateway +### 6. (Recommended) Filter network traffic with Gateway #### Enable Gateway proxy for TCP and UDP #### Zero Trust policies @@ -102,7 +120,7 @@ Option 2: create a Gateway network policy using the SNI selector https://develop Self-hosted private apps and Gateway network policies are not currently supported for services on non-443 ports. You can only create a Gateway DNS policy. -### 6. Connect as a user +### 7. Connect as a user From ff4f1bb261741d54437ee7639db811ad3c940ea5 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 23 May 2025 16:50:12 -0400 Subject: [PATCH 13/79] update private hostname diagram --- .../connections/private-hostname-route-1.png | Bin 42512 -> 40090 bytes .../cloudflared/connect-private-hostname.mdx | 13 ++++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png b/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png index 27656cd29c49d5d39039579f139abf06f571a75a..585f6c54faea9d187246e67c20dafdf1792fea40 100644 GIT binary patch literal 40090 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 Kr^~Ic-ThBGCA{hY literal 42512 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 Date: Fri, 23 May 2025 17:19:36 -0400 Subject: [PATCH 14/79] update policy guidelines --- .../private-net/cloudflared/connect-cidr.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index 990ae34fa5b6d74..f1cac8c80188ecb 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -27,7 +27,7 @@ To connect your infrastructure with Cloudflare Tunnel: ## 4. (Recommended) Filter network traffic with Gateway -By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway inspect your network traffic and either block or allow access based on user identity and device posture. +By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway to inspect your network traffic and either block or allow access based on user identity and device posture. ### Enable the Gateway proxy @@ -35,7 +35,9 @@ By default, all WARP devices enrolled in your Zero Trust organization can connec ### Zero Trust policies -Cloudflare Zero Trust allows you to configure security policies using either Access or Gateway. If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway [network and DNS policies](/learning-paths/replace-vpn/build-policies/) for IP ranges and domains. +To prevent WARP users from accessing your entire private network, we recommend creating a [catch-all block policy](/learning-paths/replace-vpn/build-policies/create-policy/#catch-all-policy) for your private IP space. You can then layer on higher priority Allow policies which grant users access to specific applications or IPs. + +If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway [network and DNS policies](/learning-paths/replace-vpn/build-policies/) for IP ranges and domains. ## 5. Connect as a user From 1233ed2db815c5d474e0346baa717264cfdb69ea Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 23 May 2025 17:32:10 -0400 Subject: [PATCH 15/79] update egress diagram --- .../egress-policies/egress-cloudflared.mdx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 678009973c41a4b..e2d46780e346601 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -9,21 +9,24 @@ import { Details } from "~/components"; Cloudflare Tunnel can be used for source IP anchoring when you want to use existing egress IPs instead of purchasing [Cloudflare dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Some third-party websites may have an Access Control List (ACL) that only allow connections from certain source IPs. If you already a non-Cloudflare IP on their allowlist (such an egress IP provided by an ISP or a cloud provider like AWS), you can configure `cloudflared` to anchor user traffic to the same IPs that you use today. -For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS envirionment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will route their traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. +For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS environment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will route their traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. ```mermaid flowchart LR subgraph aws["AWS VPC"] - cloudflared["cloudflared"]--> rules["Egress rules"] + cloudflared["cloudflared"] end subgraph cloudflare[Cloudflare] - resolver["Gateway - resolver"] + gateway["Gateway"] + end + subgraph internet[Internet] + resolver[1.1.1.1] + app[Application] end warp["WARP - clients"]--"app.bank.com"-->resolver - resolver-->cloudflared - rules--AWS egress IP -->I{Internet} + clients"]--"app.bank.com"-->gateway--"Network traffic"-->cloudflared + gateway<-.DNS lookup.->resolver + aws--AWS egress IP -->app ``` ## Prerequisites From d12a6fcb1c5c7a8cb46536253536a127f8fdb458 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 23 May 2025 18:03:49 -0400 Subject: [PATCH 16/79] add placeholders --- .../cloudflared/connect-private-hostname.mdx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 3a16a25c0098e75..562857da8b3973a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -64,10 +64,13 @@ This section covers how to enable remote access to a private hostname applicatio ### 2. Connect the DNS server to Cloudflare +--------to do------ Route the IP address of your internal DNS resolver through the tunnel. ### 3. Create a resolver policy +To resolve the private hostname through Cloudflare: + 1. [Create a Gateway resolver policy](cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the following traffic: | Selector | Operator | Value | @@ -101,15 +104,24 @@ Route the IP address of your internal DNS resolver through the tunnel. ### 5. Route private network IPs through WARP +--------to do------ + - Initial resolved IP CGNAT range: `100.80.0.0/16` - Private network CIDR where the application is located, e.g. `10.0.0.0/8`. (Still need to know the IP range of the network. Do not need to know the specific IP of the application) - Internal DNS resolver IP ### 6. (Recommended) Filter network traffic with Gateway -#### Enable Gateway proxy for TCP and UDP +--------to do------ + +#### Enable Gateway proxy + + + #### Zero Trust policies +--------to do------ + If you're running a private app on port 443: Option 1: create an Access self-hosted private app https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/ @@ -121,6 +133,9 @@ Self-hosted private apps and Gateway network policies are not currently supporte ### 7. Connect as a user +End users can now reach the application by going to its private hostname. For example, to test an HTTP application, you can open a browser and go to `wiki.internal.local`. + +---- what's a good example for a non-HTTP app?--- ## Supported on-ramps/off-ramps From 6f704f319cf6e817cf8135f5684b9f7213eb64f7 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 23 May 2025 18:04:09 -0400 Subject: [PATCH 17/79] update egress description --- .../policies/gateway/egress-policies/egress-cloudflared.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index e2d46780e346601..e2ce33ef8f94281 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -9,7 +9,7 @@ import { Details } from "~/components"; Cloudflare Tunnel can be used for source IP anchoring when you want to use existing egress IPs instead of purchasing [Cloudflare dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Some third-party websites may have an Access Control List (ACL) that only allow connections from certain source IPs. If you already a non-Cloudflare IP on their allowlist (such an egress IP provided by an ISP or a cloud provider like AWS), you can configure `cloudflared` to anchor user traffic to the same IPs that you use today. -For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS environment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will route their traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. +For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS environment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will apply your network policies and route the filered traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. ```mermaid flowchart LR @@ -29,6 +29,8 @@ For example, assume that your organization's banking service, `app.bank.com`, ex aws--AWS egress IP -->app ``` +To learn more about how Gateway applies hostname-based policies, refer to the [Cloudflare blog](). + ## Prerequisites ## 1. Connect private network to Cloudflare From 0125a0ab9401eed951a95a544894baf440c8a70d Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 23 May 2025 18:08:57 -0400 Subject: [PATCH 18/79] add beta pill --- .../private-net/cloudflared/connect-private-hostname.mdx | 2 ++ .../policies/gateway/egress-policies/egress-cloudflared.mdx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 562857da8b3973a..09e149c4c66c7ab 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -3,6 +3,8 @@ pcx_content_type: how-to title: Connect a private hostname sidebar: order: 2 + badge: + text: Beta --- import { Render, Details } from "~/components"; diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index e2ce33ef8f94281..65d21ed25707eff 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -3,6 +3,8 @@ pcx_content_type: how-to title: Egress through Cloudflare Tunnel sidebar: order: 2 + badge: + text: Beta --- import { Details } from "~/components"; From b0d0bdb1b47c621fa395c8b7f06fa267e4bd6c51 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 27 May 2025 18:29:27 -0400 Subject: [PATCH 19/79] add split tunnel and policy details --- .../private-net/cloudflared/connect-cidr.mdx | 8 ++-- .../cloudflared/connect-private-hostname.mdx | 40 +++++++++++++------ .../private-net/cloudflared/private-dns.mdx | 2 +- .../tunnel/catch-all-policy.mdx | 6 +++ .../tunnel/enable-gateway-proxy.mdx | 2 + .../tunnel/filter-network-traffic.mdx | 5 +++ .../tunnel/warp-to-tunnel-route-ips.mdx | 28 +++++++++---- 7 files changed, 68 insertions(+), 23 deletions(-) create mode 100644 src/content/partials/cloudflare-one/tunnel/catch-all-policy.mdx create mode 100644 src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index f1cac8c80188ecb..6184f0b18b5dc35 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -27,7 +27,7 @@ To connect your infrastructure with Cloudflare Tunnel: ## 4. (Recommended) Filter network traffic with Gateway -By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway to inspect your network traffic and either block or allow access based on user identity and device posture. + ### Enable the Gateway proxy @@ -35,9 +35,11 @@ By default, all WARP devices enrolled in your Zero Trust organization can connec ### Zero Trust policies -To prevent WARP users from accessing your entire private network, we recommend creating a [catch-all block policy](/learning-paths/replace-vpn/build-policies/create-policy/#catch-all-policy) for your private IP space. You can then layer on higher priority Allow policies which grant users access to specific applications or IPs. + -If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway [network and DNS policies](/learning-paths/replace-vpn/build-policies/) for IP ranges and domains. +If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway network and DNS policies for IP ranges and domains. + +For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ## 5. Connect as a user diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 09e149c4c66c7ab..410df8c8eb8f28f 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -66,12 +66,21 @@ This section covers how to enable remote access to a private hostname applicatio ### 2. Connect the DNS server to Cloudflare ---------to do------ -Route the IP address of your internal DNS resolver through the tunnel. +To route your internal DNS resolver through Cloudflare Tunnel: + +1. Go to **Networks** > **Routes**. + +2. Select **Create route**. + +3. In **CIDR**, enter the private IP address of your internal DNS resolver. + +4. For **Tunnel**, select the Cloudflare Tunnel that is being used to connect the private network to Cloudflare. + +5. Select **Create**. ### 3. Create a resolver policy -To resolve the private hostname through Cloudflare: +Configure Gateway to resolve the private hostname using your internal DNS resolver: 1. [Create a Gateway resolver policy](cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the following traffic: @@ -104,17 +113,19 @@ To resolve the private hostname through Cloudflare: -### 5. Route private network IPs through WARP +### 5. Route traffic through WARP ---------to do------ +In your [device profiles]((/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/)), [configure Split Tunnels](cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: - Initial resolved IP CGNAT range: `100.80.0.0/16` -- Private network CIDR where the application is located, e.g. `10.0.0.0/8`. (Still need to know the IP range of the network. Do not need to know the specific IP of the application) +- Private network CIDR where the application is located (for example, `10.0.0.0/8`) - Internal DNS resolver IP +For more details on configuring Split Tunnels, refer to [Route private network IPs through WARP](). + ### 6. (Recommended) Filter network traffic with Gateway ---------to do------ + #### Enable Gateway proxy @@ -122,16 +133,21 @@ To resolve the private hostname through Cloudflare: #### Zero Trust policies ---------to do------ + + +##### HTTPS applications + +If your private hostname points to an HTTPS application on port 443, you can secure it using either Access or Gateway policies: -If you're running a private app on port 443: + - Option 1 (Recommended): Create an [Access self-hosted private app](/cloudflare-one/applications/non-http/self-hosted-private-app/) to manage user access alongside your SaaS and other web apps. -Option 1: create an Access self-hosted private app https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/ + - Option 2: If you prefer to secure a private network using a traditional firewall model, build Gateway network and DNS policies using the [SNI](/cloudflare-one/policies/gateway/network-policies/#sni) or [SNI Domain](/cloudflare-one/policies/gateway/network-policies/#sni-domain) selector. For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). -Option 2: create a Gateway network policy using the SNI selector https://developers.cloudflare.com/cloudflare-one/policies/gateway/network-policies/#sni +##### Non-HTTPS applications -Self-hosted private apps and Gateway network policies are not currently supported for services on non-443 ports. You can only create a Gateway DNS policy. +Access policies and Gateway network policies only support hostname-based filtering for applications on port 443. If your application runs on a non-443 port, you will need to allow or block network traffic using the [Destination IP](/cloudflare-one/policies/gateway/network-policies/#destination-ip) selector. Then, add a Gateway DNS policy to allow or block the [Host](/cloudflare-one/policies/gateway/dns-policies/#host) or [Domain](/cloudflare-one/policies/gateway/dns-policies/#domain) from resolving. +For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ### 7. Connect as a user diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx index ad777d3b0ea49dd..78d1d27b345f1de 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx @@ -19,7 +19,7 @@ To resolve private DNS queries: :::note - Ensure that **Split Tunnels** are configured to [include traffic to private IPs and hostnames](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#3-route-private-network-ips-through-warp). + Ensure that **Split Tunnels** are configured to [include traffic to private IPs and hostnames](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). ::: diff --git a/src/content/partials/cloudflare-one/tunnel/catch-all-policy.mdx b/src/content/partials/cloudflare-one/tunnel/catch-all-policy.mdx new file mode 100644 index 000000000000000..798067db655e6b0 --- /dev/null +++ b/src/content/partials/cloudflare-one/tunnel/catch-all-policy.mdx @@ -0,0 +1,6 @@ +--- +{} +--- + +To prevent WARP users from accessing your entire private network, we recommend creating a [catch-all block policy](/learning-paths/replace-vpn/build-policies/create-policy/#catch-all-policy) for your private IP space. You can then layer on higher priority Allow policies which grant users access to specific applications or IPs. + diff --git a/src/content/partials/cloudflare-one/tunnel/enable-gateway-proxy.mdx b/src/content/partials/cloudflare-one/tunnel/enable-gateway-proxy.mdx index 39904f2f677d63a..e3cd975df26e2a8 100644 --- a/src/content/partials/cloudflare-one/tunnel/enable-gateway-proxy.mdx +++ b/src/content/partials/cloudflare-one/tunnel/enable-gateway-proxy.mdx @@ -4,6 +4,8 @@ import { Tabs, TabItem } from "~/components"; +To start logging and filtering network traffic, turn on the Gateway proxy: + 1. Go to **Settings** > **Network**. diff --git a/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx b/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx new file mode 100644 index 000000000000000..f96eae19160a928 --- /dev/null +++ b/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway to inspect your network traffic and either block or allow access based on user identity and device posture. diff --git a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx index 267d3dbeeebdcc3..5db7ae2e6cecfef 100644 --- a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx +++ b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx @@ -3,18 +3,20 @@ params: - one --- -import { Markdown } from "~/components"; +import { Markdown, Details, Tabs, TabItem} from "~/components"; import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; By default, WARP excludes traffic bound for [RFC 1918 space](https://datatracker.ietf.org/doc/html/rfc1918), which are IP addresses typically used in private networks and not reachable from the Internet. In order for WARP to send traffic to your , you must configure [Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the IP/CIDR of your routes through WARP. 1. First, check whether your [Split Tunnels mode](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#change-split-tunnels-mode) is set to **Exclude** or **Include** mode. -2. If you are using **Include** mode, add your 's IP/CIDR range to the list. Your list should also include the [domains necessary for Cloudflare Zero Trust functionality](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains). -3. If you are using **Exclude** mode: +2. Edit your Split Tunnel routes depending on the mode: + - a. Delete your 's IP/CIDR range from the list. For example, if your network uses the default AWS range of `172.31.0.0/16`, delete `172.16.0.0/12`. + If you are using **Exclude** mode: - b. Re-add IP/CIDR ranges that are not explicitly used by your . For the AWS example above, you would add new entries for `172.16.0.0/13`, `172.24.0.0/14`, `172.28.0.0/15`, and `172.30.0.0/16`. This ensures that only traffic to `172.31.0.0/16` routes through WARP. + a. [Delete the route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#remove-a-route) containing your 's IP/CIDR range. For example, if your network uses the default AWS range of `172.31.0.0/16`, delete `172.16.0.0/12`. + + b. [Re-add IP/CIDR ranges](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) that are not explicitly used by your . For the AWS example above, you would add new entries for `172.16.0.0/13`, `172.24.0.0/14`, `172.28.0.0/15`, and `172.30.0.0/16`. This ensures that only traffic to `172.31.0.0/16` routes through WARP. You can use the following calculator to determine which IP addresses to re-add: @@ -25,6 +27,18 @@ By default, WARP excludes traffic bound for [RFC 1918 space](https://datatracker exclude: ["172.31.0.0/16", `172.28.0.0/15`] }} /> - In **Base CIDR**, enter the RFC 1918 range that you deleted from Split Tunnels. In **Excluded CIDRs**, enter the IP/CIDR range used by your . Re-add the calculator results to your Split Tunnel Exclude mode list. +
+ 1. In **Base CIDR**, enter the RFC 1918 range that you deleted from Split Tunnels. + 2. In **Excluded CIDRs**, enter the IP/CIDR range used by your . + 3. Re-add the calculator results to your Split Tunnel Exclude mode list. +
+ + By tightening the private IP range included in WARP, you reduce the risk of breaking a user's [access to local resources](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/#allow-users-to-enable-local-network-exclusion). + + +
+ If you are using **Include** mode: + 1. Add the required [Zero Trust domains](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains) or [IP addresses](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-ip-addresses) to your Split Tunnel include list. + 2. [Add a route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to include your 's IP/CIDR range. -By tightening the private IP range included in WARP, you reduce the risk of breaking a user's [access to local resources](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/#allow-users-to-enable-local-network-exclusion). +
From 9d54a209440bce0377267284310fbdd0cd9bd6e9 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 27 May 2025 19:26:13 -0400 Subject: [PATCH 20/79] example policies --- .../private-net/cloudflared/connect-cidr.mdx | 26 +++++++++ .../cloudflared/connect-private-hostname.mdx | 57 ++++++++++++++++++- .../tunnel/filter-network-traffic.mdx | 2 +- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index 6184f0b18b5dc35..1fcea3f2946b73c 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -39,6 +39,32 @@ To connect your infrastructure with Cloudflare Tunnel: If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway network and DNS policies for IP ranges and domains. +
+ The following example consists of two policies: the first allows specific users to reach your application, and the second blocks all other traffic. + + 1. Allow company employees + + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | Destination IP | in | `10.0.0.0/8` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | + + 2. Catch-all block policy + + | Selector | Operator | Value | Action | + | -------------- | -------- | ------------ | ------ | + | Destination IP | in | `10.0.0.0/8` | Block | + +
+ +
+ + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | Host | is | `wiki.internal.com` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | +
+ For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ## 5. Connect as a user diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 410df8c8eb8f28f..b365c047f928b3d 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -139,15 +139,66 @@ For more details on configuring Split Tunnels, refer to [Route private network I If your private hostname points to an HTTPS application on port 443, you can secure it using either Access or Gateway policies: - - Option 1 (Recommended): Create an [Access self-hosted private app](/cloudflare-one/applications/non-http/self-hosted-private-app/) to manage user access alongside your SaaS and other web apps. + - **Option 1 (Recommended)**: Create an [Access self-hosted private app](/cloudflare-one/applications/non-http/self-hosted-private-app/) to manage user access alongside your SaaS and other web apps. + + - **Option 2**: If you prefer to secure the application using a traditional firewall model, build Gateway network policies using the [SNI](/cloudflare-one/policies/gateway/network-policies/#sni) or [SNI Domain](/cloudflare-one/policies/gateway/network-policies/#sni-domain) selector. For an additional layer of protection, add a Gateway DNS policy to allow or block the [Host](/cloudflare-one/policies/gateway/dns-policies/#host) or [Domain](/cloudflare-one/policies/gateway/dns-policies/#domain) from resolving. + +
+ The following example consists of two policies: the first allows specific users to reach your application, and the second blocks all other traffic. + + 1. Allow company employees + + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | SNI | is | `wiki.internal.com` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | + + 2. Catch-all block policy + + | Selector | Operator | Value | Action | + | -------------- | -------- | ------------ | ------ | + | Destination IP | in | `10.0.0.0/8` | Block | +
+ +
+ + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | Host | is | `wiki.internal.com` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | +
- - Option 2: If you prefer to secure a private network using a traditional firewall model, build Gateway network and DNS policies using the [SNI](/cloudflare-one/policies/gateway/network-policies/#sni) or [SNI Domain](/cloudflare-one/policies/gateway/network-policies/#sni-domain) selector. For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ##### Non-HTTPS applications Access policies and Gateway network policies only support hostname-based filtering for applications on port 443. If your application runs on a non-443 port, you will need to allow or block network traffic using the [Destination IP](/cloudflare-one/policies/gateway/network-policies/#destination-ip) selector. Then, add a Gateway DNS policy to allow or block the [Host](/cloudflare-one/policies/gateway/dns-policies/#host) or [Domain](/cloudflare-one/policies/gateway/dns-policies/#domain) from resolving. +
+ The following example consists of two policies: the first allows specific users to reach your application, and the second blocks all other traffic. + + 1. Allow company employees + + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | Destination IP | in | `10.0.0.0/8` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | + + 2. Catch-all block policy + + | Selector | Operator | Value | Action | + | -------------- | -------- | ------------ | ------ | + | Destination IP | in | `10.0.0.0/8` | Block | + +
+ + +
+ + | Selector | Operator | Value | Logic | Action | + | -------------- | ------------- | ---------------- | ----- | ------ | + | Host | is | `wiki.internal.com` | And | Allow | + | User Email | matches regex | `.*@example.com` | | | +
-For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ### 7. Connect as a user diff --git a/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx b/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx index f96eae19160a928..33b8915c0eb4f46 100644 --- a/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx +++ b/src/content/partials/cloudflare-one/tunnel/filter-network-traffic.mdx @@ -2,4 +2,4 @@ {} --- -By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway to inspect your network traffic and either block or allow access based on user identity and device posture. +By default, all WARP devices enrolled in your Zero Trust organization can connect to your private network through Cloudflare Tunnel. You can configure Gateway to inspect your network traffic and either block or allow access based on user identity and device posture. To learn more about policy design, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/). From 6d3c82a34fb1073f62d0916dc17bfa4f3441dd79 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 27 May 2025 19:27:45 -0400 Subject: [PATCH 21/79] fix example hostname --- .../private-net/cloudflared/connect-cidr.mdx | 2 +- .../private-net/cloudflared/connect-private-hostname.mdx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index 1fcea3f2946b73c..dcfd7b1dd94284b 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -61,7 +61,7 @@ If you have applications clearly defined by IPs or hostnames, we recommend [crea | Selector | Operator | Value | Logic | Action | | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.com` | And | Allow | + | Host | is | `wiki.internal.local` | And | Allow | | User Email | matches regex | `.*@example.com` | | |
diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index b365c047f928b3d..f8fc0943ccf1f51 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -150,7 +150,7 @@ If your private hostname points to an HTTPS application on port 443, you can sec | Selector | Operator | Value | Logic | Action | | -------------- | ------------- | ---------------- | ----- | ------ | - | SNI | is | `wiki.internal.com` | And | Allow | + | SNI | is | `wiki.internal.local` | And | Allow | | User Email | matches regex | `.*@example.com` | | | 2. Catch-all block policy @@ -164,7 +164,7 @@ If your private hostname points to an HTTPS application on port 443, you can sec | Selector | Operator | Value | Logic | Action | | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.com` | And | Allow | + | Host | is | `wiki.internal.local` | And | Allow | | User Email | matches regex | `.*@example.com` | | |
@@ -195,7 +195,7 @@ Access policies and Gateway network policies only support hostname-based filteri | Selector | Operator | Value | Logic | Action | | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.com` | And | Allow | + | Host | is | `wiki.internal.local` | And | Allow | | User Email | matches regex | `.*@example.com` | | |
From 3afe762ab9d8f53a5a4598db685def16f3342487 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 27 May 2025 19:30:50 -0400 Subject: [PATCH 22/79] tweak availability note --- .../private-net/cloudflared/connect-private-hostname.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index f8fc0943ccf1f51..ed7cc1f938bcb35 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -12,7 +12,7 @@ import { Render, Details } from "~/components"; `cloudflared` can route to HTTP and non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. :::note[Availability] -Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) and [configure Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/) to resolve its private hostname. +Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) and resolve its private hostname using [Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/). ::: ## How private hostname routing works From 97ad52c208de7ad9597d526f7465b252c5aa90ad Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 13:49:14 -0400 Subject: [PATCH 23/79] policy partials --- .../gateway/network-policies/common-policies.mdx | 10 ++-------- .../restrict-access-to-private-networks-allow.mdx | 8 ++++++++ .../restrict-access-to-private-networks-block.mdx | 7 +++++++ .../restrict-access-to-private-networks-dns.mdx | 8 ++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-allow.mdx create mode 100644 src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-block.mdx create mode 100644 src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-dns.mdx diff --git a/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx index 02282b56b97824f..efac87813b3fcfa 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx @@ -175,11 +175,7 @@ The following example consists of two policies: the first allows specific users -| Selector | Operator | Value | Logic | Action | -| -------------- | ------------- | ---------------- | ----- | ------ | -| Destination IP | in | `10.0.0.0/8` | And | Allow | -| User Email | matches regex | `.*@example.com` | | | - + @@ -208,9 +204,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ -| Selector | Operator | Value | Action | -| -------------- | -------- | ------------ | ------ | -| Destination IP | in | `10.0.0.0/8` | Block | + diff --git a/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-allow.mdx b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-allow.mdx new file mode 100644 index 000000000000000..4e453523e39abb5 --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-allow.mdx @@ -0,0 +1,8 @@ +--- +inputParameters: selector;;value +--- + +| Selector | Operator | Value | Logic | Action | +| -------------- | ------------- | ---------------- | ----- | ------ | +| {props.selector} | in | {props.value} | And | Allow | +| User Email | matches regex | `.*@example.com` | | | diff --git a/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-block.mdx b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-block.mdx new file mode 100644 index 000000000000000..3b9f11e6ef1ca2b --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-block.mdx @@ -0,0 +1,7 @@ +--- +{} +--- + +| Selector | Operator | Value | Action | +| -------------- | -------- | ------------ | ------ | +| Destination IP | in | `10.0.0.0/8` | Block | \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-dns.mdx b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-dns.mdx new file mode 100644 index 000000000000000..293b0d23be0ff03 --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/policies/restrict-access-to-private-networks-dns.mdx @@ -0,0 +1,8 @@ +--- +{} +--- + +| Selector | Operator | Value | Logic | Action | +| -------------- | ------------- | ---------------- | ----- | ------ | +| Host | in | `wiki.internal.local` | And | Allow | +| User Email | matches regex | `.*@example.com` | | | From f6e3c01265b69806ad23d7644a6af90e65d8c91f Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 13:50:08 -0400 Subject: [PATCH 24/79] update policies, testing, troubleshooting --- .../private-net/cloudflared/connect-cidr.mdx | 26 ------------ .../cloudflared/connect-private-hostname.mdx | 41 ++++++------------- .../tunnel/troubleshoot-private-networks.mdx | 2 +- 3 files changed, 14 insertions(+), 55 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index dcfd7b1dd94284b..6184f0b18b5dc35 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -39,32 +39,6 @@ To connect your infrastructure with Cloudflare Tunnel: If you have applications clearly defined by IPs or hostnames, we recommend [creating an Access application](/cloudflare-one/applications/non-http/self-hosted-private-app/) and managing user access alongside your SaaS and other web apps. Alternatively, if you prefer to secure a private network using a traditional firewall model, you can build Gateway network and DNS policies for IP ranges and domains. -
- The following example consists of two policies: the first allows specific users to reach your application, and the second blocks all other traffic. - - 1. Allow company employees - - | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | Destination IP | in | `10.0.0.0/8` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | - - 2. Catch-all block policy - - | Selector | Operator | Value | Action | - | -------------- | -------- | ------------ | ------ | - | Destination IP | in | `10.0.0.0/8` | Block | - -
- -
- - | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.local` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | -
- For more information on building Gateway policies, refer to [Secure your first application](/learning-paths/replace-vpn/build-policies/create-policy/) and [Common network policies](/cloudflare-one/policies/gateway/network-policies/common-policies/#restrict-access-to-private-networks). ## 5. Connect as a user diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index ed7cc1f938bcb35..d798e49bb7be32b 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -127,7 +127,7 @@ For more details on configuring Split Tunnels, refer to [Route private network I -#### Enable Gateway proxy +#### Enable the Gateway proxy @@ -148,25 +148,17 @@ If your private hostname points to an HTTPS application on port 443, you can sec 1. Allow company employees - | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | SNI | is | `wiki.internal.local` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | + 2. Catch-all block policy - | Selector | Operator | Value | Action | - | -------------- | -------- | ------------ | ------ | - | Destination IP | in | `10.0.0.0/8` | Block | +
- | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.local` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | -
+ + ##### Non-HTTPS applications @@ -177,35 +169,28 @@ Access policies and Gateway network policies only support hostname-based filteri 1. Allow company employees - | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | Destination IP | in | `10.0.0.0/8` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | + 2. Catch-all block policy - | Selector | Operator | Value | Action | - | -------------- | -------- | ------------ | ------ | - | Destination IP | in | `10.0.0.0/8` | Block | + -
- | Selector | Operator | Value | Logic | Action | - | -------------- | ------------- | ---------------- | ----- | ------ | - | Host | is | `wiki.internal.local` | And | Allow | - | User Email | matches regex | `.*@example.com` | | | +
+### 7. Test the connection -### 7. Connect as a user +End users can now reach the application by going to its private hostname. For example, to test an HTTP application, open a browser and go to `wiki.internal.local`. -End users can now reach the application by going to its private hostname. For example, to test an HTTP application, you can open a browser and go to `wiki.internal.local`. +If you [enabled the Gateway proxy](#enable-the-gateway-proxy), you can view the traffic in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). ----- what's a good example for a non-HTTP app?--- +### Troubleshooting +For a step-by-step troubleshooting procedure, refer to [Troubleshoot private network connectivity](/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/private-networks/). ## Supported on-ramps/off-ramps diff --git a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx index 0823ed9d3573923..ba7a3ea1315406a 100644 --- a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx +++ b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx @@ -20,7 +20,7 @@ If WARP is stuck in the `Disconnected` state or frequently changes between `Conn ## 2. Is the WARP client connecting to your private DNS server? -This step is only needed if users access your application via a private hostname (for example, `wiki.internal.com`). +This step is only needed if users access your application via a private hostname (for example, `wiki.internal.local`). - If you are using [custom resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) to handle private DNS, go to your Gateway DNS logs (**Logs** > **Gateway** > **DNS**) and search for DNS queries to the hostname. From 3852707e3b9a4d9aa6832c89346ee9cc10ffe231 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 13:56:59 -0400 Subject: [PATCH 25/79] update availability --- .../connect-networks/private-net/cloudflared/connect-cidr.mdx | 2 ++ .../private-net/cloudflared/connect-private-hostname.mdx | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index 6184f0b18b5dc35..d015c49fb97a3e3 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -45,6 +45,8 @@ For more information on building Gateway policies, refer to [Secure your first a End users can now reach HTTP or TCP-based services on your network by visiting any IP address in the range you have specified. +To allow users to reach the service using its private hostname instead of its IP, refer to [Private DNS](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/). + ### Troubleshooting #### Device configuration diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index d798e49bb7be32b..817bf38d597ed70 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -11,8 +11,8 @@ import { Render, Details } from "~/components"; `cloudflared` can route to HTTP and non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. -:::note[Availability] -Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using its [IP address](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) and resolve its private hostname using [Local Domain Fallback](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/). +:::note[Only available on Enterprise plans] +Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using [IP routes](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/). ::: ## How private hostname routing works From cfc93748f00fcc32927bef4d3480d64f9e0055cb Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 14:16:06 -0400 Subject: [PATCH 26/79] fix relative links --- .../private-net/cloudflared/connect-private-hostname.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 817bf38d597ed70..1fe885a0c5857a0 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -82,7 +82,7 @@ To route your internal DNS resolver through Cloudflare Tunnel: Configure Gateway to resolve the private hostname using your internal DNS resolver: -1. [Create a Gateway resolver policy](cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the following traffic: +1. [Create a Gateway resolver policy](/cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the private hostname for which you are establishing the route: | Selector | Operator | Value | | -------- | -------- | ---------------------- | @@ -115,7 +115,7 @@ Configure Gateway to resolve the private hostname using your internal DNS resolv ### 5. Route traffic through WARP -In your [device profiles]((/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/)), [configure Split Tunnels](cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: +In your [device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), [configure Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: - Initial resolved IP CGNAT range: `100.80.0.0/16` - Private network CIDR where the application is located (for example, `10.0.0.0/8`) From 61a71acd4a771751d70c95df955ef827f710bfae Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 14:34:29 -0400 Subject: [PATCH 27/79] convert prereqs to partials --- .../cloudflared/connect-private-hostname.mdx | 25 ++----------------- .../gateway/egress-policies/index.mdx | 25 ++----------------- .../gateway/egress-selector-onramps.mdx | 12 +++++++++ .../gateway/egress-selector-warp-version.mdx | 23 +++++++++++++++++ 4 files changed, 39 insertions(+), 46 deletions(-) create mode 100644 src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx create mode 100644 src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 1fe885a0c5857a0..d33bf88a832875c 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -94,22 +94,7 @@ Configure Gateway to resolve the private hostname using your internal DNS resolv ### 4. Set up the client -
- -| [WARP modes](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| Gateway with WARP | Enterprise | - -| System | Availability | Minimum WARP version | -| -------- | ------------ | -------------------- | -| Windows | βœ… | 2025.4.929.0 | -| macOS | βœ… | 2025.4.929.0 | -| Linux | βœ… | 2025.4.929.0 | -| iOS | ❌ | | -| Android | ❌ | | -| ChromeOS | ❌ | | - -
+ @@ -198,13 +183,7 @@ For a step-by-step troubleshooting procedure, refer to [Troubleshoot private net End users can connect to private hostnames from the following device on-ramps: -| On-ramp method | Compatibility | -| ------------------------------------------------------------------------------------------ | ------------- | -| [WARP client](/cloudflare-one/connections/connect-devices/warp/) | βœ… | -| [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | -| [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | + ### Private network connectivity diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx index a68db16b0bddfa3..63df354396b382b 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx @@ -180,32 +180,11 @@ Gateway uses Rust to evaluate regular expressions. The Rust implementation is sl ### Selector prerequisites -
- -| [WARP modes](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| Gateway with WARP | Enterprise | - -| System | Availability | Minimum WARP version | -| -------- | ------------ | -------------------- | -| Windows | βœ… | 2025.4.929.0 | -| macOS | βœ… | 2025.4.929.0 | -| Linux | βœ… | 2025.4.929.0 | -| iOS | ❌ | | -| Android | ❌ | | -| ChromeOS | ❌ | | - -
+ The [Application](#application), [Content Categories](#content-categories), [Domain](#domain), and [Host](#host) selectors are only available for traffic on-ramped to Gateway with the following methods: -| On-ramp method | Compatibility | -| ------------------------------------------------------------------------------------------ | ------------- | -| [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | -| [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | -| [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | + When you use these selectors in an egress policy for traffic from a supported on-ramp, Gateway will assign initial resolved IPs in the `100.80.0.0/16` range to the DNS queries, then apply the correct egress IP according to the egress policy. Unsupported traffic will be resolved with your default Gateway settings. Gateway will only overwrite the DNS response when the query matches a condition in the egress policy. If you use [DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/) to send a DNS query to Gateway with IPv4, IPv6, DoT, or DoH, Gateway will not return the initial resolved IP for supported traffic nor resolve unsupported traffic. diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx new file mode 100644 index 000000000000000..4907079a4a62ad0 --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -0,0 +1,12 @@ +--- +{} + +--- + +| On-ramp method | Compatibility | +| ------------------------------------------------------------------------------------------ | ------------- | +| [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | +| [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | +| [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | +| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx new file mode 100644 index 000000000000000..8224c99db07a79e --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx @@ -0,0 +1,23 @@ +--- +{} + +--- + +import { Details } from "~/components" + +
+ +| [WARP modes](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | +| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| Gateway with WARP | Enterprise | + +| System | Availability | Minimum WARP version | +| -------- | ------------ | -------------------- | +| Windows | βœ… | 2025.4.929.0 | +| macOS | βœ… | 2025.4.929.0 | +| Linux | βœ… | 2025.4.929.0 | +| iOS | ❌ | | +| Android | ❌ | | +| ChromeOS | ❌ | | + +
From ea9230fa992a2dae642a8c5e0e4a5bd62e48998b Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 14:49:16 -0400 Subject: [PATCH 28/79] update diagram --- .../connections/private-hostname-route-1.png | Bin 40090 -> 40057 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png b/src/assets/images/cloudflare-one/connections/private-hostname-route-1.png index 585f6c54faea9d187246e67c20dafdf1792fea40..473e9b510bc9b721421bd47a21ad5921ac5bacb6 100644 GIT binary patch literal 40057 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 N>t>dh%P+b{|2r(3IM4t9 literal 40090 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 Kr^~Ic-ThBGCA{hY From e6667e0500d49bb2890ad874db8509598c4832ed Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 18:09:00 -0400 Subject: [PATCH 29/79] refine egress use case --- .../cloudflared/connect-private-hostname.mdx | 8 ++-- .../egress-policies/egress-cloudflared.mdx | 48 +++++++++++++++---- .../gateway/egress-policies/index.mdx | 20 +------- .../gateway/egress-selector-split-tunnels.mdx | 25 ++++++++++ 4 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index d33bf88a832875c..a27d25294a5b4f4 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -68,15 +68,15 @@ This section covers how to enable remote access to a private hostname applicatio To route your internal DNS resolver through Cloudflare Tunnel: -1. Go to **Networks** > **Routes**. +1. Go to **Networks** > **Routes** > **CIDR**. -2. Select **Create route**. +2. Select **Create CIDR route**. 3. In **CIDR**, enter the private IP address of your internal DNS resolver. 4. For **Tunnel**, select the Cloudflare Tunnel that is being used to connect the private network to Cloudflare. -5. Select **Create**. +5. Select **Create route**. ### 3. Create a resolver policy @@ -106,7 +106,7 @@ In your [device profiles](/cloudflare-one/connections/connect-devices/warp/confi - Private network CIDR where the application is located (for example, `10.0.0.0/8`) - Internal DNS resolver IP -For more details on configuring Split Tunnels, refer to [Route private network IPs through WARP](). +For more details on configuring Split Tunnels, refer to [Route private network IPs through WARP](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). ### 6. (Recommended) Filter network traffic with Gateway diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 65d21ed25707eff..3ca6e4df634f0b2 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -7,11 +7,13 @@ sidebar: text: Beta --- -import { Details } from "~/components"; +import { Render, Details } from "~/components"; + + Cloudflare Tunnel can be used for source IP anchoring when you want to use existing egress IPs instead of purchasing [Cloudflare dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Some third-party websites may have an Access Control List (ACL) that only allow connections from certain source IPs. If you already a non-Cloudflare IP on their allowlist (such an egress IP provided by an ISP or a cloud provider like AWS), you can configure `cloudflared` to anchor user traffic to the same IPs that you use today. -For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS environment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will apply your network policies and route the filered traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. +For example, assume that your organization's banking service, `app.bank.com`, expects user traffic to come from an AWS IP. You can install `cloudflared` in your AWS environment and add a public hostname route pointing to `app.bank.com`. When users connect to `app.bank.com` using the WARP client, Gateway will apply your network policies and route the filtered traffic down the corresponding Cloudflare Tunnel to AWS. The traffic can then egress to the public Internet using your AWS egress IP. ```mermaid flowchart LR @@ -35,16 +37,46 @@ To learn more about how Gateway applies hostname-based policies, refer to the [C ## Prerequisites -## 1. Connect private network to Cloudflare +- [Connect your private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) to Cloudflare using `cloudflared`. In the AWS example shown above, you would connect the private CIDR block of your AWS VPC. +- User traffic is on-ramped to Gateway using one of the following methods: + + + +## 1. Add a public hostname route + +To route a public hostname through Cloudflare Tunnel: + +1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Networks** > **Routes** > **Hostname routes**. + +2. Select **Create hostname route**. + +3. In **Hostname**, enter the public hostname that represents the application (for example, `app.bank.com`). The hostname should be accessible from the public Internet. + +4. For **Tunnel**, select the Cloudflare Tunnel that is being used to connect the private network to Cloudflare. + +5. Select **Create route**. + +## 2. Route network traffic through WARP + +If your traffic is onboarded using WARP, ensure that traffic to the following IP addresses route through the WARP tunnel to Gateway: + +- Initial resolved IP CGNAT range: `100.80.0.0/16` +- Private network CIDR block + +### Route initial resolved IPs + +When users connect to a public hostname route, Gateway will assign an initial resolved IP from the `100.80.0.0/16` range to the DNS query. The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If the packet's destination IP falls within the designated CGNAT range, Gateway will know that it corresponds to a hostname route and sends it down Cloudflare Tunnel. + +To route `100.80.0.0/16` through WARP: -## 2. Add a public hostname route + -## 3. Route private network IPs through WARP +### Route private network IPs -## 4. (Optional) Filter network traffic with Gateway +To route your private network's CIDR block through WARP, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). -## 5. Create an egress policy +## 3. Create an egress policy Create an egress policy that points traffic to Cloudflare Tunnel. -## 6. Test the connection \ No newline at end of file +Traffic to the public hostname will now route to your private network before egressing to the Internet. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx index 63df354396b382b..48205c71e2317cf 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx @@ -217,22 +217,4 @@ Additionally, to use these selectors to filter traffic onboarded with WARP, you ``` -2. In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure your [Split Tunnel](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) depending on the mode: - - - - 1. [Remove the route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#remove-a-route) to the IP address `100.64.0.0/10` from your Split Tunnel exclude list. - 2. [Add routes](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to exclude the following IP addresses: - - `100.64.0.0/12` - - `100.81.0.0/16` - - `100.82.0.0/15` - - `100.84.0.0/14` - - `100.88.0.0/13` - - `100.96.0.0/11` - - - - 1. Add the required [Zero Trust domains](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains) or [IP addresses](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-ip-addresses) to your Split Tunnel include list. - 2. [Add a route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to include the IP address `100.80.0.0/16`. - - +2. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx new file mode 100644 index 000000000000000..28334cf67522b9e --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx @@ -0,0 +1,25 @@ +--- +{} + +--- +import { Tabs, TabItem } from "~/components" + +In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure your [Split Tunnel](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) depending on the mode: + + + + 1. [Remove the route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#remove-a-route) to the IP address `100.64.0.0/10` from your Split Tunnel exclude list. + 2. [Add routes](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to exclude the following IP addresses: + - `100.64.0.0/12` + - `100.81.0.0/16` + - `100.82.0.0/15` + - `100.84.0.0/14` + - `100.88.0.0/13` + - `100.96.0.0/11` + + + + 1. Add the required [Zero Trust domains](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains) or [IP addresses](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-ip-addresses) to your Split Tunnel include list. + 2. [Add a route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to include the IP address `100.80.0.0/16`. + + From ad64a3beda39b14b67e0d1efd57c52c6f11815a8 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 18:12:09 -0400 Subject: [PATCH 30/79] add Magic WAN onramp --- .../cloudflare-one/gateway/egress-selector-onramps.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx index 4907079a4a62ad0..018505efe163f51 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -8,5 +8,5 @@ | [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | | [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | | [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | \ No newline at end of file +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | βœ… | +| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | \ No newline at end of file From eb41dbe2f682698fe582d6ebc2fc799b5c64b2ee Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 28 May 2025 18:38:03 -0400 Subject: [PATCH 31/79] tweak initial resolved IP --- .../policies/gateway/egress-policies/egress-cloudflared.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 3ca6e4df634f0b2..af77f1420ef3175 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -65,7 +65,7 @@ If your traffic is onboarded using WARP, ensure that traffic to the following IP ### Route initial resolved IPs -When users connect to a public hostname route, Gateway will assign an initial resolved IP from the `100.80.0.0/16` range to the DNS query. The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If the packet's destination IP falls within the designated CGNAT range, Gateway will know that it corresponds to a hostname route and sends it down Cloudflare Tunnel. +When users connect to a public hostname route, Gateway will assign an initial resolved IP from the `100.80.0.0/16` range to the DNS query. The initial resolved IP is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If a packet's destination IP falls within the `100.80.0.0/16`, Gateway knows that the IP maps to a public hostname route and sends the traffic down the corresponding Cloudflare Tunnel. To route `100.80.0.0/16` through WARP: From c40cee8745851cdcef7ce06cfd5b7f1578bc6d21 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 3 Jun 2025 18:54:58 -0400 Subject: [PATCH 32/79] mobile WARP client versions --- .../cloudflare-one/gateway/egress-selector-warp-version.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx index 8224c99db07a79e..79fa611ec0868a3 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx @@ -16,8 +16,8 @@ import { Details } from "~/components" | Windows | βœ… | 2025.4.929.0 | | macOS | βœ… | 2025.4.929.0 | | Linux | βœ… | 2025.4.929.0 | -| iOS | ❌ | | -| Android | ❌ | | -| ChromeOS | ❌ | | +| iOS | βœ… | 1.10 | +| Android | βœ… | 2.4 | +| ChromeOS | βœ… | 2.4 | From f4f664478a4a8197c8336cde44c5593eb0e502ef Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 3 Jun 2025 18:56:17 -0400 Subject: [PATCH 33/79] remove punycode requirement --- .../private-net/cloudflared/connect-private-hostname.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index a27d25294a5b4f4..29c1ed77e214e12 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -59,7 +59,6 @@ This section covers how to enable remote access to a private hostname applicatio - Leading wildcards (`*`) and dots (`.`) are allowed but trimmed off. For example, `*.internal.local` becomes `internal.local`. - Ending dots (`.`) are allowed but trimmed off. - No wildcards (`*`) in the middle. For example, `foo*bar.internal.local` is not allowed. - - Hostnames with non-Latin characters must be Punycode encoded and include the [ACE prefix](https://en.wikipedia.org/wiki/Punycode#ACE_prefix_for_internationalized_domain_names). For example, to represent `δΎ‹.internal.local`, enter `xn--fsq.internal.local`. 10. Select **Complete setup**. From 2cccbdd459c1a284641e40c1328a8cf39cc42163 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 4 Jun 2025 15:45:39 -0400 Subject: [PATCH 34/79] public hostname Gateway policies --- .../egress-policies/egress-cloudflared.mdx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index af77f1420ef3175..59f9841bb96a7b7 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -75,8 +75,17 @@ To route `100.80.0.0/16` through WARP: To route your private network's CIDR block through WARP, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). -## 3. Create an egress policy +## 3. (Optional) Configure network policies -Create an egress policy that points traffic to Cloudflare Tunnel. +You can bulid [Gateway network policies](/cloudflare-one/policies/gateway/network-policies/) to filter HTTPS traffic to your public hostname on port 443. For example, suppose that you want to block all WARP users from accessing `app.bank.com` except for a specific set of users or groups. Additionally, those authorized users should only access `app.bank.com` using your AWS egress IP. You can accomplish this using two policies: the first allows specific users to reach `app.bank.com`, and the second blocks all other port 443 traffic to `app.bank.com`. -Traffic to the public hostname will now route to your private network before egressing to the Internet. \ No newline at end of file +1. Allow company employees + + +2. Block everyone else on port 443 + + | Selector | Operator | Value | Action | + | -------------- | -------- | ------------ | ------ | + | SNI | in | `app.bank.com` | Block | + +Gateway does not currently support hostname-based filtering for traffic on non-443 ports. To block traffic to `app.bank.com` on all ports, you will need to use the [Destination IP](/cloudflare-one/policies/gateway/network-policies/#destination-ip) selector and specify the public IP space of `app.bank.com`. \ No newline at end of file From 118f54be46e5b5801d3f1c282066262b1da09231 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 4 Jun 2025 15:46:44 -0400 Subject: [PATCH 35/79] more details on initial resolved IPs --- .../private-net/cloudflared/connect-private-hostname.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 29c1ed77e214e12..e25018ff25b591d 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -36,11 +36,13 @@ Figures 1 and 2 illustrate the flow of DNS and network traffic when a user conne The selected CGNAT IP is called the initial resolved IP. 5. Gateway's network engine stores the mapping between the private hostname (`wiki.internal.local`), initial resolved IP (`100.80.0.1`), and the actual IP (`10.0.0.5`). -6. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response. +6. The WARP client receives the initial resolved IP (`100.80.0.1`) in the DNS response. Each WARP device will receive a unique, ephemeral initial resolved IP. -As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP. The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. Because the packet's destination IP falls within the designated CGNAT range, Gateway knows that it corresponds to a hostname route and can apply hostname-based policies. Traffic that passes your Gateway policies will route through Cloudflare Tunnel to the application's actual origin IP. +As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` traffic to the initial resolved IP. -![Figure 2: Network traffic flow for a private hostname route](~/assets/images/cloudflare-one/connections/private-hostname-route-2.png "Figure 1: Network traffic flow for a private hostname route") +![Figure 2: Network traffic flow for a private hostname route](~/assets/images/cloudflare-one/connections/private-hostname-route-2.png "Figure 2: Network traffic flow for a private hostname route") + +The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. Because the packet's destination IP falls within the designated CGNAT range, Gateway knows that it corresponds to a hostname route and can apply hostname-based policies. Traffic that passes your Gateway policies will route through Cloudflare Tunnel to the application's actual origin IP. When the initial resolved IP expires, WARP will send a new DNS request (Figure 1) to refresh the initial resolved IP. To learn more about hostname routing, refer to the [Cloudflare blog](). From 474e7c495ac4f7855c38cc4abae269cc691550b4 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 4 Jun 2025 15:59:02 -0400 Subject: [PATCH 36/79] move Tunnel prereq into a step --- .../gateway/egress-policies/egress-cloudflared.mdx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 59f9841bb96a7b7..17843dd7d2d0185 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -37,12 +37,15 @@ To learn more about how Gateway applies hostname-based policies, refer to the [C ## Prerequisites -- [Connect your private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) to Cloudflare using `cloudflared`. In the AWS example shown above, you would connect the private CIDR block of your AWS VPC. - User traffic is on-ramped to Gateway using one of the following methods: -## 1. Add a public hostname route +## 1. Connect your private network + +[Connect your private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/) to Cloudflare using `cloudflared`. For example, if you want traffic to egress from AWS, connect the private CIDR block of your AWS VPC. + +## 2. Add a public hostname route To route a public hostname through Cloudflare Tunnel: @@ -56,7 +59,7 @@ To route a public hostname through Cloudflare Tunnel: 5. Select **Create route**. -## 2. Route network traffic through WARP +## 3. Route network traffic through WARP If your traffic is onboarded using WARP, ensure that traffic to the following IP addresses route through the WARP tunnel to Gateway: @@ -75,9 +78,9 @@ To route `100.80.0.0/16` through WARP: To route your private network's CIDR block through WARP, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). -## 3. (Optional) Configure network policies +## 4. (Optional) Configure network policies -You can bulid [Gateway network policies](/cloudflare-one/policies/gateway/network-policies/) to filter HTTPS traffic to your public hostname on port 443. For example, suppose that you want to block all WARP users from accessing `app.bank.com` except for a specific set of users or groups. Additionally, those authorized users should only access `app.bank.com` using your AWS egress IP. You can accomplish this using two policies: the first allows specific users to reach `app.bank.com`, and the second blocks all other port 443 traffic to `app.bank.com`. +You can build [Gateway network policies](/cloudflare-one/policies/gateway/network-policies/) to filter HTTPS traffic to your public hostname on port 443. For example, suppose that you want to block all WARP users from accessing `app.bank.com` except for a specific set of users or groups. Additionally, those authorized users should only access `app.bank.com` using your AWS egress IP. You can accomplish this using two policies: the first allows specific users to reach `app.bank.com`, and the second blocks all other port 443 traffic to `app.bank.com`. 1. Allow company employees From ae73144f04d20de02bcf979882eb3e8eb949dbeb Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 19 Jun 2025 16:53:14 -0400 Subject: [PATCH 37/79] magic wan is pending SHIP-8236 --- .../partials/cloudflare-one/gateway/egress-selector-onramps.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx index 018505efe163f51..404ef85745cb5e2 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -8,5 +8,5 @@ | [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | | [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | | [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | βœ… | +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | | [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | \ No newline at end of file From 3d33a60a6b73aaee5b4f0aea45bc0e19824f7531 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 19 Jun 2025 17:38:26 -0400 Subject: [PATCH 38/79] add glossary entry --- src/content/glossary/cloudflare-one.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/content/glossary/cloudflare-one.yaml b/src/content/glossary/cloudflare-one.yaml index b3f0fe391bff06c..463a590e780b5fc 100644 --- a/src/content/glossary/cloudflare-one.yaml +++ b/src/content/glossary/cloudflare-one.yaml @@ -103,6 +103,10 @@ entries: general_definition: |- an identity provider (IdP) stores and manages users' digital identities, enabling single sign-on and authentication for multiple applications. + - term: initial resolved IP + general_definition: |- + a unique, ephemeral IP address that Gateway assigns to DNS queries when filtering network traffic by hostname. The IP is randomly selected from the `100.80.0.0/16` (IPv4) or `2606:4700:0cf1:4000::/64` (IPv6) range. + - term: JSON web token general_definition: |- a compact way to securely transmit information between parties as a JSON object, often used for authentication. From b2980dddb4612d84ebfb4e656f9b979fdf4a8240 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 19 Jun 2025 17:39:25 -0400 Subject: [PATCH 39/79] add ipv6 range --- .../private-net/cloudflared/connect-private-hostname.mdx | 8 ++++---- .../gateway/egress-policies/egress-cloudflared.mdx | 9 +++++---- .../policies/gateway/egress-policies/index.mdx | 4 ++-- .../cloudflare-one/gateway/egress-selector-cgnat-ips.mdx | 7 +++++++ .../gateway/egress-selector-split-tunnels.mdx | 6 +++--- 5 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 src/content/partials/cloudflare-one/gateway/egress-selector-cgnat-ips.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index e25018ff25b591d..17000c96691d0b9 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -7,7 +7,7 @@ sidebar: text: Beta --- -import { Render, Details } from "~/components"; +import { Render, Details, GlossaryTooltip } from "~/components"; `cloudflared` can route to HTTP and non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. @@ -31,8 +31,7 @@ Figures 1 and 2 illustrate the flow of DNS and network traffic when a user conne 2. Based on the configured resolver policies, Gateway determines that `wiki.internal.local` should be resolved by a custom DNS resolver. 3. Gateway does a DNS lookup for `wiki.internal.local` through Cloudflare Tunnel, and the custom DNS resolver returns the origin IP (`10.0.0.5`). 4. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the following CGNAT range: - - **IPv4**: `100.80.0.0/16` - - **IPv6**: `2606:4700:0cf1:4000::/64` + The selected CGNAT IP is called the initial resolved IP. 5. Gateway's network engine stores the mapping between the private hostname (`wiki.internal.local`), initial resolved IP (`100.80.0.1`), and the actual IP (`10.0.0.5`). @@ -103,7 +102,8 @@ Configure Gateway to resolve the private hostname using your internal DNS resolv In your [device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), [configure Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: -- Initial resolved IP CGNAT range: `100.80.0.0/16` +- Initial resolved IP CGNAT range: + - Private network CIDR where the application is located (for example, `10.0.0.0/8`) - Internal DNS resolver IP diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 17843dd7d2d0185..f6a26368aa041b6 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -7,7 +7,7 @@ sidebar: text: Beta --- -import { Render, Details } from "~/components"; +import { Render, Details, GlossaryTooltip } from "~/components"; @@ -63,14 +63,15 @@ To route a public hostname through Cloudflare Tunnel: If your traffic is onboarded using WARP, ensure that traffic to the following IP addresses route through the WARP tunnel to Gateway: -- Initial resolved IP CGNAT range: `100.80.0.0/16` +- Initial resolved IP CGNAT range: + - Private network CIDR block ### Route initial resolved IPs -When users connect to a public hostname route, Gateway will assign an initial resolved IP from the `100.80.0.0/16` range to the DNS query. The initial resolved IP is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If a packet's destination IP falls within the `100.80.0.0/16`, Gateway knows that the IP maps to a public hostname route and sends the traffic down the corresponding Cloudflare Tunnel. +When users connect to a public hostname route, Gateway will assign an initial resolved IP to the DNS query. The initial resolved IP is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If a packet's destination IP falls within the initial resolved IP CGNAT range, Gateway knows that the IP maps to a public hostname route and sends the traffic down the corresponding Cloudflare Tunnel. -To route `100.80.0.0/16` through WARP: +To route initial resolved IPs through WARP: diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx index 48205c71e2317cf..d0ef67f4c1e65b9 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx @@ -5,7 +5,7 @@ sidebar: order: 5 --- -import { Render, Badge, Tabs, TabItem, Details } from "~/components"; +import { Render, Badge, Tabs, TabItem, Details, GlossaryTooltip } from "~/components"; :::note Only available on Enterprise plans. @@ -186,7 +186,7 @@ The [Application](#application), [Content Categories](#content-categories), [Dom -When you use these selectors in an egress policy for traffic from a supported on-ramp, Gateway will assign initial resolved IPs in the `100.80.0.0/16` range to the DNS queries, then apply the correct egress IP according to the egress policy. Unsupported traffic will be resolved with your default Gateway settings. Gateway will only overwrite the DNS response when the query matches a condition in the egress policy. If you use [DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/) to send a DNS query to Gateway with IPv4, IPv6, DoT, or DoH, Gateway will not return the initial resolved IP for supported traffic nor resolve unsupported traffic. +When you use these selectors in an egress policy for traffic from a supported on-ramp, Gateway will assign initial resolved IPs to the DNS queries, then apply the correct egress IP according to the egress policy. Unsupported traffic will be resolved with your default Gateway settings. Gateway will only overwrite the DNS response when the query matches a condition in the egress policy. If you use [DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/) to send a DNS query to Gateway with IPv4, IPv6, DoT, or DoH, Gateway will not return the initial resolved IP for supported traffic nor resolve unsupported traffic. To turn on the selectors for your account, use the [Patch Zero Trust account configuration](/api/resources/zero_trust/subresources/gateway/subresources/configurations/methods/edit/) endpoint. For example: diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-cgnat-ips.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-cgnat-ips.mdx new file mode 100644 index 000000000000000..ea9c95d04ff8dfe --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-cgnat-ips.mdx @@ -0,0 +1,7 @@ +--- +{} + +--- + +- **IPv4**: `100.80.0.0/16` +- **IPv6**: `2606:4700:0cf1:4000::/64` \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx index 28334cf67522b9e..d9be7a4423551c0 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx @@ -2,7 +2,7 @@ {} --- -import { Tabs, TabItem } from "~/components" +import { Tabs, TabItem, Render } from "~/components" In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure your [Split Tunnel](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) depending on the mode: @@ -20,6 +20,6 @@ In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/c 1. Add the required [Zero Trust domains](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains) or [IP addresses](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-ip-addresses) to your Split Tunnel include list. - 2. [Add a route](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to include the IP address `100.80.0.0/16`. - + 2. [Add routes](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route) to include the following IP addresses: + From a193f22af667fea3c5735b155b824e80cef27a9d Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 1 Jul 2025 12:37:39 -0400 Subject: [PATCH 40/79] update mobile WARP versions --- .../cloudflare-one/gateway/egress-selector-warp-version.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx index 79fa611ec0868a3..5e0ad1d117f5bbe 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-warp-version.mdx @@ -16,8 +16,8 @@ import { Details } from "~/components" | Windows | βœ… | 2025.4.929.0 | | macOS | βœ… | 2025.4.929.0 | | Linux | βœ… | 2025.4.929.0 | -| iOS | βœ… | 1.10 | -| Android | βœ… | 2.4 | -| ChromeOS | βœ… | 2.4 | +| iOS | βœ… | 1.11 | +| Android | βœ… | 2.4.2 | +| ChromeOS | βœ… | 2.4.2 | From 354fe1ed634648038c757d14dfde8344ca54abe9 Mon Sep 17 00:00:00 2001 From: ranbel <101146722+ranbel@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:01:06 -0400 Subject: [PATCH 41/79] Apply suggestions from code review --- src/content/docs/cloudflare-one/account-limits.mdx | 2 +- .../configure-tunnels/cloudflared-parameters/index.mdx | 2 +- .../use-cases/rdp/rdp-cloudflared-authentication.mdx | 2 +- .../connections/connect-networks/use-cases/smb.mdx | 4 ++-- src/content/docs/data-localization/compatibility.mdx | 2 +- .../connect-private-applications/create-tunnel.mdx | 4 ++-- .../partials/cloudflare-one/ssh/tunnel-public-hostname.mdx | 2 +- .../partials/cloudflare-one/tunnel/cloud-public-hostname.mdx | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/content/docs/cloudflare-one/account-limits.mdx b/src/content/docs/cloudflare-one/account-limits.mdx index b99e92d3842d374..f2b05491564a9eb 100644 --- a/src/content/docs/cloudflare-one/account-limits.mdx +++ b/src/content/docs/cloudflare-one/account-limits.mdx @@ -64,7 +64,7 @@ This page lists the default account limits for rules, applications, fields, and | Feature | Limit | | ---------------------------------------- | ----- | | Tunnels per account | 1,000 | -| Combined hostname and IP routes per tunnel | 1,000 | +| Routes per tunnel | 1,000 | | Active `cloudflared` replicas per tunnel | 25 | ## Digital Experience Monitoring (DEX) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx index b49c34756684033..33cebe3c4315b02 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx @@ -147,4 +147,4 @@ To configure how `cloudflared` sends requests to your [published applications](/ 3. Select the **Published applications** tab. 4. Choose an application and select **Edit**. 5. Under **Additional application settings**, modify one or more [origin configuration parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). -6. Select **Save hostname**. \ No newline at end of file +6. Select **Save**. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx index 15abfdb0c199aa4..fd79f6b3ca67c42 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx @@ -20,7 +20,7 @@ Client-side `cloudflared` can be used in conjunction with [routing over WARP](/c 3. For **Service**, select _RDP_ and enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server (for example, `localhost:3389`). It will likely be port `3389`. -4. Save the configuration. +4. Select **Save**. ## 2. (Recommended) Create an Access application diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx index 56515c9f1983446..235f5cc4c73cfc0 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx @@ -71,11 +71,11 @@ The public hostname method can be implemented in conjunction with routing over W 3. For **Service**, select _TCP_ and enter the SMB listening port (for example, `localhost:445`). SMB drives listen on port `139` or `445` by default. -4. Save the configuration. +4. Select **Save**. ## 2. (Recommended) Create an Access application -By default, anyone on the Internet can connect to the server using its public hostname. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. +By default, anyone on the Internet can connect to the server using the hostname of the published application. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. ### 3. Connect as a user diff --git a/src/content/docs/data-localization/compatibility.mdx b/src/content/docs/data-localization/compatibility.mdx index d0b4c2a3fa2ea41..e567a2c0859c0b1 100644 --- a/src/content/docs/data-localization/compatibility.mdx +++ b/src/content/docs/data-localization/compatibility.mdx @@ -131,7 +131,7 @@ The table below provides a summary of the Data Localization Suite product's beha [^15]: Can be localized to US FedRAMP Moderate Domestic region only. [^16]: Customer Metadata Boundary can be used to limit data transfer outside region, but Access User Logs will not be available outside US region. [^17]: Currently may only be used with US FedRAMP region. -[^18]: When Cloudflare Tunnel connects to Cloudflare, the connectivity options available are the Global Region (default) and [US FedRAMP Moderate Domestic region](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region). For incoming requests to the Cloudflare Edge, Regional Services only applies when using [public hostnames on Cloudflare](/cloudflare-one/connections/connect-networks/routing-to-tunnel/). In this case, the region associated with the DNS record will apply. +[^18]: When Cloudflare Tunnel connects to Cloudflare, the connectivity options available are the Global Region (default) and [US FedRAMP Moderate Domestic region](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region). For incoming requests to the Cloudflare Edge, Regional Services only applies when using [published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/). In this case, the region associated with the DNS record will apply. [^19]: Uses Gateway HTTP and CASB. [^20]: You can [bring your own certificate](https://blog.cloudflare.com/bring-your-certificates-cloudflare-gateway/) to Gateway but these cannot yet be restricted to a specific region. [^21]: Gateway HTTP supports Regional Services. Gateway DNS does not yet support regionalization.
ICMP proxy and WARP-to-WARP proxy are not available to Regional Services users. diff --git a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx index 0dfcf3fc1986084..2ba903431f70ecd 100644 --- a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx +++ b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx @@ -18,9 +18,9 @@ To create a Cloudflare Tunnel: -## Connect an application +## Publish an application -To add a published application to the tunnel: +To route an application to a public hostname: diff --git a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx index d29454442b74f45..fa5edbe923921ad 100644 --- a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx @@ -8,6 +8,6 @@ 3. For **Service**, select _SSH_ and enter `localhost:22`. If the SSH server is on a different machine from where you installed the tunnel, enter `:22`. -4. Save the configuration. +4. Select **Save**. 5. (Recommended) Add a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to Cloudflare Access in order to manage access to your server. diff --git a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx index 75ecc2d4cea1282..ee1af85fd517fbc 100644 --- a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx @@ -7,7 +7,7 @@ 1. In the **Published applications** tab, enter a hostname for the application (for example, `hellocloudflare..com`). 2. Under **Service**, enter `http://localhost:80`. -3. Save the configuration. +3. Select **Save**. 4. To test, open a browser and go to `http://hellocloudflare..com`. You should see the **Hello Cloudflare!** test page. You can optionally [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to control who can access the service. From 48d77c2bd6ec2062ea5be3a1d62cf6cb06829b41 Mon Sep 17 00:00:00 2001 From: ranbel <101146722+ranbel@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:02:12 -0400 Subject: [PATCH 42/79] Update rdp-cloudflared-authentication.mdx --- .../use-cases/rdp/rdp-cloudflared-authentication.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx index fd79f6b3ca67c42..65fa736023cba0d 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx @@ -24,7 +24,7 @@ Client-side `cloudflared` can be used in conjunction with [routing over WARP](/c ## 2. (Recommended) Create an Access application -By default, anyone on the Internet can connect to the server using its public hostname. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. +By default, anyone on the Internet can connect to the server using the hostname of the published application. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. ## 3. Connect as a user @@ -49,4 +49,4 @@ If the client machine is running Windows, port `3389` may already be consumed lo 4. Double-click the newly added PC. 5. When asked if you want to continue, select **Continue**. -When the client launches, a browser window will open and prompt the user to authenticate with Cloudflare Access. \ No newline at end of file +When the client launches, a browser window will open and prompt the user to authenticate with Cloudflare Access. From d66c2c433e4e33bff55458fa733757e8fca6586f Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Tue, 12 Aug 2025 18:18:55 -0400 Subject: [PATCH 43/79] remove steps formatting --- .../partials/cloudflare-one/tunnel/create-tunnel.mdx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/content/partials/cloudflare-one/tunnel/create-tunnel.mdx b/src/content/partials/cloudflare-one/tunnel/create-tunnel.mdx index 4877be7689af99e..6fefdf6135e88d5 100644 --- a/src/content/partials/cloudflare-one/tunnel/create-tunnel.mdx +++ b/src/content/partials/cloudflare-one/tunnel/create-tunnel.mdx @@ -3,9 +3,6 @@ --- -import { Steps } from "~/components"; - - 1. Log in to [Zero Trust](https://one.dash.cloudflare.com) and go to **Networks** > **Tunnels**. 2. Select **Create a tunnel**. @@ -22,5 +19,4 @@ import { Steps } from "~/components"; ![Connector appearing in the UI after cloudflared has run](~/assets/images/cloudflare-one/connections/connect-apps/connector.png) -8. Select **Next**. - +8. Select **Next**. \ No newline at end of file From 46d847b78f1c97d4105b0ede4c8dfd1fa4482dfa Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Wed, 13 Aug 2025 13:43:24 -0400 Subject: [PATCH 44/79] add mwan and warpconn limitation --- .../cloudflared/connect-private-hostname.mdx | 6 ++++++ .../gateway/egress-selector-onramps.mdx | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 17000c96691d0b9..96e1a74b8bddd87 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -180,6 +180,12 @@ For a step-by-step troubleshooting procedure, refer to [Troubleshoot private net ## Supported on-ramps/off-ramps +The table below summarizes the Cloudflare One products that are compatible with private hostname routing. Refer to the table legend for guidance on interpreting the table. + +βœ… Product works with no caveats
+🚧 Product can be used with some caveats
+❌ Product cannot be used
+ ### Device connectivity End users can connect to private hostnames from the following device on-ramps: diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx index 404ef85745cb5e2..85f6b5f9321d8bb 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -8,5 +8,18 @@ | [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | | [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | | [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | -| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | \ No newline at end of file +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | 🚧[^1] | +| [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | βœ… | + +[^1]: Not compatible with [ECMP routing](/magic-wan/reference/traffic-steering/#equal-cost-multi-path-routing). For hostname-based routing to work, DNS queries and the resulting network traffic must reach Cloudflare over the same Magic WAN tunnel.
+ +:::note[WARP Connector and Magic WAN] + +DNS traffic to the Gateway resolver must route through Cloudflare's network instead of over the public Internet. If your devices are behind WARP Connector, you may need to [configure your router](/cloudflare-one/connections/connect-networks/private-net/warp-connector/site-to-internet/#3-route-traffic-from-subnet-to-warp-connector) to route the Gateway resolver IPs through WARP Connector. If your devices are behind Magic WAN, [create a route](/magic-wan/configuration/manually/how-to/configure-routes/) to route the Gateway resolver IPs through the Magic WAN tunnel. + +The Gateway resolver IPs are: + +- `172.64.36.1` +- `172.64.36.2` + +::: \ No newline at end of file From fa0748c0c585aaf6cc66d5284af6810d5e8ce9f2 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 14:31:52 -0400 Subject: [PATCH 45/79] fix package.json --- package-lock.json | 2904 ++++++++++++++++++++++++++++++++++----------- package.json | 12 +- 2 files changed, 2190 insertions(+), 726 deletions(-) diff --git a/package-lock.json b/package-lock.json index b1911238d57243a..a3b17382c116b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@astrojs/check": "0.9.4", "@astrojs/react": "4.2.5", "@astrojs/rss": "4.0.12", - "@astrojs/sitemap": "3.4.1", + "@astrojs/sitemap": "3.4.2", "@astrojs/starlight": "0.35.1", "@astrojs/starlight-docsearch": "0.6.0", "@astrojs/starlight-tailwind": "4.0.1", @@ -22,7 +22,7 @@ "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.41.3", "@expressive-code/plugin-line-numbers": "0.41.3", - "@floating-ui/react": "0.27.13", + "@floating-ui/react": "0.27.15", "@iarna/toml": "2.2.5", "@lottiefiles/dotlottie-react": "0.14.4", "@marsidev/react-turnstile": "1.3.0", @@ -49,7 +49,7 @@ "dedent": "1.6.0", "dompurify": "3.2.6", "dot-prop": "9.0.0", - "eslint": "9.31.0", + "eslint": "9.32.0", "eslint-plugin-astro": "1.3.1", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", @@ -64,7 +64,7 @@ "jsonc-parser": "3.3.1", "ldrs": "1.1.7", "lz-string": "1.5.0", - "marked": "16.1.1", + "marked": "16.1.2", "mdast-util-from-markdown": "2.0.2", "mdast-util-mdx": "3.0.0", "mdast-util-mdx-expression": "2.0.1", @@ -115,8 +115,8 @@ "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", - "vitest": "2.1.6", - "wrangler": "4.26.0" + "vitest": "2.1.9", + "wrangler": "4.26.1" }, "engines": { "node": ">=22" @@ -184,9 +184,9 @@ } }, "node_modules/@actions/http-client/node_modules/undici": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", - "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, "license": "MIT", "dependencies": { @@ -837,15 +837,15 @@ } }, "node_modules/@astrojs/sitemap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.4.1.tgz", - "integrity": "sha512-VjZvr1e4FH6NHyyHXOiQgLiw94LnCVY4v06wN/D0gZKchTMkg71GrAHJz81/huafcmavtLkIv26HnpfDq6/h/Q==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.4.2.tgz", + "integrity": "sha512-wfN2dZzdkto6yaMtOFa/J9gc60YE3wl3rgSBoNJ+MU3lJVUMsDY9xf9uAVi8Mp/zEQKFDSJlQzBvqQUpw0Hf6g==", "dev": true, "license": "MIT", "dependencies": { "sitemap": "^8.0.0", "stream-replace-string": "^2.0.0", - "zod": "^3.24.2" + "zod": "^3.24.4" } }, "node_modules/@astrojs/starlight": { @@ -1330,14 +1330,14 @@ } }, "node_modules/@cloudflare/unenv-preset": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.4.1.tgz", - "integrity": "sha512-70mk5GPv+ozJ5XcIhFpq4ps7HvQYu+As7vwasUy9LcBadsTcWA2iFis/7aFJmQehfKerDwVOHfMYpgTTC+u24Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.5.0.tgz", + "integrity": "sha512-CZe9B2VbjIQjBTyc+KoZcN1oUcm4T6GgCXoel9O7647djHuSRAa6sM6G+NdxWArATZgeMMbsvn9C50GCcnIatA==", "dev": true, "license": "MIT OR Apache-2.0", "peerDependencies": { - "unenv": "2.0.0-rc.17", - "workerd": "^1.20250521.0" + "unenv": "2.0.0-rc.19", + "workerd": "^1.20250722.0" }, "peerDependenciesMeta": { "workerd": { @@ -1346,18 +1346,18 @@ } }, "node_modules/@cloudflare/vitest-pool-workers": { - "version": "0.8.57", - "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.57.tgz", - "integrity": "sha512-06hDhqNlDdFROz9LzBVQJ7nfqIzUDh5G6SuBoo7TvpSXOI6cbBuAhnbX+SbGJrnPel9cpqe97Kx5m9KztEF90g==", + "version": "0.8.59", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.59.tgz", + "integrity": "sha512-ji3ALNMPNMAJqxi77B9tvng6QKs04Z883RkHwH6i0V9QbbXblKZDKsCmx9kCaDDuK8UwiBG6/+ug3JSp9wl9WQ==", "dev": true, "license": "MIT", "dependencies": { "birpc": "0.2.14", "cjs-module-lexer": "^1.2.3", "devalue": "^4.3.0", - "miniflare": "4.20250712.2", + "miniflare": "4.20250730.0", "semver": "^7.7.1", - "wrangler": "4.26.0", + "wrangler": "4.27.0", "zod": "^3.22.3" }, "peerDependencies": { @@ -1402,9 +1402,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250712.0.tgz", - "integrity": "sha512-M6S6a/LQ0Jb0R+g0XhlYi1adGifvYmxA5mD/i9TuZZgjs2bIm5ELuka/n3SCnI98ltvlx3HahRaHagAtOilsFg==", + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250730.0.tgz", + "integrity": "sha512-X3egNyTjLQaECYe34x8Al7r4oXAhcN3a8+8qcpNCcq1sgtuHIeAwS9potgRR/mwkGfmrJn7nfAyDKC4vrkniQQ==", "cpu": [ "x64" ], @@ -1419,9 +1419,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250712.0.tgz", - "integrity": "sha512-7sFzn6rvAcnLy7MktFL42dYtzL0Idw/kiUmNf2P3TvsBRoShhLK5ZKhbw+NAhvU8e4pXWm5lkE0XmpieA0zNjw==", + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250730.0.tgz", + "integrity": "sha512-/4bvcaGY/9v0rghgKboGiyPKKGQTbDnQ1EeY0oN0SSQH0Cp3OBzqwni/JRvh8TEaD+5azJnSFLlFZj9w7fo+hw==", "cpu": [ "arm64" ], @@ -1436,9 +1436,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250712.0.tgz", - "integrity": "sha512-EFRrGe/bqK7NHtht7vNlbrDpfvH3eRvtJOgsTpEQEysDjVmlK6pVJxSnLy9Hg1zlLY15IfhfGC+K2qisseHGJQ==", + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250730.0.tgz", + "integrity": "sha512-I4ZsXYdNkqkJnzNFKADMufiLIzRdIRsN7dSH8UCPw2fYp1BbKA10AkKVqitFwBxIY8eOzQ6Vf7c41AjLQmtJqA==", "cpu": [ "x64" ], @@ -1453,9 +1453,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250712.0.tgz", - "integrity": "sha512-rG8JUleddhUHQVwpXOYv0VbL0S9kOtR9PNKecgVhFpxEhC8aTeg2HNBBjo8st7IfcUvY8WaW3pD3qdAMZ05UwQ==", + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250730.0.tgz", + "integrity": "sha512-tTpO6139jFQ5vxgtBZgS8Y8R1jVidS4n7s37x5xO9bCWLZoL0kTj38UGZ8FENkTeaMxE9Mm//nbQol7TfJ2nZg==", "cpu": [ "arm64" ], @@ -1470,9 +1470,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250712.0.tgz", - "integrity": "sha512-qS8H5RCYwE21Om9wo5/F807ClBJIfknhuLBj16eYxvJcj9JqgAKWi12BGgjyGxHuJJjeoQ63lr4wHAdbFntDDg==", + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250730.0.tgz", + "integrity": "sha512-paVHgocuilMzOU+gEyKR/86j/yI+QzmSHRnqdd8OdQ37Hf6SyPX7kQj6VVNRXbzVHWix1WxaJsXfTGK1LK05wA==", "cpu": [ "x64" ], @@ -2383,9 +2383,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2420,9 +2420,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -2457,9 +2457,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", - "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true, "license": "MIT", "engines": { @@ -2479,13 +2479,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { @@ -2572,31 +2572,34 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", - "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", "dev": true, + "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", - "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz", + "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", "dev": true, + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.2", + "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react": { - "version": "0.27.13", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.13.tgz", - "integrity": "sha512-Qmj6t9TjgWAvbygNEu1hj4dbHI9CY0ziCMIJrmYoDIn9TUAH5lRmiIeZmRd4c6QEZkzdoH7jNnoNyoY1AIESiA==", + "version": "0.27.15", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.15.tgz", + "integrity": "sha512-0LGxhBi3BB1DwuSNQAmuaSuertFzNAerlMdPbotjTVnvPtdOs7CkrHLaev5NIXemhzDXNC0tFzuseut7cWA5mw==", "dev": true, + "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.1.4", + "@floating-ui/react-dom": "^2.1.5", "@floating-ui/utils": "^0.2.10", "tabbable": "^6.0.0" }, @@ -2606,12 +2609,13 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz", - "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.5.tgz", + "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==", "dev": true, + "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.7.2" + "@floating-ui/dom": "^1.7.3" }, "peerDependencies": { "react": ">=16.8.0", @@ -3295,22 +3299,22 @@ } }, "node_modules/@lottiefiles/dotlottie-react": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.14.3.tgz", - "integrity": "sha512-O917vzFmacyC/F1NM2CLBsHqCMUBPiyI9Vw0o3ZohbZzRJYbgHPhdOpL83wE3zWs9VNr0JSbmJrkkUwaQizTWQ==", + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.14.4.tgz", + "integrity": "sha512-HFaA9ttniLMDapYxRhui+YFKAOs1h/z1ILQCLYHhfXGOvETtoWqJpuKdSKeEsDFD4BhFjZRgEfRlPiGOEFikUg==", "dev": true, "license": "MIT", "dependencies": { - "@lottiefiles/dotlottie-web": "0.48.0" + "@lottiefiles/dotlottie-web": "0.49.0" }, "peerDependencies": { "react": "^17 || ^18 || ^19" } }, "node_modules/@lottiefiles/dotlottie-web": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-web/-/dotlottie-web-0.48.0.tgz", - "integrity": "sha512-gcS6/3NYcpD2VUi2413wrZmdNLPbtwPaXqoFBqioLW/GsI/oTpTqmunsliRb4BL1ECLAUu0YOzHyK73UXMHrRg==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-web/-/dotlottie-web-0.49.0.tgz", + "integrity": "sha512-SQ8sDrUrGMM24QWjs0n863SKobMSB9Plz8gbte9RYnLc4TfmQoWxjFgGBTlbGnh/aTQvtpxOxX2ueBohCsCaRQ==", "dev": true, "license": "MIT" }, @@ -5426,14 +5430,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.6.tgz", - "integrity": "sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==", + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.6", - "@vitest/utils": "2.1.6", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, @@ -5441,68 +5445,12 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/expect/node_modules/@vitest/pretty-format": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", - "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/expect/node_modules/@vitest/utils": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", - "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.6", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.6.tgz", - "integrity": "sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.6", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, "node_modules/@vitest/pretty-format": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tinyrainbow": "^1.2.0" }, @@ -5516,7 +5464,6 @@ "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" @@ -5531,7 +5478,6 @@ "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", @@ -5542,9 +5488,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.6.tgz", - "integrity": "sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==", + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5560,7 +5506,6 @@ "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", @@ -6102,8 +6047,8 @@ "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.12.2", - "@astrojs/internal-helpers": "0.6.1", - "@astrojs/markdown-remark": "6.3.3", + "@astrojs/internal-helpers": "0.7.1", + "@astrojs/markdown-remark": "6.3.5", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", @@ -6160,7 +6105,7 @@ "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", - "zod": "^3.24.2", + "zod": "^3.24.4", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, @@ -6277,14 +6222,21 @@ "unist-util-visit-parents": "^6.0.1" } }, + "node_modules/astro/node_modules/@astrojs/internal-helpers": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.1.tgz", + "integrity": "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/astro/node_modules/@astrojs/markdown-remark": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.3.tgz", - "integrity": "sha512-DDRtD1sPvAuA7ms2btc9A7/7DApKqgLMNrE6kh5tmkfy8utD0Z738gqd3p5aViYYdUtHIyEJ1X4mCMxfCfu15w==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.5.tgz", + "integrity": "sha512-MiR92CkE2BcyWf3b86cBBw/1dKiOH0qhLgXH2OXA6cScrrmmks1Rr4Tl0p/lFpvmgQQrP54Pd1uidJfmxGrpWQ==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.6.1", + "@astrojs/internal-helpers": "0.7.1", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", @@ -7038,9 +6990,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7236,9 +7188,9 @@ } }, "node_modules/chai": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", - "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", + "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", "dev": true, "license": "MIT", "dependencies": { @@ -7249,7 +7201,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -9382,9 +9334,9 @@ } }, "node_modules/eslint": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", - "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, "license": "MIT", "dependencies": { @@ -9394,8 +9346,8 @@ "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.31.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -9528,9 +9480,9 @@ } }, "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -9585,9 +9537,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -9648,19 +9600,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9678,9 +9617,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -10245,14 +10184,16 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -10540,9 +10481,9 @@ "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -12838,9 +12779,9 @@ } }, "node_modules/marked": { - "version": "16.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.1.tgz", - "integrity": "sha512-ij/2lXfCRT71L6u0M29tJPhP0bM5shLL3u5BePhFwPELj2blMJ6GDtD7PfJhRLhJ/c2UwrK17ySVcDzy2YHjHQ==", + "version": "16.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.2.tgz", + "integrity": "sha512-rNQt5EvRinalby7zJZu/mB+BvaAY2oz3wCuCjt1RDrWNpS1Pdf9xqMOeC9Hm5adBdcV/3XZPJpG58eT+WBc0XQ==", "dev": true, "license": "MIT", "bin": { @@ -14119,9 +14060,9 @@ } }, "node_modules/miniflare": { - "version": "4.20250712.2", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250712.2.tgz", - "integrity": "sha512-cZ8WyQBwqfjYLjd61fDR4/j0nAVbjB3Wxbun/brL9S5FAi4RlTR0LyMTKsIVA0s+nL4Pg9VjVMki4M/Jk2cz+Q==", + "version": "4.20250730.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250730.0.tgz", + "integrity": "sha512-avGXBStHQSqcJr8ra1mJ3/OQvnLZ49B1uAILQapAha1DHNZZvXWLIgUVre/WGY6ZOlNGFPh5CJ+dXLm4yuV3Jw==", "dev": true, "license": "MIT", "dependencies": { @@ -14133,7 +14074,7 @@ "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^7.10.0", - "workerd": "1.20250712.0", + "workerd": "1.20250730.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" @@ -14566,9 +14507,9 @@ } }, "node_modules/miniflare/node_modules/undici": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz", - "integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.13.0.tgz", + "integrity": "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA==", "dev": true, "license": "MIT", "engines": { @@ -15546,9 +15487,9 @@ "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -18450,9 +18391,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.21.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", - "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", "dev": true, "license": "MIT", "engines": { @@ -18467,14 +18408,14 @@ "license": "MIT" }, "node_modules/unenv": { - "version": "2.0.0-rc.17", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.17.tgz", - "integrity": "sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg==", + "version": "2.0.0-rc.19", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.19.tgz", + "integrity": "sha512-t/OMHBNAkknVCI7bVB9OWjUUAwhVv9vsPIAGnNUxnu3FxPQN11rjh0sksLMzc3g7IlTgvHmOTl4JM7JHpcv5wA==", "dev": true, "license": "MIT", "dependencies": { "defu": "^6.1.4", - "exsolve": "^1.0.4", + "exsolve": "^1.0.7", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" @@ -19059,9 +19000,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.6.tgz", - "integrity": "sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==", + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", "dev": true, "license": "MIT", "dependencies": { @@ -19069,648 +19010,2196 @@ "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", - "vite": "^5.0.0 || ^6.0.0" + "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-tsconfig-paths": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", - "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", + "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^3.0.3" - }, - "peerDependencies": { - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vitefu": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", - "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", + "node_modules/vite-node/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*" + "optional": true, + "os": [ + "android" ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } + "engines": { + "node": ">=12" } }, - "node_modules/vitest": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.6.tgz", - "integrity": "sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==", + "node_modules/vite-node/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.6", - "@vitest/mocker": "2.1.6", - "@vitest/pretty-format": "^2.1.6", - "@vitest/runner": "2.1.6", - "@vitest/snapshot": "2.1.6", - "@vitest/spy": "2.1.6", - "@vitest/utils": "2.1.6", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "2.1.6", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "2.1.6", - "@vitest/ui": "2.1.6", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } + "node": ">=12" } }, - "node_modules/vitest/node_modules/@vitest/pretty-format": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", - "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", + "node_modules/vite-node/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vitest/node_modules/@vitest/runner": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.6.tgz", - "integrity": "sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==", + "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vitest/utils": "2.1.6", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vitest/node_modules/@vitest/snapshot": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.6.tgz", - "integrity": "sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.6", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vitest/node_modules/@vitest/utils": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", - "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", + "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.6", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-css": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.62.tgz", - "integrity": "sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==", + "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-css-languageservice": "^6.3.0", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-emmet": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.62.tgz", - "integrity": "sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==", + "node_modules/vite-node/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@emmetio/css-parser": "^0.4.0", - "@emmetio/html-matcher": "^1.3.0", - "@vscode/emmet-helper": "^2.9.3", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-html": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.62.tgz", - "integrity": "sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==", + "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-html-languageservice": "^5.3.0", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-prettier": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.62.tgz", - "integrity": "sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==", + "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0", - "prettier": "^2.2 || ^3.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - }, - "prettier": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-typescript": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.62.tgz", - "integrity": "sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==", + "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "dependencies": { - "path-browserify": "^1.0.1", - "semver": "^7.6.2", - "typescript-auto-import-cache": "^0.3.3", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-nls": "^5.2.0", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-typescript-twoslash-queries": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.62.tgz", - "integrity": "sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==", + "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/volar-service-yaml": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.62.tgz", - "integrity": "sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==", + "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8", - "yaml-language-server": "~1.15.0" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-css-languageservice": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.2.tgz", - "integrity": "sha512-GEpPxrUTAeXWdZWHev1OJU9lz2Q2/PPBxQ2TIRmLGvQiH3WZbqaNoute0n0ewxlgtjzTW3AKZT+NHySk5Rf4Eg==", + "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "3.17.5", - "vscode-uri": "^3.0.8" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-html-languageservice": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.1.tgz", - "integrity": "sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==", + "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.0.8" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-json-languageservice": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz", - "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==", + "node_modules/vite-node/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.16.0", - "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "npm": ">=7.0.0" + "node": ">=12" } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=14.0.0" + "node": ">=12" } }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-nls": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "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==", + "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "node_modules/vite-node/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "node_modules/vite-node/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.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", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "node_modules/vite-tsconfig-paths": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "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==", + "node_modules/vitefu": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", + "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", "dev": true, "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "workspaces": [ + "tests/deps/*", + "tests/projects/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.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", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/volar-service-css": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.62.tgz", + "integrity": "sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-css-languageservice": "^6.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-emmet": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.62.tgz", + "integrity": "sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emmetio/css-parser": "^0.4.0", + "@emmetio/html-matcher": "^1.3.0", + "@vscode/emmet-helper": "^2.9.3", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-html": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.62.tgz", + "integrity": "sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-html-languageservice": "^5.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-prettier": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.62.tgz", + "integrity": "sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0", + "prettier": "^2.2 || ^3.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + }, + "prettier": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.62.tgz", + "integrity": "sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-browserify": "^1.0.1", + "semver": "^7.6.2", + "typescript-auto-import-cache": "^0.3.3", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-nls": "^5.2.0", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript-twoslash-queries": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.62.tgz", + "integrity": "sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-yaml": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.62.tgz", + "integrity": "sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8", + "yaml-language-server": "~1.15.0" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/vscode-css-languageservice": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.2.tgz", + "integrity": "sha512-GEpPxrUTAeXWdZWHev1OJU9lz2Q2/PPBxQ2TIRmLGvQiH3WZbqaNoute0n0ewxlgtjzTW3AKZT+NHySk5Rf4Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "3.17.5", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/vscode-html-languageservice": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.1.tgz", + "integrity": "sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/vscode-json-languageservice": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz", + "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + }, + "engines": { + "npm": ">=7.0.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-nls": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wolfy87-eventemitter": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", + "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerd": { + "version": "1.20250730.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250730.0.tgz", + "integrity": "sha512-w6e0WM2YGfYQGmg0dewZeLUYIxAzMYK1R31vaS4HHHjgT32Xqj0eVQH+leegzY51RZPNCvw5pe8DFmW4MGf8Fg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20250730.0", + "@cloudflare/workerd-darwin-arm64": "1.20250730.0", + "@cloudflare/workerd-linux-64": "1.20250730.0", + "@cloudflare/workerd-linux-arm64": "1.20250730.0", + "@cloudflare/workerd-windows-64": "1.20250730.0" + } + }, + "node_modules/wrangler": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.26.1.tgz", + "integrity": "sha512-zGFEtHrjTAWOngm+zwEvYCxFwMSIBrzHa3Yu6rAxYMEzsT8PPvo2rdswyUJiUkpE9s2Depr37opceaY7JxEYFw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.5.0", + "blake3-wasm": "2.1.5", + "esbuild": "0.25.4", + "miniflare": "4.20250726.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.19", + "workerd": "1.20250726.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20250726.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250726.0.tgz", + "integrity": "sha512-SOpQqQ2blLY0io/vErve44vJC1M5i7RHuMBdrdEPIEtxiLBTdOOVp4nqZ3KchocxZjskgTc2N4N3b5hNYuKDGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/wrangler/node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250726.0.tgz", + "integrity": "sha512-I+TOQ+YQahxL/K7eS2GJzv5CZzSVaZoyqfB15Q71MT/+wyzPCaFDTt+fg3uXdwpaIQEMUfqFNpTQSqbKHAYNgA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/wrangler/node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250726.0.tgz", + "integrity": "sha512-WSCv4o2uOW6b++ROVazrEW+jjZdBqCmXmmt7uVVfvjVxlzoYVwK9IvV2IXe4gsJ99HG9I0YCa7AT743cZ7TNNg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/wrangler/node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250726.0.tgz", + "integrity": "sha512-jNokAGL3EQqH+31b0dX8+tlbKdjt/0UtTLvgD1e+7bOD92lzjYMa/CixHyMIY/FVvhsN4TNqfiz4cqroABTlhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/wrangler/node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250726.0.tgz", + "integrity": "sha512-DiPTY63TNh6/ylvfutNQzYZi688x6NJDjQoqf5uiCp7xHweWx+GpVs42sZPeeXqCNvhm4dYjHjuigXJNh7t8Uw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.0.4" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "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.0.4" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "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.0.5" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.0.4" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "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.0.4" + } + }, + "node_modules/wrangler/node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "bin": { - "node-which": "bin/node-which" + "funding": { + "url": "https://opencollective.com/libvips" }, - "engines": { - "node": ">= 8" + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "node_modules/wrangler/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "node_modules/wrangler/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "node_modules/wrangler/node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" + "@emnapi/runtime": "^1.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/libvips" } }, - "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==", + "node_modules/wrangler/node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "node_modules/wrangler/node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/libvips" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "node_modules/wrangler/node_modules/miniflare": { + "version": "4.20250726.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250726.0.tgz", + "integrity": "sha512-7+/RQQ9dNsyGfR2XN2RDLultf7HHrJ5YltSXSeyQGUpzGU3iYlFhh9Smg+ygkkOJ3+trf0bgwixOnqnnWpc9ZQ==", "dev": true, "license": "MIT", "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "^7.10.0", + "workerd": "1.20250726.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "3.22.3" }, "bin": { - "why-is-node-running": "cli.js" + "miniflare": "bootstrap.js" }, "engines": { - "node": ">=8" + "node": ">=18.0.0" } }, - "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==", + "node_modules/wrangler/node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "string-width": "^7.0.0" + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" } }, - "node_modules/wolfy87-eventemitter": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", - "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==", - "dev": true, - "license": "Unlicense" - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/wrangler/node_modules/undici": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz", + "integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=20.18.1" } }, - "node_modules/workerd": { - "version": "1.20250712.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250712.0.tgz", - "integrity": "sha512-7h+k1OxREpiZW0849g0uQNexRWMcs5i5gUGhJzCY8nIx6Tv4D/ndlXJ47lEFj7/LQdp165IL9dM2D5uDiedZrg==", + "node_modules/wrangler/node_modules/workerd": { + "version": "1.20250726.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250726.0.tgz", + "integrity": "sha512-wDZqSKfIfQ2eVTUL6UawXdXEKPPyzRTnVdbhoKGq3NFrMxd+7v1cNH92u8775Qo1zO5S+GyWonQmZPFakXLvGw==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -19721,46 +21210,21 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20250712.0", - "@cloudflare/workerd-darwin-arm64": "1.20250712.0", - "@cloudflare/workerd-linux-64": "1.20250712.0", - "@cloudflare/workerd-linux-arm64": "1.20250712.0", - "@cloudflare/workerd-windows-64": "1.20250712.0" + "@cloudflare/workerd-darwin-64": "1.20250726.0", + "@cloudflare/workerd-darwin-arm64": "1.20250726.0", + "@cloudflare/workerd-linux-64": "1.20250726.0", + "@cloudflare/workerd-linux-arm64": "1.20250726.0", + "@cloudflare/workerd-windows-64": "1.20250726.0" } }, - "node_modules/wrangler": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.26.0.tgz", - "integrity": "sha512-EXuwyWlgYQZv6GJlyE0lVGk9hHqASssuECECT1XC5aIijTwNLQhsj/TOZ0hKSFlMbVr1E+OAdevAxd0kaF4ovA==", + "node_modules/wrangler/node_modules/zod": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", "dev": true, - "license": "MIT OR Apache-2.0", - "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.0", - "@cloudflare/unenv-preset": "2.4.1", - "blake3-wasm": "2.1.5", - "esbuild": "0.25.4", - "miniflare": "4.20250712.2", - "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.17", - "workerd": "1.20250712.0" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20250712.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/wrap-ansi": { @@ -20134,9 +21598,9 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index 461e8b01ccf19d8..1a2e4ddc7fe1c2c 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@astrojs/check": "0.9.4", "@astrojs/react": "4.2.5", "@astrojs/rss": "4.0.12", - "@astrojs/sitemap": "3.4.1", + "@astrojs/sitemap": "3.4.2", "@astrojs/starlight": "0.35.1", "@astrojs/starlight-docsearch": "0.6.0", "@astrojs/starlight-tailwind": "4.0.1", @@ -40,7 +40,7 @@ "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.41.3", "@expressive-code/plugin-line-numbers": "0.41.3", - "@floating-ui/react": "0.27.13", + "@floating-ui/react": "0.27.15", "@iarna/toml": "2.2.5", "@lottiefiles/dotlottie-react": "0.14.4", "@marsidev/react-turnstile": "1.3.0", @@ -67,7 +67,7 @@ "dedent": "1.6.0", "dompurify": "3.2.6", "dot-prop": "9.0.0", - "eslint": "9.31.0", + "eslint": "9.32.0", "eslint-plugin-astro": "1.3.1", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", @@ -82,7 +82,7 @@ "jsonc-parser": "3.3.1", "ldrs": "1.1.7", "lz-string": "1.5.0", - "marked": "16.1.1", + "marked": "16.1.2", "mdast-util-from-markdown": "2.0.2", "mdast-util-mdx": "3.0.0", "mdast-util-mdx-expression": "2.0.1", @@ -133,8 +133,8 @@ "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", - "vitest": "2.1.6", - "wrangler": "4.26.0" + "vitest": "2.1.9", + "wrangler": "4.26.1" }, "engines": { "node": ">=22" From 5ae2c24493ac209a0f55f3c1601b410696932ed7 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 14:38:38 -0400 Subject: [PATCH 46/79] fix package.json files --- package-lock.json | 1363 ++++++++------------------------------------- package.json | 2 +- 2 files changed, 236 insertions(+), 1129 deletions(-) diff --git a/package-lock.json b/package-lock.json index a3b17382c116b9b..aae1523e055890f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,7 +115,7 @@ "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", - "vitest": "2.1.9", + "vitest": "2.1.6", "wrangler": "4.26.1" }, "engines": { @@ -184,9 +184,9 @@ } }, "node_modules/@actions/http-client/node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", + "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", "dev": true, "license": "MIT", "dependencies": { @@ -2420,9 +2420,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -5430,14 +5430,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", - "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.6.tgz", + "integrity": "sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", + "@vitest/spy": "2.1.6", + "@vitest/utils": "2.1.6", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, @@ -5445,12 +5445,68 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/expect/node_modules/@vitest/pretty-format": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", + "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/@vitest/utils": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", + "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.6", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.6.tgz", + "integrity": "sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.6", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, "node_modules/@vitest/pretty-format": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tinyrainbow": "^1.2.0" }, @@ -5464,6 +5520,7 @@ "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" @@ -5478,6 +5535,7 @@ "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", @@ -5488,9 +5546,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", - "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.6.tgz", + "integrity": "sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5506,6 +5564,7 @@ "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", @@ -6990,9 +7049,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -7188,9 +7247,9 @@ } }, "node_modules/chai": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", - "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, "license": "MIT", "dependencies": { @@ -7201,7 +7260,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/chalk": { @@ -9480,9 +9539,9 @@ } }, "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -9537,9 +9596,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -9617,9 +9676,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -10184,16 +10243,14 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -10481,9 +10538,9 @@ "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -15487,9 +15544,9 @@ "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "license": "MIT", "engines": { @@ -18391,9 +18448,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", "dev": true, "license": "MIT", "engines": { @@ -19000,9 +19057,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", - "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.6.tgz", + "integrity": "sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==", "dev": true, "license": "MIT", "dependencies": { @@ -19010,1128 +19067,178 @@ "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", - "vite": "^5.0.0" + "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/vite-tsconfig-paths": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", + "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/vite-node/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/vitefu": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", + "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" + "workspaces": [ + "tests/deps/*", + "tests/projects/*" ], - "engines": { - "node": ">=12" + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/vite-node/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], + "node_modules/vitest": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.6.tgz", + "integrity": "sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@vitest/expect": "2.1.6", + "@vitest/mocker": "2.1.6", + "@vitest/pretty-format": "^2.1.6", + "@vitest/runner": "2.1.6", + "@vitest/snapshot": "2.1.6", + "@vitest/spy": "2.1.6", + "@vitest/utils": "2.1.6", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "2.1.6", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, "engines": { - "node": ">=12" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "2.1.6", + "@vitest/ui": "2.1.6", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/vitest/node_modules/@vitest/pretty-format": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", + "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/vitest/node_modules/@vitest/runner": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.6.tgz", + "integrity": "sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@vitest/utils": "2.1.6", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/vitest/node_modules/@vitest/snapshot": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.6.tgz", + "integrity": "sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@vitest/pretty-format": "2.1.6", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite-node/node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.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", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-tsconfig-paths": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", - "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^3.0.3" - }, - "peerDependencies": { - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", - "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", - "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@vitest/mocker": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", - "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "node_modules/vitest/node_modules/@vitest/utils": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", + "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "@vitest/pretty-format": "2.1.6", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vitest/node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.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", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } } }, "node_modules/volar-service-css": { diff --git a/package.json b/package.json index 1a2e4ddc7fe1c2c..e9d180b9b8c521c 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,7 @@ "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", - "vitest": "2.1.9", + "vitest": "2.1.6", "wrangler": "4.26.1" }, "engines": { From 51d32810e37451b950f194e21b42d49f9738a8c8 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 17:01:25 -0400 Subject: [PATCH 47/79] update mwan and warpconn prereq --- .../gateway/egress-selector-onramps.mdx | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx index 85f6b5f9321d8bb..b0c914c878b4f18 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -3,23 +3,31 @@ --- +import { Render, Details, GlossaryTooltip } from "~/components" + | On-ramp method | Compatibility | | ------------------------------------------------------------------------------------------ | ------------- | | [WARP](/cloudflare-one/connections/connect-devices/warp/) | βœ… | | [PAC files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) | βœ… | | [Browser Isolation](/cloudflare-one/policies/browser-isolation/) | βœ… | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | 🚧[^1] | | [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | βœ… | +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | 🚧[^1] | [^1]: Not compatible with [ECMP routing](/magic-wan/reference/traffic-steering/#equal-cost-multi-path-routing). For hostname-based routing to work, DNS queries and the resulting network traffic must reach Cloudflare over the same Magic WAN tunnel.
-:::note[WARP Connector and Magic WAN] -DNS traffic to the Gateway resolver must route through Cloudflare's network instead of over the public Internet. If your devices are behind WARP Connector, you may need to [configure your router](/cloudflare-one/connections/connect-networks/private-net/warp-connector/site-to-internet/#3-route-traffic-from-subnet-to-warp-connector) to route the Gateway resolver IPs through WARP Connector. If your devices are behind Magic WAN, [create a route](/magic-wan/configuration/manually/how-to/configure-routes/) to route the Gateway resolver IPs through the Magic WAN tunnel. +
+If devices are behind WARP Connector or Magic WAN, you may need to update the routing table on your device or router to send traffic to Gateway. Ensure that traffic to the following destination IPs route through WARP Connector / Magic WAN: + +- Initial resolved IP CGNAT range: + +- Private network CIDR where the application is located (for example, `10.0.0.0/8`) +- Internal DNS resolver IP +- Gateway resolver IPs: + - `172.64.36.1` + - `172.64.36.2` -The Gateway resolver IPs are: +Additionally, ensure that your local DNS resolver points to the Gateway resolver IPs listed above. -- `172.64.36.1` -- `172.64.36.2` +
-::: \ No newline at end of file From b201f494556e7edf3cc333362f7bd2a7cab9c521 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 17:06:41 -0400 Subject: [PATCH 48/79] add link to CF blog --- .../private-net/cloudflared/connect-private-hostname.mdx | 2 -- .../policies/gateway/egress-policies/egress-cloudflared.mdx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 96e1a74b8bddd87..214e43544db1772 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -43,8 +43,6 @@ As shown in Figure 2 below, the WARP client will now send `wiki.internal.local` The initial resolved IP mechanism is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. Because the packet's destination IP falls within the designated CGNAT range, Gateway knows that it corresponds to a hostname route and can apply hostname-based policies. Traffic that passes your Gateway policies will route through Cloudflare Tunnel to the application's actual origin IP. When the initial resolved IP expires, WARP will send a new DNS request (Figure 1) to refresh the initial resolved IP. -To learn more about hostname routing, refer to the [Cloudflare blog](). - ## Connect to a private hostname This section covers how to enable remote access to a private hostname application using `cloudflared` and WARP. diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index f6a26368aa041b6..d0fc8ce36319ddc 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -33,7 +33,7 @@ For example, assume that your organization's banking service, `app.bank.com`, ex aws--AWS egress IP -->app ``` -To learn more about how Gateway applies hostname-based policies, refer to the [Cloudflare blog](). +To learn more about how Gateway applies hostname-based egress policies, refer to the [Cloudflare blog](https://blog.cloudflare.com/egress-policies-by-hostname/). ## Prerequisites From 3e9aba74deddb9680d4418cf3020debc7ed17870 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 18:23:23 -0400 Subject: [PATCH 49/79] add local domain fallback --- .../cloudflared/connect-private-hostname.mdx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 214e43544db1772..198ee6afd8e4ab0 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -98,7 +98,11 @@ Configure Gateway to resolve the private hostname using your internal DNS resolv ### 5. Route traffic through WARP -In your [device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), [configure Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: +This section details routing requirements for WARP client deployments. For information about WARP Connector and other connectivity methods, refer to [Supported on-ramps](#device-connectivity). + +#### Split Tunnels + +In your WARP [device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure [Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the following IPs route through the WARP tunnel: - Initial resolved IP CGNAT range: @@ -107,6 +111,10 @@ In your [device profiles](/cloudflare-one/connections/connect-devices/warp/confi For more details on configuring Split Tunnels, refer to [Route private network IPs through WARP](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). +#### Local Domain Fallback + +By default, the WARP client uses the local DNS resolver on the device to resolve common local domains (such as `.internal` and `local`). These top-level domains are on your [Local Domain Fallback](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) list and bypass the Gateway resolver. To resolve a private hostname with Gateway, [delete its domain](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/#delete-a-domain) from Local Domain Fallback. + ### 6. (Recommended) Filter network traffic with Gateway @@ -174,6 +182,10 @@ If you [enabled the Gateway proxy](#enable-the-gateway-proxy), you can view the ### Troubleshooting +:::note +Routing issues are the most common type of misconfiguration. Make sure to check WARP Split Tunnels and Local Domain Fallback as described in [Step 5](#5-route-traffic-through-warp). +::: + For a step-by-step troubleshooting procedure, refer to [Troubleshoot private network connectivity](/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/private-networks/). ## Supported on-ramps/off-ramps From 5eeea8958b4498a99cdfaed09d45e3520daf087b Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Thu, 14 Aug 2025 18:33:39 -0400 Subject: [PATCH 50/79] fix steps component --- .../hyperdrive/configuration/connect-to-private-database.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx index a06ce50ba15206e..19dc3f046a86e36 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -53,7 +53,6 @@ Your tunnel must be configured to use a public hostname on Cloudflare so that Hy 2. In the **Service** section, specify **Type** `TCP` and the URL and configured port of your database, such as `localhost:5432` or `my-database-host.database-provider.com:5432`. This address will be used by the tunnel to route requests to your database. 3. Select **Save tunnel**. - :::note If you are setting up the tunnel through the CLI instead ([locally-managed tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/)), you will have to complete these steps manually. Follow the Cloudflare Zero Trust documentation to [add a public hostname to your tunnel](/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns/) and [configure the public hostname to route to the address of your database](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). From 34b22983a70f6125d1df113bc052b97d77190fc7 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 15 Aug 2025 17:10:45 -0400 Subject: [PATCH 51/79] refine wording --- .../cloudflared/connect-private-hostname.mdx | 61 ++++++++++++++----- .../egress-policies/egress-cloudflared.mdx | 27 +++++--- .../gateway/egress-selector-onramps.mdx | 16 ----- .../gateway/egress-selector-split-tunnels.mdx | 2 +- 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 198ee6afd8e4ab0..494ef6ebf5c94d7 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -9,18 +9,18 @@ sidebar: import { Render, Details, GlossaryTooltip } from "~/components"; -`cloudflared` can route to HTTP and non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. - -:::note[Only available on Enterprise plans] -Hostname routes currently require Gateway resolver policies, an Enterprise-only feature. If you are on a Free or Pay-as-you-go plan, you will need to connect the application using [IP routes](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/). +:::note[Availability] +Hostname routes are currently available in closed beta to Enterprise customers. To request access, contact your account team. ::: +`cloudflared` can route to HTTP and non-HTTP applications on your private network using their private hostname (for example, `wiki.internal.local`). Private hostname routes are especially useful when the application has an unknown or ephemeral IP, which often occurs when infrastructure is provisioned by a third-party cloud provider. + ## How private hostname routing works Private hostname routing with Cloudflare Tunnel consists of three main components: - The WARP client installs on the user device and forwards network and DNS traffic from the device to Cloudflare Gateway. -- Gateway resolver policies instruct Gateway to resolve the private hostname using your internal DNS resolver instead of the default public resolver. +- Gateway resolves the private hostname using your internal DNS resolver instead of the default public resolver. - `cloudflared` installs on a host machine in your private network and proxies traffic from Cloudflare to your internal DNS resolver and internal applications. Figures 1 and 2 illustrate the flow of DNS and network traffic when a user connects to a private hostname (`wiki.internal.local`): @@ -28,7 +28,7 @@ Figures 1 and 2 illustrate the flow of DNS and network traffic when a user conne ![Figure 1: DNS resolution for a private hostname](~/assets/images/cloudflare-one/connections/private-hostname-route-1.png "Figure 1: DNS resolution for private hostname") 1. The WARP client sends the DNS query to the Gateway resolver for resolution. -2. Based on the configured resolver policies, Gateway determines that `wiki.internal.local` should be resolved by a custom DNS resolver. +2. Gateway determines that `wiki.internal.local` should be resolved by a custom DNS resolver. 3. Gateway does a DNS lookup for `wiki.internal.local` through Cloudflare Tunnel, and the custom DNS resolver returns the origin IP (`10.0.0.5`). 4. Rather than responding to the DNS query with the actual origin IP, Gateway responds with a random IP address from the following CGNAT range: @@ -76,9 +76,13 @@ To route your internal DNS resolver through Cloudflare Tunnel: 5. Select **Create route**. -### 3. Create a resolver policy +### 3. (Optional) Create a resolver policy + +:::note +Only available on Enterprise plans +::: -Configure Gateway to resolve the private hostname using your internal DNS resolver: +Gateway will automatically resolve DNS queries using your internal DNS server as long as the DNS server is behind the same Cloudflare Tunnel as your application. If your DNS server is behind a different Cloudflare Tunnel (for example, if you separated DNS traffic into its own tunnel for [high availability](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/#private-dns)), then you need to point Gateway to the correct tunnel and DNS server. 1. [Create a Gateway resolver policy](/cloudflare-one/policies/gateway/resolver-policies/#create-a-resolver-policy) that matches the private hostname for which you are establishing the route: @@ -86,9 +90,9 @@ Configure Gateway to resolve the private hostname using your internal DNS resolv | -------- | -------- | ---------------------- | | Host | in | `wiki.internal.local` | -2. Under **Configure custom DNS resolvers**, enter the IPv4 and/or IPv6 address of your internal DNS resolver. The dropdown menu will not populate until you type in the full IP address. +2. Under **Configure custom DNS resolvers**, enter the IPv4 and/or IPv6 address of your internal DNS server. The dropdown menu will not populate until you type in the full IP address. -3. From the dropdown menu, select the `- Private` routing option and the [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) where the DNS resolver is located. +3. From the dropdown menu, select the `- Private` routing option and the [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) where the DNS server is located. ### 4. Set up the client @@ -176,13 +180,23 @@ Access policies and Gateway network policies only support hostname-based filteri ### 7. Test the connection -End users can now reach the application by going to its private hostname. For example, to test an HTTP application, open a browser and go to `wiki.internal.local`. +End users can now reach the application by going to its private hostname. For example, to test an HTTP application, open a terminal on a WARP device and run +```sh +curl -v4 http://wiki.internal.local +``` +```sh output +* Trying 100.80.77.135:80... +* Connected to wiki.internal.local (100.80.77.135) port 80 +... +``` + +The output should show a successful connection to an initial resolved IP. -If you [enabled the Gateway proxy](#enable-the-gateway-proxy), you can view the traffic in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). +If you [enabled the Gateway proxy](#enable-the-gateway-proxy), you can view the traffic in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). You can also check your [tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing to the application. ### Troubleshooting -:::note +:::note[Common misconfigurations] Routing issues are the most common type of misconfiguration. Make sure to check WARP Split Tunnels and Local Domain Fallback as described in [Step 5](#5-route-traffic-through-warp). ::: @@ -198,17 +212,32 @@ The table below summarizes the Cloudflare One products that are compatible with ### Device connectivity -End users can connect to private hostnames from the following device on-ramps: +End users can connect to private hostnames using the following traffic on-ramps: +#### WARP Connector and Magic WAN routes + +If devices are behind WARP Connector or Magic WAN, you may need to update the routing table on your device or router to send traffic to Gateway. Ensure that traffic to the following destination IPs route through WARP Connector / Magic WAN: + + - Initial resolved IP CGNAT range: + + - Private network CIDR where the application is located (for example, `10.0.0.0/8`) + - Internal DNS resolver IP + - Gateway DNS resolver IPs: + - `172.64.36.1` + - `172.64.36.2` + :::note + Magic WAN customers will also need to configure their DNS resolver to point to these Gateway resolver IPs. + ::: + ### Private network connectivity -To route to private applications using hostnames instead of IPs, connect your infrastructure to Cloudflare using a supported traffic off-ramp: +Private hostname routing only works for applications connected with `cloudflared`. Other traffic off-ramps require IP-based routes. | Connector | Compatibility | | ------------------------------------------------------------------------------------------ | ------------- | | [cloudflared](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) | βœ… | | [WARP-to-WARP](/cloudflare-one/connections/connect-networks/private-net/warp-to-warp/) | ❌ | | [WARP Connector](/cloudflare-one/connections/connect-networks/private-net/warp-connector/) | ❌ | -| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | \ No newline at end of file +| [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) | ❌ | diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index d0fc8ce36319ddc..6467ade2d0b1e8f 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -9,6 +9,10 @@ sidebar: import { Render, Details, GlossaryTooltip } from "~/components"; +:::note[Availability] +Hostname routes are currently available in closed beta to Enterprise customers. To request access, contact your account team. +::: + Cloudflare Tunnel can be used for source IP anchoring when you want to use existing egress IPs instead of purchasing [Cloudflare dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Some third-party websites may have an Access Control List (ACL) that only allow connections from certain source IPs. If you already a non-Cloudflare IP on their allowlist (such an egress IP provided by an ISP or a cloud provider like AWS), you can configure `cloudflared` to anchor user traffic to the same IPs that you use today. @@ -61,23 +65,22 @@ To route a public hostname through Cloudflare Tunnel: ## 3. Route network traffic through WARP -If your traffic is onboarded using WARP, ensure that traffic to the following IP addresses route through the WARP tunnel to Gateway: +In your WARP [Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) configuration, route the following IP addresses through the WARP tunnel to Gateway. -- Initial resolved IP CGNAT range: - -- Private network CIDR block +### Initial resolved IPs -### Route initial resolved IPs +When users connect to a public hostname route, Gateway will assign an initial resolved IP to the DNS query from the following range: + -When users connect to a public hostname route, Gateway will assign an initial resolved IP to the DNS query. The initial resolved IP is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If a packet's destination IP falls within the initial resolved IP CGNAT range, Gateway knows that the IP maps to a public hostname route and sends the traffic down the corresponding Cloudflare Tunnel. +The initial resolved IP is required because Gateway's network engine operates at L3/L4 and can only see IPs (not hostnames) when processing the connection. If a packet's destination IP falls within the initial resolved IP CGNAT range, Gateway knows that the IP maps to a public hostname route and sends the traffic down the corresponding Cloudflare Tunnel. To route initial resolved IPs through WARP: -### Route private network IPs +### Private network IPs -To route your private network's CIDR block through WARP, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). +Your private network's CIDR block should also route through the WARP tunnel. For a detailed configuration example, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). ## 4. (Optional) Configure network policies @@ -92,4 +95,10 @@ You can build [Gateway network policies](/cloudflare-one/policies/gateway/networ | -------------- | -------- | ------------ | ------ | | SNI | in | `app.bank.com` | Block | -Gateway does not currently support hostname-based filtering for traffic on non-443 ports. To block traffic to `app.bank.com` on all ports, you will need to use the [Destination IP](/cloudflare-one/policies/gateway/network-policies/#destination-ip) selector and specify the public IP space of `app.bank.com`. \ No newline at end of file +Gateway does not currently support hostname-based filtering for traffic on non-443 ports. To block traffic to `app.bank.com` on all ports, you will need to use the [Destination IP](/cloudflare-one/policies/gateway/network-policies/#destination-ip) selector and specify the public IP space of `app.bank.com`. + +## 5. Test the connection + +From a WARP device, open a browser and go to `app.bank.com`. + +The traffic will appear in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/); Gateway DNS logs will show that `app.bank.com` resolved to an initial resolved IP, and network logs will show requests destined to that initial resolved IP. You can also check [`cloudflared` logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing to the tunnel. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx index b0c914c878b4f18..1c643d11f0e652f 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-onramps.mdx @@ -15,19 +15,3 @@ import { Render, Details, GlossaryTooltip } from "~/components" [^1]: Not compatible with [ECMP routing](/magic-wan/reference/traffic-steering/#equal-cost-multi-path-routing). For hostname-based routing to work, DNS queries and the resulting network traffic must reach Cloudflare over the same Magic WAN tunnel.
- -
-If devices are behind WARP Connector or Magic WAN, you may need to update the routing table on your device or router to send traffic to Gateway. Ensure that traffic to the following destination IPs route through WARP Connector / Magic WAN: - -- Initial resolved IP CGNAT range: - -- Private network CIDR where the application is located (for example, `10.0.0.0/8`) -- Internal DNS resolver IP -- Gateway resolver IPs: - - `172.64.36.1` - - `172.64.36.2` - -Additionally, ensure that your local DNS resolver points to the Gateway resolver IPs listed above. - -
- diff --git a/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx index d9be7a4423551c0..d2a69bb522880e0 100644 --- a/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx +++ b/src/content/partials/cloudflare-one/gateway/egress-selector-split-tunnels.mdx @@ -4,7 +4,7 @@ --- import { Tabs, TabItem, Render } from "~/components" -In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure your [Split Tunnel](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) depending on the mode: +In your WARP [device profile](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/), configure [Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) depending on the mode: From bdb99c45801336a9eaaae157868322784617b6b0 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 15 Aug 2025 17:12:53 -0400 Subject: [PATCH 52/79] update private network tab name --- .../connections/connect-networks/deployment-guides/aws.mdx | 2 +- .../deployment-guides/google-cloud-platform.mdx | 2 +- .../connect-networks/get-started/create-remote-tunnel.mdx | 2 +- .../connect-networks/private-net/cloudflared/connect-cidr.mdx | 2 +- .../private-net/cloudflared/tunnel-virtual-networks.mdx | 2 +- .../connections/connect-networks/use-cases/grpc.mdx | 2 +- .../connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx | 2 +- .../connections/connect-networks/use-cases/smb.mdx | 2 +- .../connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx | 2 +- .../cloudflare-one/tutorials/clientless-access-private-dns.mdx | 2 +- .../docs/cloudflare-one/tutorials/mysql-network-policy.mdx | 2 +- .../replace-vpn/connect-private-network/cloudflared.mdx | 2 +- .../tunnel/connect-private-network-infra-access.mdx | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx index e5bd9513a219165..49465fe2bf66b98 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx @@ -98,7 +98,7 @@ EOF [Private network routes](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) allow users to connect to your virtual private cloud (VPC) using the WARP client. To add a private network route for your Cloudflare Tunnel: -1. In the **Private Networks** tab, enter the **Private IPv4 address** of your AWS instance (for example, `172.31.19.0`). You can expand the IP range later if necessary. +1. In the **CIDR** tab, enter the **Private IPv4 address** of your AWS instance (for example, `172.31.19.0`). You can expand the IP range later if necessary. 2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the private IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `172.16.0.0/12`. We recommend re-adding the IPs that are not explicitly used by your AWS instance. To determine which IP addresses to re-add, subtract your AWS instance IPs from `172.16.0.0/12`: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx index d3abdd73fbdafc9..a3cd634f1a69da6 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx @@ -77,7 +77,7 @@ To complete the following procedure, you will need to: To configure a private network route for your Cloudflare Tunnel: -1. In the **Private Networsk** tab, enter the **Internal IP** of your GCP VM instance (for example, `10.0.0.2`). You can expand the IP range later if necessary. +1. In the **CIDR** tab, enter the **Internal IP** of your GCP VM instance (for example, `10.0.0.2`). You can expand the IP range later if necessary. 2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the internal IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `10.0.0.0/8`. We recommend re-adding the IPs that are not explicitly used by your GCP VM. To determine which IP addresses to re-add, subtract your GCP instance IPs from `10.0.0.0/8`: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx index c3e5e7a742bb56e..c2fe346aac31499 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx @@ -32,7 +32,7 @@ Anyone on the Internet can now access the application at the specified hostname. To connect a private network through your tunnel: -1. Go to the **Private networks** tab. +1. Go to the **CIDR** tab. 2. In **CIDR**, enter the private IP address or CIDR range of your service (for example, `10.0.0.1` or `10.0.0.0/8`). `cloudflared` can now route traffic to these destination IPs. To configure Zero Trust policies and connect as a user, refer to [Connect an IP/CIDR](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx index d015c49fb97a3e3..096c3eacae74347 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr.mdx @@ -15,7 +15,7 @@ To connect your infrastructure with Cloudflare Tunnel: -2. In the **Private Networks** tab for the tunnel, enter the IP/CIDR range that you wish to route through the tunnel (for example `10.0.0.0/8`). +2. In the **CIDR** tab for the tunnel, enter the IP/CIDR range that you wish to route through the tunnel (for example `10.0.0.0/8`). ## 2. Set up the client diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx index 67705af0a366f55..748071559f7a1f2 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx @@ -60,7 +60,7 @@ The following example demonstrates how to add two overlapping IP routes to Cloud 2. Select **Create a tunnel**. 3. Name your tunnel `Staging tunnel` and select **Save tunnel**. 4. Install the connector within your staging environment. - 5. In the **Private Networks** tab, add `10.128.0.1/32`. + 5. In the **CIDR** tab, add `10.128.0.1/32`. 6. Select **Additional settings**. Under **Virtual networks**, select *staging-vnet*. 7. Save the tunnel. 8. Repeat Steps 2a-2g to create another tunnel called `Production tunnel`. Be sure to install the connector within your production environment and assign the route to *production-vnet*. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx index e2813000b24eea1..af7f4a2d6648765 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx @@ -34,7 +34,7 @@ To establish a secure, outbound-only connection to Cloudflare: -2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. +2. In the **CIDR** tab for the tunnel, enter the private IP or CIDR address of your server. ## 3. Route private network IPs through WARP diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx index b4cf0deff5f042c..f02cbabfe7be291 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx @@ -52,7 +52,7 @@ By default, Internet Explorer will be installed and configured in [Enhanced Secu -2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. +2. In the **CIDR** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. 3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx index 235f5cc4c73cfc0..a4e061f10f147d2 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx @@ -26,7 +26,7 @@ You can use Cloudflare Tunnel to create a secure, outbound-only connection from -2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. +2. In the **CIDR** tab for the tunnel, enter the private IP or CIDR address of your server. 3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. ### 2. Set up the client diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx index 3866ba385beb7ad..786b7c1a8378220 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx @@ -61,7 +61,7 @@ In order to be able to establish an SSH connection, do not enable [OS Login](htt -2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. +2. In the **CIDR** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. 3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. diff --git a/src/content/docs/cloudflare-one/tutorials/clientless-access-private-dns.mdx b/src/content/docs/cloudflare-one/tutorials/clientless-access-private-dns.mdx index 0d3ecbd77d26921..0861aa44eed052a 100644 --- a/src/content/docs/cloudflare-one/tutorials/clientless-access-private-dns.mdx +++ b/src/content/docs/cloudflare-one/tutorials/clientless-access-private-dns.mdx @@ -25,7 +25,7 @@ First, install `cloudflared` on a server in your private network: ## Add private network routes -1. In the **Private Networks** tab, add the following IP addresses: +1. In the **CIDR** tab, add the following IP addresses: - Private IP/CIDR of your application server (for example, `10.128.0.175/32`) - Private IP/CIDR of your DNS server diff --git a/src/content/docs/cloudflare-one/tutorials/mysql-network-policy.mdx b/src/content/docs/cloudflare-one/tutorials/mysql-network-policy.mdx index 9817e4015f19d4e..2e4449d7c28947f 100644 --- a/src/content/docs/cloudflare-one/tutorials/mysql-network-policy.mdx +++ b/src/content/docs/cloudflare-one/tutorials/mysql-network-policy.mdx @@ -26,7 +26,7 @@ Install `cloudflared` on a server in your private network. This server should ha ## Add private network routes -1. In the **Private Networks** tab, add the following IP addresses: +1. In the **CIDR** tab, add the following IP addresses: - Private IP/CIDR of your MySQL server (for example, `10.128.0.175/32`) - (Optional) Private IP/CIDR of your internal DNS server diff --git a/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx b/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx index 948b6e68733db2b..1cb7f55f722866f 100644 --- a/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx +++ b/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx @@ -20,7 +20,7 @@ To connect your private network: -9. In the **Private Networks** tab, enter the CIDR of your private network (for example, `10.0.0.0/8`). +9. In the **CIDR** tab, enter the CIDR of your private network (for example, `10.0.0.0/8`). 10. Select **Save tunnel**. diff --git a/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx b/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx index 5b5bc56a5f07b77..6b12ed7d60909da 100644 --- a/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx +++ b/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx @@ -2,4 +2,4 @@ {} --- -2. In the **Private Networks** tab for the tunnel, enter the IP or CIDR address of your server. Typically this would be a private IP, but public IPs are also allowed. +2. In the **CIDR** tab for the tunnel, enter the IP or CIDR address of your server. Typically this would be a private IP, but public IPs are also allowed. From 76e8eb18d3a499f29d8a097b9e78c0c76463c9ab Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 15 Aug 2025 17:19:57 -0400 Subject: [PATCH 53/79] update published applications tab name --- .../configure-tunnels/cloudflared-parameters/index.mdx | 2 +- .../use-cases/rdp/rdp-cloudflared-authentication.mdx | 2 +- .../connections/connect-networks/use-cases/smb.mdx | 2 +- .../hyperdrive/configuration/connect-to-private-database.mdx | 2 +- .../partials/cloudflare-one/ssh/tunnel-public-hostname.mdx | 2 +- .../partials/cloudflare-one/tunnel/add-public-hostname.mdx | 2 +- .../partials/cloudflare-one/tunnel/cloud-public-hostname.mdx | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx index 33cebe3c4315b02..1af13d5fd49f913 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx @@ -144,7 +144,7 @@ To configure how `cloudflared` sends requests to your [published applications](/ 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. 2. Choose a tunnel and select **Configure**. -3. Select the **Published applications** tab. +3. Select the **Published application routes** tab. 4. Choose an application and select **Edit**. 5. Under **Additional application settings**, modify one or more [origin configuration parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). 6. Select **Save**. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx index 65fa736023cba0d..747a17c3989a508 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx @@ -16,7 +16,7 @@ Client-side `cloudflared` can be used in conjunction with [routing over WARP](/c 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). +2. In the **Published application routes** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). 3. For **Service**, select _RDP_ and enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server (for example, `localhost:3389`). It will likely be port `3389`. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx index a4e061f10f147d2..dd7cb090d831822 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx @@ -67,7 +67,7 @@ The public hostname method can be implemented in conjunction with routing over W 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `smb.example.com`). +2. In the **Published application routes** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `smb.example.com`). 3. For **Service**, select _TCP_ and enter the SMB listening port (for example, `localhost:445`). SMB drives listen on port `139` or `445` by default. diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx index 19dc3f046a86e36..6c9337109f8a1be 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -48,7 +48,7 @@ First, create a [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks Your tunnel must be configured to use a public hostname on Cloudflare so that Hyperdrive can route requests to it. If you don't have a hostname on Cloudflare yet, you will need to [register a new hostname](/registrar/get-started/register-domain/) or [add a zone](/dns/zone-setups/) to Cloudflare to proceed. -1. In the **Published applications** tab, choose a **Domain** and specify any subdomain or path information. This will be used in your Hyperdrive configuration to route to this tunnel. +1. In the **Published application routes** tab, choose a **Domain** and specify any subdomain or path information. This will be used in your Hyperdrive configuration to route to this tunnel. 2. In the **Service** section, specify **Type** `TCP` and the URL and configured port of your database, such as `localhost:5432` or `my-database-host.database-provider.com:5432`. This address will be used by the tunnel to route requests to your database. diff --git a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx index fa5edbe923921ad..e0c09517e822112 100644 --- a/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/ssh/tunnel-public-hostname.mdx @@ -4,7 +4,7 @@ 1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). -2. In the **Published applications** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `ssh.example.com`). +2. In the **Published application routes** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `ssh.example.com`). 3. For **Service**, select _SSH_ and enter `localhost:22`. If the SSH server is on a different machine from where you installed the tunnel, enter `:22`. diff --git a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx index f32ef243e38c918..f11775736d94343 100644 --- a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx @@ -3,7 +3,7 @@ --- -1. Go to the **Published applications** tab. +1. Go to the **Published application routes** tab. 2. Enter a subdomain and select a **Domain** from the dropdown menu. Specify any subdomain or path information. :::note diff --git a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx index ee1af85fd517fbc..6040178579476ec 100644 --- a/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/cloud-public-hostname.mdx @@ -5,7 +5,7 @@ [Published applications](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) allow anyone on the Internet to connect to HTTP resources hosted on your virtual private cloud (VPC). To add a published application for your Cloudflare Tunnel: -1. In the **Published applications** tab, enter a hostname for the application (for example, `hellocloudflare..com`). +1. In the **Published application routes** tab, enter a hostname for the application (for example, `hellocloudflare..com`). 2. Under **Service**, enter `http://localhost:80`. 3. Select **Save**. 4. To test, open a browser and go to `http://hellocloudflare..com`. You should see the **Hello Cloudflare!** test page. From 21f87c35bcfd084be0c07b49f0522f255fc98774 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Fri, 15 Aug 2025 17:22:33 -0400 Subject: [PATCH 54/79] update public hostname partial file --- .../connect-networks/get-started/create-remote-tunnel.mdx | 2 +- .../connect-private-applications/create-tunnel.mdx | 2 +- .../{add-public-hostname.mdx => add-published-application.mdx} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/content/partials/cloudflare-one/tunnel/{add-public-hostname.mdx => add-published-application.mdx} (100%) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx index c2fe346aac31499..d2f1ae8515e4520 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx @@ -24,7 +24,7 @@ Before you publish an application through your tunnel, you must: Follow these steps to publish an application to the Internet. If you are looking to connect a private resource, skip to the [Connect a network](#2b-connect-a-network) section. - + Anyone on the Internet can now access the application at the specified hostname. To allow or block specific users, [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). diff --git a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx index 2ba903431f70ecd..56ae96e185dd179 100644 --- a/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx +++ b/src/content/docs/learning-paths/clientless-access/connect-private-applications/create-tunnel.mdx @@ -22,7 +22,7 @@ To create a Cloudflare Tunnel: To route an application to a public hostname: - + All users on the Internet can now connect to this application via its public hostname. In [Module 4: Secure your applications](/learning-paths/clientless-access/access-application/), we will discuss how to restrict access to authorized users. diff --git a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/add-published-application.mdx similarity index 100% rename from src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx rename to src/content/partials/cloudflare-one/tunnel/add-published-application.mdx From 4d7f7b4f7f4259941acb049c5c4573726669e1b7 Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Mon, 18 Aug 2025 18:11:34 -0400 Subject: [PATCH 55/79] add testing details --- .../cloudflared/connect-private-hostname.mdx | 68 ++++++++++++++----- .../egress-policies/egress-cloudflared.mdx | 2 +- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx index 494ef6ebf5c94d7..70e19f4df79f8db 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-private-hostname.mdx @@ -110,10 +110,10 @@ In your WARP [device profiles](/cloudflare-one/connections/connect-devices/warp/ - Initial resolved IP CGNAT range: -- Private network CIDR where the application is located (for example, `10.0.0.0/8`) +- Private network CIDR where the application is located - Internal DNS resolver IP -For more details on configuring Split Tunnels, refer to [Route private network IPs through WARP](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp). +For example, if you are using the default Split Tunnels Exclude configuration and your application and DNS resolver have private IPs in the range `10.0.0.0/8`, delete `100.64.0.0/10` and `10.0.0.0/8` from the Split Tunnels list. We recommend adding back the IPs that are not explicitly used by your network β€” refer to our [Split Tunnels calculator](/cloudflare-one/connections/connect-networks/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-warp) for details. #### Local Domain Fallback @@ -180,27 +180,59 @@ Access policies and Gateway network policies only support hostname-based filteri ### 7. Test the connection -End users can now reach the application by going to its private hostname. For example, to test an HTTP application, open a terminal on a WARP device and run -```sh -curl -v4 http://wiki.internal.local -``` -```sh output -* Trying 100.80.77.135:80... -* Connected to wiki.internal.local (100.80.77.135) port 80 -... -``` +WARP users can now reach the application by going to its private hostname. For example, to connect to a private web application, open a browser and go to `wiki.internal.local`. -The output should show a successful connection to an initial resolved IP. +#### Troubleshooting -If you [enabled the Gateway proxy](#enable-the-gateway-proxy), you can view the traffic in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). You can also check your [tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing to the application. +You can run the following tests to check if private hostname routing is properly configured. -### Troubleshooting +1. From the WARP device, confirm that you can successfully resolve the private hostname using your internal DNS server: -:::note[Common misconfigurations] -Routing issues are the most common type of misconfiguration. Make sure to check WARP Split Tunnels and Local Domain Fallback as described in [Step 5](#5-route-traffic-through-warp). -::: + ```sh + nslookup wiki.internal.local 10.0.0.1 + ``` + + ```sh output + Server: 10.0.0.1 + Address: 10.0.0.1#53 + + Name: wiki.internal.local + Address: 10.0.0.5 + ``` + + If the DNS lookup fails, it means that WARP cannot connect to your internal DNS server through `cloudflared`. Check that you have a [tunnel route](#2-connect-the-dns-server-to-cloudflare) for the internal DNS server IP. Also, confirm that the DNS server IP [routes through the WARP tunnel](#split-tunnels). + + +2. Run a standard `nslookup` for the private hostname: + + ```sh + nslookup wiki.internal.local + ``` + + ```sh output + Server: 127.0.2.2 + Address: 127.0.2.2#53 + + Non-authoritative answer: + Name: wiki.internal.local + Address: 100.80.200.48 + ``` + + The query should resolve using [WARP's DNS proxy](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/warp-architecture/#dns-traffic) and return a Gateway initial resolved IP. If the query fails to resolve or returns a different IP, check your [Local Domain Fallback configuration](#local-domain-fallback) and [Gateway resolver policies](#3-optional-create-a-resolver-policy). + +3. When you connect to the application using its private hostname, the device should make a connection to the initial resolved IP: + ```sh + curl -v4 http://wiki.internal.local + ``` + ```sh output + * Trying 100.80.200.48:80... + * Connected to wiki.internal.local (100.80.200.48) port 80 + ... + ``` + + You can check your [tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing to the application's private IP. -For a step-by-step troubleshooting procedure, refer to [Troubleshoot private network connectivity](/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/private-networks/). + For a generic WARP-to-Tunnel troubleshooting procedure, refer to [Troubleshoot private network connectivity](/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/private-networks/). ## Supported on-ramps/off-ramps diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx index 6467ade2d0b1e8f..7da26abc23f9237 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/egress-cloudflared.mdx @@ -101,4 +101,4 @@ Gateway does not currently support hostname-based filtering for traffic on non-4 From a WARP device, open a browser and go to `app.bank.com`. -The traffic will appear in your [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/); Gateway DNS logs will show that `app.bank.com` resolved to an initial resolved IP, and network logs will show requests destined to that initial resolved IP. You can also check [`cloudflared` logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing to the tunnel. \ No newline at end of file +You can search for `app.bank.com` in your [Gateway DNS logs](/cloudflare-one/insights/logs/gateway-logs/); the **DNS response details** section should show the public resolved IPs as well as an initial resolved IP. You can also check your [Cloudflare Tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) to confirm that requests are routing through the tunnel to the public resolved IPs. \ No newline at end of file From 535efef0b96048818be5de5df6d4b4957b2cffed Mon Sep 17 00:00:00 2001 From: Ranbel Sun Date: Mon, 18 Aug 2025 18:16:30 -0400 Subject: [PATCH 56/79] Merge branch 'production' into ranbel/tunnel-onoma --- .github/CODEOWNERS | 2 +- astro.config.ts | 2 +- public/__redirects | 9 +- public/robots.txt | 2 + .../load-balancing/asnum-custom-rule.png | Bin 0 -> 242214 bytes src/components/Checkbox.astro | 66 ++ ...roductCatalog.tsx => DirectoryCatalog.tsx} | 8 +- src/components/HeaderDropdowns.tsx | 2 +- src/components/HomepageHero.astro | 2 +- src/components/ProductReleaseNotes.astro | 10 - src/components/PublicStats.astro | 2 +- src/components/ResourcesBySelector.astro | 6 + src/components/Stream.astro | 124 ++-- .../homepage/FeaturedContentSection.astro | 2 +- src/components/index.ts | 1 + src/components/overrides/Footer.astro | 2 +- src/components/overrides/Head.astro | 24 +- src/components/overrides/PageTitle.astro | 4 +- .../overrides/TableOfContents.astro | 4 +- ...ss-Supports-Customer-Metadata-Boundary.mdx | 13 + .../changelog/access/2025-08-15-sftp.mdx | 9 + ...025-08-06-zone-monitoring-improvements.mdx | 20 + ...25-08-15-asnum-support-in-custom-rules.mdx | 15 + ...5-08-15-brand-protection-bulk-endpoint.mdx | 9 + .../changelog/waf/2025-08-18-waf-release.mdx | 169 +++++ .../changelog/waf/scheduled-waf-release.mdx | 118 +--- ...port-long-branch-names-preview-aliases.mdx | 25 + ...workers-terraform-and-sdk-improvements.mdx | 133 ++++ .../1.1.1.1/infrastructure/ipv6-networks.mdx | 2 + .../docs/aegis/about/ips-allocation.mdx | 2 + .../docs/agents/concepts/calling-llms.mdx | 2 + .../docs/agents/concepts/what-are-agents.mdx | 3 + .../docs/agents/guides/remote-mcp-server.mdx | 2 + .../agents/guides/test-remote-mcp-server.mdx | 2 + src/content/docs/agents/index.mdx | 2 +- .../model-context-protocol/authorization.mdx | 2 + .../agents/model-context-protocol/index.mdx | 2 + .../model-context-protocol/mcp-agent-api.mdx | 2 + .../mcp-servers-for-cloudflare.mdx | 2 + .../model-context-protocol/transport.mdx | 2 + .../connect-to-stripe.mdx | 2 + .../connect-to-stripe.mdx | 2 + .../network-analytics-v2/index.mdx | 2 +- .../network-analytics-v2/schema-map.mdx | 2 +- src/content/docs/api-shield/api-gateway.mdx | 2 +- src/content/docs/api-shield/index.mdx | 8 +- .../management-and-monitoring/api-routing.mdx | 2 +- .../developer-portal.mdx | 2 +- .../endpoint-labels.mdx | 2 +- .../endpoint-management/index.mdx | 2 +- .../endpoint-management/schema-learning.mdx | 2 +- .../session-identifiers.mdx | 2 +- src/content/docs/api-shield/plans.mdx | 4 +- .../reference/classic-schema-validation.mdx | 12 +- .../api-shield/security/api-discovery.mdx | 10 +- .../security/authentication-posture.mdx | 8 +- .../security/bola-vulnerability-detection.mdx | 6 +- .../security/graphql-protection/api.mdx | 2 +- .../docs/api-shield/security/index.mdx | 2 +- .../security/jwt-validation/api.mdx | 16 +- .../security/jwt-validation/jwt-worker.mdx | 2 +- .../jwt-validation/transform-rules.mdx | 4 +- .../security/schema-validation/api.mdx | 2 +- .../security/sequence-analytics.mdx | 2 +- .../security/sequence-mitigation/api.mdx | 2 +- .../manage-sequence-rules.mdx | 10 +- .../security/volumetric-abuse-detection.mdx | 6 +- .../docs/autorag/concepts/what-is-rag.mdx | 2 + src/content/docs/autorag/index.mdx | 2 +- src/content/docs/bots/concepts/bot-tags.mdx | 4 +- src/content/docs/bots/plans/biz-and-ent.mdx | 2 +- .../docs/bots/plans/bm-subscription.mdx | 2 +- src/content/docs/bots/plans/free.mdx | 2 +- src/content/docs/bots/plans/index.mdx | 2 +- src/content/docs/bots/plans/pro.mdx | 2 +- .../docs/browser-rendering/how-to/ai.mdx | 1 + .../platform/playwright-mcp.mdx | 2 + .../rest-api/json-endpoint.mdx | 2 + .../rest-api/pdf-endpoint.mdx | 3 +- .../cache/how-to/cache-rules/create-api.mdx | 2 +- .../how-to/cache-rules/examples/index.mdx | 2 +- .../docs/cache/how-to/tiered-cache.mdx | 4 +- src/content/docs/cache/index.mdx | 2 +- src/content/docs/cache/plans.mdx | 2 +- .../challenge-types/javascript-detections.mdx | 32 +- .../access-api-examples/access-group.mdx | 2 +- .../access-api-examples/any-service-token.mdx | 2 +- .../authentication-method.mdx | 2 +- .../access-api-examples/common-name.mdx | 2 +- .../access-api-examples/country-code.mdx | 2 +- .../access-api-examples/email-domain.mdx | 2 +- .../access-api-examples/email.mdx | 2 +- .../access-api-examples/entra-group.mdx | 2 +- .../access-api-examples/everyone.mdx | 2 +- .../access-api-examples/github-org.mdx | 2 +- .../access-api-examples/gsuite-group.mdx | 2 +- .../access-api-examples/index.mdx | 2 +- .../access-api-examples/ip-range.mdx | 2 +- .../access-api-examples/mtls-certificate.mdx | 2 +- .../access-api-examples/okta-group.mdx | 2 +- .../access-api-examples/saml-attribute.mdx | 2 +- .../access-api-examples/service-token.mdx | 2 +- .../configure-apps/dash-sso-apps.mdx | 13 +- .../mcp-servers/linked-apps.mdx | 2 + .../configure-apps/mcp-servers/saas-mcp.mdx | 2 + .../agentless/dns/locations/index.mdx | 2 + .../connect-devices/agentless/pac-files.mdx | 32 +- .../custom-certificate.mdx | 45 +- .../user-side-certificates/index.mdx | 43 +- .../ssh/ssh-infrastructure-access.mdx | 4 +- src/content/docs/cloudflare-one/faq/index.mdx | 2 +- .../mutual-tls-authentication.mdx | 2 +- src/content/docs/cloudflare-one/index.mdx | 2 +- .../browser-isolation/isolation-policies.mdx | 161 +++-- .../gateway/dns-policies/common-policies.mdx | 421 ++++++------ .../gateway/dns-policies/timed-policies.mdx | 68 +- .../gateway/egress-policies/index.mdx | 53 +- .../gateway/http-policies/common-policies.mdx | 352 +++++----- .../policies/gateway/http-policies/http3.mdx | 4 + .../policies/gateway/initial-setup/dns.mdx | 40 +- .../network-policies/common-policies.mdx | 271 ++++---- .../gateway/network-policies/index.mdx | 2 + .../docs/cloudflare-one/tutorials/index.mdx | 2 +- .../containers/examples/container-backend.mdx | 2 +- src/content/docs/containers/examples/cron.mdx | 2 +- .../examples/durable-object-interface.mdx | 2 +- .../examples/env-vars-and-secrets.mdx | 2 +- .../docs/containers/examples/index.mdx | 2 +- .../docs/containers/examples/stateless.mdx | 2 +- .../docs/containers/examples/status-hooks.mdx | 2 +- .../docs/containers/examples/websocket.mdx | 2 +- src/content/docs/containers/index.mdx | 2 +- src/content/docs/d1/examples/d1-and-hono.mdx | 2 +- src/content/docs/d1/examples/d1-and-remix.mdx | 2 +- .../docs/d1/examples/d1-and-sveltekit.mdx | 2 +- src/content/docs/d1/examples/index.mdx | 2 +- .../examples/query-d1-from-python-workers.mdx | 2 +- src/content/docs/d1/index.mdx | 2 +- src/content/docs/d1/sql-api/query-json.mdx | 2 + .../tutorials/build-a-comments-api/index.mdx | 8 +- src/content/docs/d1/tutorials/index.mdx | 2 +- .../docs/data-localization/compatibility.mdx | 4 +- .../metadata-boundary/logpush-datasets.mdx | 2 +- .../ddos-protection/about/attack-coverage.mdx | 2 +- .../api/dns-protection/json-objects.mdx | 2 + .../change-log/http/2022-04-07.mdx | 2 +- .../developer-spotlight/application-guide.mdx | 2 +- .../developer-spotlight/tutorials/index.mdx | 2 +- src/content/docs/dns/get-started.mdx | 6 +- .../durable-objects/examples/alarms-api.mdx | 2 +- .../examples/build-a-counter.mdx | 2 +- .../examples/build-a-rate-limiter.mdx | 2 +- .../durable-object-in-memory-state.mdx | 2 +- .../examples/durable-object-ttl.mdx | 2 +- .../examples/readable-stream.mdx | 2 +- .../examples/reference-do-name-using-init.mdx | 2 +- .../examples/testing-with-durable-objects.mdx | 2 +- .../examples/websocket-hibernation-server.mdx | 2 +- .../examples/websocket-server.mdx | 2 +- src/content/docs/durable-objects/index.mdx | 2 +- .../docs/durable-objects/tutorials/index.mdx | 2 +- .../firewall/cf-dashboard/rule-preview.mdx | 2 +- .../api/how-to/make-api-calls.mdx | 2 +- .../fundamentals/manage-domains/index.mdx | 9 +- .../change-password-or-email.mdx | 40 +- .../examples/connect-to-mysql/index.mdx | 2 +- .../aws-rds-aurora.mdx | 2 +- .../mysql-database-providers/azure.mdx | 2 +- .../google-cloud-sql.mdx | 2 +- .../mysql-database-providers/index.mdx | 2 +- .../mysql-database-providers/planetscale.mdx | 2 +- .../examples/connect-to-postgres/index.mdx | 2 +- .../aws-rds-aurora.mdx | 2 +- .../postgres-database-providers/azure.mdx | 2 +- .../cockroachdb.mdx | 2 +- .../digital-ocean.mdx | 6 +- .../postgres-database-providers/fly.mdx | 2 +- .../google-cloud-sql.mdx | 2 +- .../postgres-database-providers/index.mdx | 2 +- .../materialize.mdx | 2 +- .../postgres-database-providers/neon.mdx | 2 +- .../postgres-database-providers/nile.mdx | 2 +- .../postgres-database-providers/pgedge.mdx | 2 +- .../postgres-database-providers/supabase.mdx | 2 +- .../postgres-database-providers/timescale.mdx | 2 +- .../postgres-database-providers/xata.mdx | 2 +- .../drizzle-orm.mdx | 5 +- .../docs/hyperdrive/examples/index.mdx | 2 +- src/content/docs/hyperdrive/get-started.mdx | 11 +- src/content/docs/hyperdrive/index.mdx | 6 +- .../docs/hyperdrive/tutorials/index.mdx | 2 +- src/content/docs/images/examples/index.mdx | 2 +- .../examples/transcode-from-workers-ai.mdx | 2 +- .../images/examples/watermark-from-kv.mdx | 2 +- .../examples/cache-data-with-workers-kv.mdx | 4 +- ...tributed-configuration-with-workers-kv.mdx | 4 +- .../implement-ab-testing-with-workers-kv.mdx | 2 +- src/content/docs/kv/examples/index.mdx | 4 +- .../kv/examples/routing-with-workers-kv.mdx | 4 +- .../examples/workers-kv-to-serve-assets.mdx | 4 +- .../series/build-the-app-frontend-5.mdx | 9 +- .../series/deploy-your-video-call-app-7.mdx | 9 +- .../series/introduction-to-series-1.mdx | 14 +- .../series/make-answer-webrtc-calls-6.mdx | 9 +- .../real-time-messaging-with-websockets-4.mdx | 9 +- .../series/serverless-websocket-backend-3.mdx | 9 +- .../series/what-are-durable-objects-2.mdx | 9 +- .../learning-paths/r2-intro/series/r2-1.mdx | 14 +- .../learning-paths/r2-intro/series/r2-2.mdx | 14 +- .../learning-paths/r2-intro/series/r2-3.mdx | 16 +- .../learning-paths/r2-intro/series/r2-4.mdx | 19 +- .../learning-paths/r2-intro/series/r2-5.mdx | 15 +- .../build-dns-policies/create-list.mdx | 32 +- .../build-dns-policies/create-policy.mdx | 42 +- .../recommended-dns-policies.mdx | 216 +++--- .../deploy-egress-ips.mdx | 45 +- .../build-http-policies/browser-isolation.mdx | 196 +++--- .../data-loss-prevention.mdx | 94 ++- .../recommended-http-policies.mdx | 252 ++++--- .../build-http-policies/tls-inspection.mdx | 120 ++-- .../recommended-network-policies.mdx | 230 ++++--- .../workers/devplat/intro-to-devplat.mdx | 11 +- .../workers/get-started/first-application.mdx | 2 + .../workflows-course/series/workflows-1.mdx | 18 +- .../workflows-course/series/workflows-2.mdx | 15 +- .../workflows-course/series/workflows-3.mdx | 19 +- .../load-balancing-rules/actions.mdx | 2 +- src/content/docs/logs/faq/index.mdx | 2 +- .../docs/logs/logpush/logpush-job/filters.mdx | 2 +- .../docs/magic-transit/how-to/ipv6.mdx | 2 + src/content/docs/network/ip-geolocation.mdx | 2 + .../docs/network/ipv6-compatibility.mdx | 2 + src/content/docs/notifications/index.mdx | 4 +- .../notifications/reference/common-errors.mdx | 2 +- .../reference/traffic-alerts.mdx | 4 +- .../docs/page-shield/reference/csp-header.mdx | 2 +- .../framework-guides/deploy-a-hono-site.mdx | 8 +- .../framework-guides/deploy-a-nuxt-site.mdx | 8 +- .../framework-guides/deploy-an-astro-site.mdx | 8 +- .../docs/pages/framework-guides/index.mdx | 2 +- .../pages/framework-guides/nextjs/index.mdx | 10 +- .../framework-guides/nextjs/ssr/index.mdx | 2 +- .../pages/functions/examples/ab-testing.mdx | 2 +- .../pages/functions/examples/cors-headers.mdx | 2 +- .../docs/pages/functions/examples/index.mdx | 2 +- src/content/docs/pages/how-to/index.mdx | 2 +- src/content/docs/pages/index.mdx | 2 +- src/content/docs/pages/migrations/index.mdx | 2 +- .../index.mdx | 4 +- .../index.mdx | 8 +- src/content/docs/pages/tutorials/index.mdx | 2 +- src/content/docs/pipelines/index.mdx | 2 +- .../pub-sub/examples/connect-javascript.mdx | 2 +- .../docs/pub-sub/examples/connect-python.mdx | 2 +- .../docs/pub-sub/examples/connect-rust.mdx | 2 +- src/content/docs/pub-sub/examples/index.mdx | 2 +- .../pub-sub/learning/client-libraries.mdx | 2 +- .../learning/command-line-wrangler.mdx | 2 +- .../pub-sub/learning/websockets-browsers.mdx | 2 +- src/content/docs/queues/examples/index.mdx | 2 +- src/content/docs/queues/index.mdx | 2 +- src/content/docs/queues/tutorials/index.mdx | 2 +- src/content/docs/r2/examples/index.mdx | 2 +- src/content/docs/r2/how-r2-works.mdx | 2 +- src/content/docs/r2/index.mdx | 2 +- src/content/docs/realtime/index.mdx | 25 +- .../realtime/{ => realtimekit}/concepts.mdx | 4 +- .../{ => realtimekit}/getting-started.mdx | 0 .../docs/realtime/realtimekit/index.mdx | 41 ++ .../{ => realtimekit}/introduction.mdx | 2 +- src/content/docs/realtime/sfu/index.mdx | 4 +- src/content/docs/realtime/turn/index.mdx | 4 +- .../architectures/security.mdx | 2 +- .../securing-guest-wireless-networks.mdx | 2 + .../rules/cloud-connector/examples/index.mdx | 2 +- .../compression-rules/examples/index.mdx | 2 +- .../rules/configuration-rules/create-api.mdx | 2 +- .../configuration-rules/examples/index.mdx | 2 +- src/content/docs/rules/examples.mdx | 13 +- .../rules/origin-rules/examples/index.mdx | 2 +- .../rules/origin-rules/tutorials/index.mdx | 2 +- .../snippets/examples/ab-testing-same-url.mdx | 2 +- .../examples/append-dates-to-cookies.mdx | 2 +- .../snippets/examples/auth-with-headers.mdx | 2 +- .../snippets/examples/bot-data-to-origin.mdx | 2 +- .../snippets/examples/bots-to-honeypot.mdx | 2 +- .../snippets/examples/bulk-redirect-map.mdx | 2 +- .../examples/country-code-redirect.mdx | 2 +- .../rules/snippets/examples/custom-cache.mdx | 2 +- .../snippets/examples/debugging-logs.mdx | 2 +- .../snippets/examples/define-cors-headers.mdx | 2 +- .../snippets/examples/follow-redirects.mdx | 2 +- .../rules/snippets/examples/hex-timestamp.mdx | 2 +- .../docs/rules/snippets/examples/index.mdx | 6 +- .../snippets/examples/jwt-validation.mdx | 2 +- .../rules/snippets/examples/maintenance.mdx | 2 +- .../examples/override-set-cookies-value.mdx | 2 +- .../examples/redirect-forbidden-status.mdx | 2 +- .../examples/redirect-replaced-domain.mdx | 2 +- .../examples/remove-fields-api-response.mdx | 2 +- .../examples/remove-query-strings.mdx | 2 +- .../examples/remove-response-headers.mdx | 2 +- .../return-incoming-request-properties.mdx | 2 +- .../snippets/examples/rewrite-site-links.mdx | 2 +- .../snippets/examples/route-and-rewrite.mdx | 2 +- .../snippets/examples/security-headers.mdx | 2 +- .../examples/send-timestamp-to-origin.mdx | 2 +- .../examples/serve-different-origin.mdx | 2 +- .../snippets/examples/signing-requests.mdx | 2 +- .../examples/slow-suspicious-requests.mdx | 2 +- .../docs/rules/transform/examples/index.mdx | 2 +- .../create-api.mdx | 2 +- .../reference/url-components.mdx | 2 +- .../rules/url-forwarding/examples/index.mdx | 2 +- .../add-rule-phase-rulesets.mdx | 2 +- .../basic-operations/deploy-rulesets.mdx | 2 +- .../basic-operations/view-rulesets.mdx | 2 +- .../ruleset-engine/managed-rulesets/index.mdx | 2 +- .../ruleset-engine/reference/phases-list.mdx | 44 +- .../ruleset-engine/rules-language/actions.mdx | 2 +- .../rules-language/operators.mdx | 2 +- .../ruleset-engine/rulesets-api/add-rule.mdx | 2 +- .../ruleset-engine/rulesets-api/create.mdx | 2 +- .../rulesets-api/delete-rule.mdx | 2 +- .../ruleset-engine/rulesets-api/delete.mdx | 2 +- .../rulesets-api/json-object.mdx | 2 + .../rulesets-api/update-rule.mdx | 2 +- .../ruleset-engine/rulesets-api/update.mdx | 2 +- .../docs/ruleset-engine/rulesets-api/view.mdx | 2 +- .../spectrum/reference/settings-by-plan.mdx | 2 +- .../stream/edit-videos/adding-captions.mdx | 2 +- src/content/docs/stream/examples/android.mdx | 2 +- src/content/docs/stream/examples/dash-js.mdx | 2 +- src/content/docs/stream/examples/hls-js.mdx | 2 +- src/content/docs/stream/examples/index.mdx | 2 +- src/content/docs/stream/examples/ios.mdx | 2 +- .../examples/obs-from-scratch/index.mdx | 2 +- .../docs/stream/examples/rtmps_playback.mdx | 2 +- .../docs/stream/examples/shaka-player.mdx | 2 +- .../docs/stream/examples/srt_playback.mdx | 2 +- .../docs/stream/examples/stream-player.mdx | 2 +- src/content/docs/stream/examples/video-js.mdx | 2 +- src/content/docs/stream/examples/vidstack.mdx | 2 +- .../docs/stream/examples/wordpress.mdx | 2 +- .../docs/stream/transform-videos/index.mdx | 13 +- .../docs/stream/transform-videos/sources.mdx | 4 +- .../transform-videos/troubleshooting.mdx | 23 + .../docs/style-guide/components/cards.mdx | 11 + .../docs/style-guide/components/checkbox.mdx | 23 + .../docs/style-guide/components/details.mdx | 23 +- .../docs/style-guide/components/icons.mdx | 13 +- .../docs/style-guide/components/stream.mdx | 64 +- .../docs/style-guide/components/tabs.mdx | 11 +- src/content/docs/time-services/index.mdx | 2 +- src/content/docs/turnstile/plans.mdx | 4 +- .../reference/workers-templates/index.mdx | 2 +- .../workers-templates/price-scraping.mdx | 2 +- src/content/docs/use-cases/ai.mdx | 4 +- src/content/docs/vectorize/examples/index.mdx | 2 +- src/content/docs/vectorize/index.mdx | 2 +- .../reference/what-is-a-vector-database.mdx | 2 + .../docs/vectorize/tutorials/index.mdx | 2 +- src/content/docs/version-management/index.mdx | 2 +- .../custom-rulesets/create-dashboard.mdx | 2 +- .../docs/waf/custom-rules/create-api.mdx | 2 +- .../waf/custom-rules/create-dashboard.mdx | 2 +- .../command-line/decrypt-payload.mdx | 2 +- .../command-line/generate-key-pair.mdx | 2 +- .../create-zone-dashboard.mdx | 2 +- .../waf/rate-limiting-rules/request-rate.mdx | 2 +- src/content/docs/waf/tools/lists/index.mdx | 2 +- .../waf/tools/lists/lists-api/json-object.mdx | 2 + .../waiting-room/how-to/json-response.mdx | 2 + src/content/docs/waiting-room/plans.mdx | 2 +- .../reference/configuration-settings.mdx | 4 +- .../features/function-calling/index.mdx | 6 +- .../docs/workers-ai/features/json-mode.mdx | 2 + .../docs/workers-ai/features/prompting.mdx | 2 + ...generation-using-deepseek-coder-models.mdx | 4 +- ...ers-ai-models-using-a-jupyter-notebook.mdx | 4 +- .../fine-tune-models-with-autotrain.mdx | 1 + ...choose-the-right-text-generation-model.mdx | 4 +- .../image-generator-flux-newmodels.mdx | 9 +- .../image-generator-flux.mdx | 9 +- .../image-generator-store-and-catalog.mdx | 9 +- src/content/docs/workers-ai/index.mdx | 2 +- .../configuration/integrations/apis.mdx | 2 +- .../configuration/routing/custom-domains.mdx | 23 +- .../workers/configuration/routing/routes.mdx | 25 +- .../docs/workers/examples/103-early-hints.mdx | 2 +- .../docs/workers/examples/ab-testing.mdx | 2 +- .../accessing-the-cloudflare-object.mdx | 2 +- .../workers/examples/aggregate-requests.mdx | 2 +- .../docs/workers/examples/alter-headers.mdx | 2 +- .../workers/examples/auth-with-headers.mdx | 2 +- .../docs/workers/examples/basic-auth.mdx | 2 +- .../docs/workers/examples/block-on-tls.mdx | 2 +- .../workers/examples/bulk-origin-proxy.mdx | 2 +- .../docs/workers/examples/bulk-redirects.mdx | 2 +- .../docs/workers/examples/cache-api.mdx | 2 +- .../workers/examples/cache-post-request.mdx | 2 +- .../docs/workers/examples/cache-tags.mdx | 2 +- .../workers/examples/cache-using-fetch.mdx | 2 +- .../workers/examples/conditional-response.mdx | 2 +- .../workers/examples/cors-header-proxy.mdx | 2 +- .../examples/country-code-redirect.mdx | 2 +- .../docs/workers/examples/cron-trigger.mdx | 2 +- .../workers/examples/data-loss-prevention.mdx | 2 +- .../docs/workers/examples/debugging-logs.mdx | 2 +- .../workers/examples/extract-cookie-value.mdx | 2 +- .../docs/workers/examples/fetch-html.mdx | 2 +- .../docs/workers/examples/fetch-json.mdx | 2 +- .../examples/geolocation-app-weather.mdx | 2 +- .../examples/geolocation-custom-styling.mdx | 2 +- .../examples/geolocation-hello-world.mdx | 2 +- .../workers/examples/hot-link-protection.mdx | 2 +- .../docs/workers/examples/images-workers.mdx | 2 +- src/content/docs/workers/examples/index.mdx | 2 +- .../docs/workers/examples/logging-headers.mdx | 2 +- .../examples/modify-request-property.mdx | 2 +- .../docs/workers/examples/modify-response.mdx | 2 +- .../examples/multiple-cron-triggers.mdx | 2 +- .../workers/examples/openai-sdk-streaming.mdx | 2 +- .../docs/workers/examples/post-json.mdx | 2 +- .../protect-against-timing-attacks.mdx | 2 +- .../docs/workers/examples/read-post.mdx | 2 +- .../docs/workers/examples/redirect.mdx | 2 +- .../examples/respond-with-another-site.mdx | 2 +- .../docs/workers/examples/return-html.mdx | 2 +- .../docs/workers/examples/return-json.mdx | 2 +- .../docs/workers/examples/rewrite-links.mdx | 2 +- .../workers/examples/security-headers.mdx | 2 +- .../workers/examples/signing-requests.mdx | 2 +- .../examples/turnstile-html-rewriter.mdx | 2 +- .../docs/workers/examples/websockets.mdx | 2 +- .../framework-guides/web-apps/astro.mdx | 2 +- .../web-apps/more-web-frameworks/angular.mdx | 2 +- .../web-apps/more-web-frameworks/hono.mdx | 2 + .../web-apps/more-web-frameworks/nuxt.mdx | 2 +- .../web-apps/more-web-frameworks/solid.mdx | 2 +- .../framework-guides/web-apps/nextjs.mdx | 4 +- .../docs/workers/get-started/prompting.mdx | 3 + .../docs/workers/get-started/quickstarts.mdx | 2 +- src/content/docs/workers/index.mdx | 2 +- .../docs/workers/observability/logs/index.mdx | 4 +- .../docs/workers/runtime-apis/rpc/index.mdx | 8 +- .../migration-guides/migrate-from-pages.mdx | 13 +- src/content/docs/workers/testing/index.mdx | 2 +- .../write-your-first-test.mdx | 4 +- .../deploy-a-realtime-chat-app/index.mdx | 12 +- src/content/docs/workers/tutorials/index.mdx | 2 +- .../docs/workers/tutorials/postgres/index.mdx | 112 ++- .../docs/workers/wrangler/configuration.mdx | 18 +- .../docs/workflows/examples/backup-d1.mdx | 2 +- src/content/docs/workflows/examples/index.mdx | 2 +- .../docs/workflows/examples/send-invoices.mdx | 2 +- .../docs/workflows/examples/twilio.mdx | 10 +- .../workflows/examples/wait-for-event.mdx | 2 +- src/content/docs/workflows/index.mdx | 2 +- src/content/glossary/durable-objects.yaml | 5 +- .../partials/billing/two-payment-methods.mdx | 4 +- .../get-started/create-http-policy.mdx | 69 +- .../get-started/create-network-policy.mdx | 57 +- .../partials/cloudflare-one/gateway/lists.mdx | 135 ++-- .../gateway/policies/block-file-types.mdx | 34 +- .../dash-plus-api/dns/block-applications.mdx | 33 +- .../dns/block-content-categories.mdx | 34 +- .../dns/block-security-categories.mdx | 35 +- .../dash-plus-api/http/block-applications.mdx | 36 +- .../http/block-content-categories.mdx | 37 +- .../network/enforce-device-posture.mdx | 35 +- .../email-security/reference-detect-phish.mdx | 13 +- .../hyperdrive/create-hyperdrive-config.mdx | 63 +- .../use-postgres-js-to-make-query.mdx | 4 - src/content/partials/prompts/base-prompt.txt | 4 - src/content/partials/style-guide/icons.mdx | 6 + .../partials/workers/secrets-in-dev.mdx | 2 +- src/content/products/realtime-sfu.yaml | 12 + src/content/products/realtime-turn.yaml | 10 + src/content/products/realtime.yaml | 8 +- src/content/products/turn.yaml | 11 - .../china-network-acceleration/index.yaml | 307 ++++++++- .../stream/onboard-domain-cf/index.yaml | 326 ++++++++- .../sase-1-evolution-corp-networks/index.yaml | 566 +++++++++++++++- .../sase-2-stop-hosting-own-vpn/index.yaml | 618 ++++++++++++++++- .../sase-3-secure-remote-access/index.yaml | 444 +++++++++++- .../stream/sase-4-connect-secure/index.yaml | 510 +++++++++++++- .../stream/sase-5-protect-users/index.yaml | 589 +++++++++++++++- src/content/stream/warp-1-basics/index.yaml | 379 ++++++++++- .../stream/warp-2-diagonostic-logs/index.yaml | 635 +++++++++++++++++- .../workers-ai-models/dreamshaper-8-lcm.json | 4 - .../workers-ai-models/gpt-oss-120b.json | 67 +- .../workers-ai-models/gpt-oss-20b.json | 63 +- src/icons/realtime-kit.svg | 1 + src/icons/realtime-sfu.svg | 1 + src/icons/realtime-turn.svg | 1 + src/pages/changelog/[...slug].astro | 3 +- src/pages/{products.astro => directory.astro} | 9 +- src/pages/index.astro | 12 +- src/pages/plans.astro | 6 +- src/pages/videos/[...slug].astro | 2 + src/schemas/base.ts | 23 +- src/util/api.ts | 2 +- worker/index.ts | 1 + worker/index.worker.test.ts | 5 +- 505 files changed, 7592 insertions(+), 2903 deletions(-) create mode 100644 src/assets/images/changelog/load-balancing/asnum-custom-rule.png create mode 100644 src/components/Checkbox.astro rename src/components/{ProductCatalog.tsx => DirectoryCatalog.tsx} (95%) create mode 100644 src/content/changelog/access/2025-07-01-Access-Supports-Customer-Metadata-Boundary.mdx create mode 100644 src/content/changelog/access/2025-08-15-sftp.mdx create mode 100644 src/content/changelog/load-balancing/2025-08-06-zone-monitoring-improvements.mdx create mode 100644 src/content/changelog/load-balancing/2025-08-15-asnum-support-in-custom-rules.mdx create mode 100644 src/content/changelog/security-center/2025-08-15-brand-protection-bulk-endpoint.mdx create mode 100644 src/content/changelog/waf/2025-08-18-waf-release.mdx create mode 100644 src/content/changelog/workers/2025-08-08-support-long-branch-names-preview-aliases.mdx create mode 100644 src/content/changelog/workers/2025-08-14-workers-terraform-and-sdk-improvements.mdx rename src/content/docs/realtime/{ => realtimekit}/concepts.mdx (87%) rename src/content/docs/realtime/{ => realtimekit}/getting-started.mdx (100%) create mode 100644 src/content/docs/realtime/realtimekit/index.mdx rename src/content/docs/realtime/{ => realtimekit}/introduction.mdx (96%) create mode 100644 src/content/docs/stream/transform-videos/troubleshooting.mdx create mode 100644 src/content/docs/style-guide/components/checkbox.mdx create mode 100644 src/content/partials/style-guide/icons.mdx create mode 100644 src/content/products/realtime-sfu.yaml create mode 100644 src/content/products/realtime-turn.yaml delete mode 100644 src/content/products/turn.yaml create mode 100644 src/icons/realtime-kit.svg create mode 100644 src/icons/realtime-sfu.svg create mode 100644 src/icons/realtime-turn.svg rename src/pages/{products.astro => directory.astro} (81%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f5a6718e847db8f..e220f65b724fd0a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -21,7 +21,7 @@ # AI /src/content/docs/agents/ @irvinebroque @rita3ko @elithrar @thomasgauvin @threepointone @cloudflare/pcx-technical-writing -/src/content/docs/ai-gateway/ @kathayl @mchenco @kodster28 @cloudflare/pcx-technical-writing +/src/content/docs/ai-gateway/ @palashgo @thebongy @kathayl @mchenco @kodster28 @cloudflare/pcx-technical-writing /src/content/docs/workers-ai/ @rita3ko @craigsdennis @markdembo @mchenco @kodster28 @cloudflare/pcx-technical-writing /src/content/docs/vectorize/ @elithrar @vy-ton @sejoker @mchenco @cloudflare/pcx-technical-writing /src/content/partials/vectorize/ @elithrar @mchenco @sejoker @cloudflare/pcx-technical-writing diff --git a/astro.config.ts b/astro.config.ts index 36f6af23a20ce23..3a28b6cba44f327 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -142,7 +142,7 @@ export default defineConfig({ "{props.*}", "/", "/glossary/", - "/products/", + "/directory/", "/rules/snippets/examples/?operation=*", "/rules/transform/examples/?operation=*", "/ruleset-engine/rules-language/fields/reference/**", diff --git a/public/__redirects b/public/__redirects index 16034c21cfbaef8..54cb57fb5073242 100644 --- a/public/__redirects +++ b/public/__redirects @@ -1,6 +1,7 @@ # homepage /api /api/ 301 -/docs/ /products/ 301 +/docs/ /directory/ 301 +/products/ /directory/ 301 /zero-trust/ /products/?product-group=Cloudflare+One 301 /dashboard-landing/ / 301 /tutorials/ /search/?content_type%5B0%5D=Tutorial 301 @@ -2356,4 +2357,8 @@ /realtime/demos /realtime/sfu/demos/ 302 /realtime/example-architecture /realtime/sfu/example-architecture/ 302 /realtime/pricing /realtime/sfu/pricing/ 302 -/realtime/changelog /realtime/sfu/changelog/ 302 \ No newline at end of file +/realtime/changelog /realtime/sfu/changelog/ 302 + +/realtime/realtimekit/get-started /realtime/realtimekit/getting-started/ 302 +/realtime/introduction /realtime/realtimekit/introduction 302 +/realtime/concepts /realtime/realtimekit/concepts 302 \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt index 20a85d5f9226c20..2520e82139fecec 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -6,4 +6,6 @@ Disallow: /constellation Disallow: /cdn-cgi/ Disallow: /email-security/ +Content-Usage: tdm=y + Sitemap: https://developers.cloudflare.com/sitemap-index.xml diff --git a/src/assets/images/changelog/load-balancing/asnum-custom-rule.png b/src/assets/images/changelog/load-balancing/asnum-custom-rule.png new file mode 100644 index 0000000000000000000000000000000000000000..05eab6514a7f157297a031dce2c1cb7546649cdd GIT binary patch literal 242214 zcmeFZbySt>w*`!diXsR~D5;>Rq)JJPlz?=%G@F!0Vk2RZ7NE4^rn|coP>^ubEueIF z^R3r&&hOrF@3+)BaP4cc!mDC^gUd^vqpCnvf~3zW$21!eN4URPeYt-piW*pr$tV{#5`?Sol$o3 zh+~g>1{Z8+Md#maQ+4-ZE z6?fQvi-|uus&TxxGTepd$VaP8-fQ`LJ^T6rVG5Tia2|_^L@~Z4u)idPk284rWy2EA zMd?enLR|7GUs5l1z7jccDMM-GG?|Uk2q#$u*6bX`=O-H{ag3dW^uvxkmf-oNx#@E{ zN%Ywd+^a7XSiHN>7{>PZf4lp9{I1ne>z`4M7$N@I6VZW{s02cbrOgYz8e}s1mrgwY zjiugO+2^3yFa0%k?f6*MQ&mA_^0V=Q7sh6#)_&c%qV{aV_cAN}Swm|a1s#@|Ty;a! z1p3Q*CLz7}zjWSlRQb6E3S15AYN^NHJYqmhbvKIb+Y9{p!t3`bPF%Nsu-AIaj+ULs zQ1E%G*iuzDI`Ul3x0^?o2k(d5@$T+8RHU_>!0hpeI}1o+LQrP@uDe_Bj6_Uz=)b5u zKe|+Vl7!gu4)vv$V8ZD_sq0^VNu2KfN_w+FgXLn_i_6t}OrB|+y5yv7wv`;}Ld5*e z^vd4@ChFCfZ;jqnDXxjZ-|*b~tdV8&%I}hf3V{bUAwq#0N|83dmMBUhUb!{@XKH$?MMLQa~{caB(6zB`@sxF|ohf?zP&%?F3>>z(7oN1mZgABY+1hv4ZMi5%HDM^EzdOz`sj zG?}-@S1+0xCf>!1i6wlGSN4Q3(%i16?AY*+@-FE8NW6Su<>CAhs`K^_ zRM+<1(T{hVA6`5+*mCW-sqv2!EHAvj;27fHd~O~<^;4*bf|e)~oy9k5)o*k$cz(?< z(T}@^p@#4-|8VnVyAM{+!;M7v+s{n3$oGb9R;R}$Fwcd!i#jC*a@ZaH`M9*|(d{Dk zs2;MMespE1rUBuPJ#9Q;fe&bY|8vJMr{gyit)2$AXSF?~QBfS*s^3ZSkfr+0HzaiQpiZ8k%X=_QWZRssLgG-KM$^EET@9RgZXhgq^NZ|!DXf(?;XW(30r|TG> zm317d@VTK~;jrv=qH5dK)^`5Yyv~Fj&RX$j`I_PRC_*Y5RtuacVHSn2ORCfvWyC+j zeTjyIJc|n7AEi1U!twB^Uey^q9|hu*BX`ce!!K{~o7Op=;Pd_g?KRvh4|p|>HdHfa zk*RnOJP=MgA^Y?4Z2~rL=AXxl2-M|IxE?8~=3lrVLVWhF==tYDhCUkfYtK1qBs^Z; zxlH{+FH%ST^bJY~#yi|)FJ8vXCD5E4(NnzS{zbGzJSnEf5UX%nRnkd; zq5TxiiyTEF%BOW7&b6L)Jf-!R?N0bd6Z0!21nHvkAH!Rz%=x!)XRC1%p5DBv{QZcL zkq*mQnL6yv3*1!9b<)|=Y2=oEEt`~`!A=HrcJ$3vnng!-sxP?;uvI1g%w4?V%B%OJ zYdCSyaznI?YF{Fbbd*#tIw^!)PJEp`{I*)&ecb6=%qZAXp^7k1?L4gMmdJIi)`IdV~Bhi z{Y~VTagLwPJ+>?Jm+2VvuLv`EC73I*T#tEs&;RAE=$ycuAnd*3`;&1V2^Na!$%E~; zEy$f{^8>YH1VzgwJ>wG+OcTaFkf$@MMW(7H6sXUZ^@`?)O!ZDVPwA|ZIz8D^TBVt~ z+CHCD`QeAT8mF+k22j{BTei&?z}>d(r%s4~VAuVR@y`{G?h=idm)2rCF{ zdp$vy?|B~WuWG*7`yi!S!k6Q??q{c`?t~Pl*=Z}hHf*0JeTX&)96tRy{VD5HL5Vtv zY6+!yCyB(slEC+M=sL~1)S!?HE)h5Gd))uRm?|3_xl@fbvD4s9yVZ$OD@^`?dY)Y4 z7=TKhG~=+$bjjlssm&?6}-9)-*Oi&PZ;=YO2+)v12NgZLDpom60!CwmI0) z%k;zIgKBw)gQcKljFY!h(5fI+L{MfEX{2=Ibb*+5fpx*`@jhnfr07)L1l=bCChqNn zO?p<9)fLuw27dMU-<~&+6jHa-+$P#2;vzaj^FDYu_(||;FuSBy;Cn?zqq+5+#>Q&qKFh?e z<(r*GVnzi)k7lgLn$`zL2If95Nv-zGw9Q#gHLjXe*ySmahw;pKJ_-$lnq-@1y zDSVS|$*X1cSMx{=eig3IQU9Y_NAr)49&J2Ihxh)N30?=D(}~jKE%-ttckxdWXp-0m zn0-07kn(8Y!`z45yYkPHpVdAMeI|ISkRbdCPq29X(_me$H9bEQzsnzm&WbJ3tBVhY zftLP7J4B?^d485%ny!g}W11by#Oe9|frS$6(wOGw*xF z3`b`(#dEar*p_J$9O*45mULLOXEHUlZth|Cfu1k5} ztd-nRukt+o$KP@(mzWsj%-V|yi449>JnFTgP0H;bOL}J6bBTFL_`d8rw+9iOoZs@o zCY{?T^C%MV>OvH=U?BjV`+lI(hg8`{}f8-_2G zrBL6(ulQV{@SlZ!dBM41p$#cP) zsb>Y1>$*J4TCF|Bl+Gkmc(!oN*0Y4wps!fJyHdrLr&}*)cbe#1@LI~dl(vq!jt+i8 z7q(OpOH!`rQYB~I9-6Gu51k*J8)?U4UY9?}G@Pf~R$3qErz@!3#M!-wv7Mf{+{9+PW*Xsn&x%Q(@h6`tdMKvZi*-{h?W}oM zQl~SYX$@#ivz6-G6ph$nvaRp;Wv5oC%j*#oIj`}}Z(*oNczSK>hRQsdf2(a<56_Of z*w2-1vF;bPxQq`n^fOmvKB`>t9`cQec0mueUub{yJ7m$zvFv5VM!)JxVrT5Mes7t;M);6E>%eFUzuq^!)e5~O ziT$SFLN?n-_m6J0WsRQeo1Tj&cF(BN_0Y9=O7E=9EVr|NVmHyZuH;4&Y&&Q26c(yC zgfDKRkKKq9=>2qb!R-W2-esKg3;p+KGWqD%$i$oyW<`Gr8+2UA$t*geK(Id#gM1 zRCTLb*YriBdXj2evKUbM*h8oALKoM{XY8oDGu`4XW_>+4)>o|pWKQ&`p@HIRqz~+h_a}Z z6#P~;vNtiYaWJ=abfzXBgg=~ocu&&-2Z#I$@^eH=>GA@6em6=*!%;)_KA(}THJgF4 zt)U5Ip`aiGWgU869+37F-d5NQ?AiajH!bMSA zdy|XYY&Y0$&-{1P*p8B6}Rdq127qzv9FLf09uL=A6&Hw$$zuzdp zj@WV)giiUArKG_`QlrG=Rp2))GvpucPx#NZzkb8xBd?wn zFlR;M;M~EH5))BzJu)-kQbgLZd14_R|5{R#Mm7}zlUiW;gU^GOEZw`u6lb`)-Kz%; z=XH(Pv+JJf`j&sutGb(Z&1Y#j+Sqn&u6eM)g`HwEYP>p{*J14YjM-SmzDMl(ea^MQ zFiu=NeBz6D9^)K2@IjpJsr#2Fy4Yd^BIytH2INEEKaPu~@IJ(+|8)gJdiLPL}U~Ps&-+~W%@X!}?u{HP@-fr*WXFJP7kL#V* z7XCwD3|?>c<2ZeO^lh7=i2+tq-Vu;P_ zaedIU8^c9h2d=okXZYg9iE)}kUkvW7#+}wo8e!@}iGSXI;OOG*mK{Cxe8tfa;BV!R zJ{#>k^q|5fa5?nF;QzY`4jQX}H^D(m`u~5MAkNNPlJ?Q%)ycNRMeinRlI6Woy8V04 z=+LelEmi}=KIrsm6!&36g1M+SLx{jF8oMtfJ(ZnAzhpUoi1qM1+8BOjdG@ju)0;Sb zWlZ21Sf=*e!~vzPjh@wd2^^EdXk=i9OjK4Z;d zJ;R=!p^M>jntGcMX;U&Ybf2T?ZHe=2@AnIYR~0mWcIkV`#(M2N8sJ|aa2dkP4U~43 zJ8*ozAsXR2@`73ZC;k!KbjF3{7U4wpij9v}6;fBDIk!t$_~U#Jyeo4G+|U~IsLWS( z;$yoJ3ryv!o!XOiRJQlmhrGPD*7|IjV@SMHuY~K|TAl6VNzZ9uLN#1ZOuOBA1UD29 zy)~KWIA6YwT=ezw#X73%HR#aZl{WcUHGR+3ygEwDPkQBUs+0+_cbbk72`p5t47$&A zP4k_TJvrQINg4xSGTd%mI3Fw`VBS>GbcS?J|AP z9~7|Y&EMgUSgETfsyos|T<$Iz#beS)e9z8d5DaVAyl zchT=~{fabw$?21MYOR?MB^57m)nG|BEZGfEB9%35i&6(&d7Zv@jeYqdA>MA?(D=KG zy{&1-sv{>pjmNlWbX16|tn*K&3ju0jZ?eg&DJ^4Mdo$4sVl zw(#Q}%M-h&3d#3HgIsuPB1TIfxJ_UExpmOai{taY`;~nO|HsFgp^dX^%0JlMjbU|# z2=Bcs=(R{)sXjqRx;kbnF<}hXCOhP@Ec*smOSi;P3N8#i)sd>c=jXjU9~@E_^KL}3`G z9&94niJfL5{H>tU6I$0Nc+6Yl^1k0{{57bdq7d}JX$L*%IvO;Y7>jP8p{Sm^O)K*u zq!EUIZB;k&pum%-6ZheczG%G`y0%kTxplrWp+#W%zS>QTneOc329mFow;w+6Z}1?@ ze>eWq_l(^B-g>3OGwa+YZd9!2+Bd-j4*j3&=T`#Ot-5qwWLt#yJ?6rL6^6cDjg2DL zb^Osk`lK0OLR`E`V~;0Omb=Gz5+Ye9!O5|pO~F-IJf(@6*C$-2k`qm@*ie<`4u5`T zCZloY!mZ0L=6-2LnyYp_u);AFmItLW@351cSH5<=y~$eYHXVIsVm;Et55o?;?M*w4Bw06S@nwq-hSQ;u))Q@_RQMH@-g{F5L4T)d8TEBo9I1c-Z))&-h#wu_|7 z_g~Fb?(e0&o+{c3gY+*w=ydXchpiKGuCA7r*^?7k{NmK*FYTRKwj^E9Z}PqTrw>6wErovB zoGT^>zqM?CZ+kMgMW}JFHlJRBdo++Ep~oz?yd&%!t)QEu8$>!~Kbld!(UNSH#dc-+ zXjYg0T(cI^#)sUU{;crTX^!xc@MvtM*FI@jZF+Y~k+5xP`u(L0n&DDcT8#B;DMl%h z-be_8(r36z=;j}mHDXxDJXU^4wtaddr!}vTZMW#1Kv}mPzK*V6wr=1Ew%l84WbfIg zo;P8U(%GpHYqhJ`9J6%H7}-A0Wuc;FQ~cY%Qm$a&gXpsr$X(&9JgcR3FS5T_^_!LT z>7zGI{C{fh?0&!T`82ATcihSuCp~!&wxFsTWDI4NRq7$9m`7vZbP}TM8*=8AdlzR5 zhY|{h(EQsJm%bJaJsOWL6rWe0?8j`UldJ^r(s?XY=fMz#%f-&_&)Rx5qBH%^aCc;H zM2*ajtS1%;&kNc#LA==6y}lPyaL^=H&8x-{_Xo_cFMK}3gA%W);q}~F`PPh*=k`HY z3I-)rP@KulbDHht63;?n9IIgar`_GPK6XLKYbHiUyqz*^#h>){EB972(_X8VHxD_x ztt3_%H7)0y(?{SNYK#aSz^ zGm^wsp{i<9*#dUTcYPl@2*5Lwy_T6xH7X2}!QZJ~uhzcKL(+M#P3f!>#@~s=T+6n6 zm8tnhtM@}|tKz}iIE3oG}_|?kJ zt&<2x@y}$5MgV3BIMZQG=iF^D*~~wm)@M5<;p!(NIvZ(Q@ofwiMx=x9`zH9uQFz~bPyBHeeZk>ySB?UCo41CDK>v<)%S z+4Z!M$M717_Byj$?-F35T?Tp6vuaK~dZyjpr6p2{ueb&{YMmCox-73X{GBPyX|BI`PQyr~61EMa_EO=T-@c8?sjb@e7jZ3+G!)&WeYZ(= zc;|{nmHen9u^)Ri0$T{AxgF6g2Gqmp_z5u^i){+4Dqe?JG88H8-;|@oEmqH4bav;{^?X#klDkL7grPdY)V;O-VfIlVO!XA zOFj)a_p#Orh8JiZ+a1yTGNj8gI}k;FsTu!_nzSZ~s* zpIfnHuM}Qgm^mOC;&=~zxN|9qLO;FuQYEgWLGT*sTI5e(G|AWnPIHCf3mx0vwHb2; zA2ZH~aaCy46y%9lB@|g`iHcMIJlJXJkU_XA%DVRWH{x(-cTxvj=M z-lmRa0I-UOn~TR|_;cA}Qdo~F*$v?H&6ckZqQ1VoR9pBXZMLk+5U`OU?{Ky6iNxuQ z(hSXYHG$hH(lG!h3Du6Kldc4qgz@y6$CJ)mDQmF|yKm1HCT;|tdc2s)%Nq7A=%rqM zI*eU5>3mKjTO?IQ@c7w%238vwxPUWx){4Yl@?I)#c346xHjAB(PI7v_FWTA!OZqHHNsUs4DT;#Ze3zDGdW}t!aNn(qWcp)}KV;Q) zom6Y*$;cKA-_PKS2hj?aj1+A|>UyqrOa~V_w`OKghk z|234ETf508%$^;DZ+4pTPF0s}Xmvc@ImP*ew@-9hypxi0!7-O z-~c?^(|!BALD2}tTHj-_b_HsOuxJX^Hn-I&)lA_qSyn=p{7|WKs^qL?xaCg|n=H== zt|&xUq$Dp9b$rT%Ot2%8_ct7k1ySgx?=RZ(F-fV#2ZY zbY40hMK=6<%_HSr090}+G>G_po|e0>H~YM?n*&^`#Z%$Pkf~%i`L1paX4C~Twiy}O zat1}CQaBs)AVgjnDB>sAuePYr9Yh^$2;vJYePwW}E!1NErT*}`-!46~6JT|UlD-`W znA_Q+(O}KT2`cEHRo*DrW$d#VJ!qKOVIPuT0DwHPSQ&O*Td4tjZtt9)*KsRYsBc?J0mO>;!GK?~?e|8kjRl&&b~t3OgT+dAi)o(IW81 zxzD&8r?CfhxEx`4M&`841WVkAA%}(Z7mqRuo~+taYdMdiF?WSI_Z>IBKz$f}Nig*JY7M zsh7`j;w2R&3oXUC#Fb)z$`meUeaiQ5iX(-&edYxjjd=)A#T~4pw##s}_mQ%>CyMac zuA$~U0b9|j?CZ;u@_B{<4J?K=2q9E0CVUMSsivF`h#_SaiAZ#wci@wddU z-S){6-rF$hNq?)x&U)IsalNQmq;hR-TlvQFfwd_*1ou_41_~3Z^h;5zRQzQY`7-yo z(AAANq!bEQjbauLz#9Y1qTj2VyZh7!t@wN9t+JdH031W#F5%5zZ`uHGXmc|vVeHa~ z@mZ)Av?W#E1YB{H(e_&-659CbHlP@4{e(>I9!3>MUE4Yzsn)WmEJa zkAJpoxmgoGYo^MUrUQxWm**>%w?5hre|Sc#9=g3wfQcFJ!MP(LSZBw?#>paF58-k9lEnK@THtRul4Se#rz|mKU#086=qRpc=B1af^-jJs3cfzuyrxaLVkz^cpQ>dt@YIV% zo6v%!4RV>V0u#%|$0{D<8*>=eyCGE8d5S2P^4)8Rlr1?$wK=7V#Tj|3=T=hl0@s1W ziaJh6sp6KLvwMQp^&-u~sv{=5B>klTzH?1p1e{Sznds`iRRZ;-rj}W>lYe4LAJ9|f zZIG9=3-wDDfgMm;3BK}ubiN#uuGDJ#nULqZrHUbShMCgG7%`Z0yDt31&Z(f@x951vPMqg+G@pC@Rk1e*dp3iW za4TQ(O;Q2*yc%j6=!=pOe`e`Y%aS43?~-($oZ=7i^Tcm(3YbFKh!th+wMDhs{`&e# z^GSKxkWW%v;X(}okDG9Il#NPBV6n8e9#;v(T_muJ;}n1BEVLcUQLqgRS+{&8PM+*) z(Ql-3e0TU6T|=E%{|e~?TRiWvGado9U2{j-7q>Y&lV?l zAg%nMjQAbkF2xJXOva%F8o9h-tJbM%KtA*szrobgx~El}xQx;oeH+wZ%*lfYB!_~S zhZ!i|M#@o}-&LJDbsJA8^uC5ovX*-z_$vMz6l5_qxp}J-KNtp}9K#H74cIn5ZigBz z^4O#_^Kvc446r!}fNrC-Ondc_$#}duT6?D)R-pTIdf^|^#eD$(x}4DFui|=X{_WN2 z@R9kXyx*$5siZ60^}>6v5b_dxeQMSg7>Y@VBdJ{!jdMgmC^${EC+m4l%3;O_q0C>j z(QzGql5ExzgVB$-sl={B9_lYy1M487Rf-41_}7zrzw)7E`kHsjaF*n^M; zvAI6(Igi#%r5lOY8-Ev!#ix<3SXy8TrB&xgXo2|~VH~i~!)KQ32VzH=Wx7v+3Ms>p z{JA|}87s8A(#9fiL1w3}QX__AuXZg-G2T8gS-jO&C-Rr)4+KUmvj~!VHzOQkUTMO% z^@W%I>^YDBz0Ksaqg7RT?CDC_j^g)1bo6fA%<4zMiwo9K^)Tw1@;>FC- zeA}p}oZKZ3fL9a%FQ|x}b7c?W(C`EQ42SKI=eq0};hl#)$^kd-Q(GcSsH@avKJBBb z(Yjr?!LyDu`hIe4t5*mu-LLIB9_^B2!WBRDz;9El*Mek)N}ZAL0;dWu+v#{8P3`=G z)Awp!wjeJf(IFDZ`oXl!+kno@$o9Db-E%f^wsE@J$N*6|;H>S>6oX+6YYoCUM)o4L ziX&9sp@bn8PXMrZl%qu|-KbZc<#>O;O~W-VZ$8BjV4LUaL>H}>7ZdT+!HP}YQ6y{t zODq-Qa~8g6-{XYRNX{MbsHFm8_xfOZ z(Qcc(Fb01%G*}-BE#>d}=0^3wO*L8w?f)V5M~jBP!_v2_E&0#iSdt(KNaDyI|HYY_ z;y&U-H?``}+(6?6Gl@p(kYbEJOI}mGJ zOl1VaX>HBD@;lUIU<(=gyQJjhb3)Lct;;FJu(HRg^Ch_M`!i?UgOuuKr(QtQB5=31 z*81+rE%A%D_bQfqPhO3BX;U=(G)HvNDzjp1svX#}93u?Pf2|tn*_ne%v?I8qAys&E zD*>mB6b)E2nFfxWpnh4Nja^ z7KRe6G;^r4dOm`&6GVx4FS`Uo&f`r7IDb7%d-g}XWQ2Xg^)`frWR;>)?bZW1BM&P4 z&}i*|IDPGix1Jx4^C7|05jdT&pm)x_s5V`fflxl@84c&OWE#a|tTm~yW6A|Le)>*3 zsZ+g7$-8e2n6-_qbVg}jE7X~O&Cwbs}GGBT~7~GEQAdp*WD4$C}@+Gzp-M zd6uou7SJXypv|pq<>N^Q3uouq@etxg0E5pc2r<;;42zE|42UJU5;K3dU$AsX3djY) zjz}dG`JopWno56+zD!?6>0AU-^n}BB(hb+cJ5sHJHO5xre2JuK_#ChCt4$=4zJ>Uk z$trtlDD!$Od-;k|uU$Qj!?QUAW{Z67uf7tEh=Jre)DXzOy?Q&MJJVNaTfQfKBv~Ve zFD%0*P1UUuQb=QI9ZXt;!%twC5F6m;BbHvjwYL$9DHVD_$q2kTfbDO-kuju!KRv&a3++GpOkH_fF5t zFADY^B4W{jH)<$G)o%{8t9Sj0>;X^K_1&N9S3`n5+Ra zsv+d@loP?$?z2(g52YXs+iU?On%ex*jOdzz`(-8(1ipXc!t%X6(teM#2g>84;g92n zY+IOp7_-03LG)5zTQMx|L0kg_v!OI;tt18?M0}595K!y#1+dOL;B0m0HDJr$G^#U} zA+C41Zqs(3L$=_pc{rP{f2l*EWZ?N%NKVKxl3~dfD>!XSjU+tmSfs5UH)D#8_-c9` z!pnxmxJ@PJ7_dU@X=Py|SF?aYo!lZ^h2^$6=|jNwl?I!tp6LjxoLM97IMLThh`AKG zapUsByDH9{G5Uk~h{mx3Ty%I)$j|mF@1u=d0sJ4Q^jJa9PtVnyc2u zI!XKi_uW^Ix{Bv3wy_{FsL!teAlTqX!{;lDdS^p05=J7z>R3Q@5O?o28n=lLCc79K z5&=lrM`cQtK@iJP7y;E#Y5rZ@(Eja_-9V)HxisT?f+@eiEo5}7>Eu@a_)x5L*w#Tr zI*#`m^TmnvAu|UMlvGbIi`|}he3a;(wpF%xy!_G|c_As1^KPR-Jofc!DOu{Ezp#;e zzr$Yfju&Qn5e+qVkXm0KR0LSjGlHav?fLju5%MKj!GH}{4{Ae$fyJ6StK6nA)sM_G zw#T>1HzcMCo3n8%#n_U z>$y#mUP{G=QJiL>J$I>cqmR|vE1x^H4=KqT5dB= zs1r+Ta#aG|$L_hi+Oo)pr;`aG_WY2Zm)FSP!3NF;J7;>5`231ev@*S72cK8#1hPc8!=#M z_k~xVWl-D@0Gii^$-^3V^YX-R&u4umVusq1!I4~~q>;U{Yz9f;F^Hs9vUi@UV|ytB zd^wWFp(NACDXhgXRY}fkqaniNt9!P&^07jbP|xn_Oa4$}IqC8B(lgT49W#f7_ofZF zccS@Skl{8bcvF)fvAqc&YTCkFgL=eTp|0{~x+_yZ!mjSZG~p&7NM*dM4Bb7g{H2IJ z0{`yseCdpv&fdq!??G{66#-iQbTlQ|8WE&67Gw4KJ3r)5t?WeBC6fuoAL<0xx*2BS z9>mSMhCF_~lEfl#x^lU&{HYJdU=0e^x6uv&!OT?g8;N!b83t#QW;Q|S4JUjLGusBt zkeb>Hj^lN?-4G+O@T2Cex6>rqdP_hiGEU#~6^zv_j*Ox0*z%-a3Xz7gf9QctAjp&s zB*-qdqQODxA0zAcj{c=e$&U4pmsT7p{o*zm)t79@&%6y6VuDSH|o$sO) zseEU)@UwanMk}}}hg@}l9*+xDVB^Lb38xATf1Z@Wa;VjTQ2Ydx6a_|{LN{+PTjSO` zfRE%Z3jUkuCa$jgNXRuk*HQeGh$cd{8f3{(Tx&a<*yBEElDJ+dbPY8$wT)ki=isy= z)hJCs3%&_iVZn{-6?zT@kkkOy75z|70Fsk*$lCvU!aWeB)cjrYv&p@&u4p?Oy=@5R zN-DhpkG1sz;)ZJo*rSdq^8+J>xIkERZbM!w8+P(Ui2tIPhczdijQn}HfyX58I+>#GmiDTJlZ{F?cNM!NcWmB}IJsP4Z=96PUB zn5Q}UgS}&QXCNKF9w(JamT<}_yK-CRDYqq0jijP=rjliPoW7sQ-b$h{W_{2-6N`!H z*T4Smyi7seI!Y>l_yJzLv^Em6mc&d->TpeOn&Ewx_I+V(ptR)~Q9}2j0D>M*>3l*= z+gm%5Q>O!9#T8T!E2b|3?`He({$RDnpi8t<=QrIg9(G6ur)+^m){Nt_t(chZ&Nf20 zZ|rjt2FlaT+y!r^Vd2KI75(&)4o{xexBqrUIgr&lG0I*V$@|i!k>$d`pqq5;jJW^i z5~;Kgh5XB#dRY^F*(8)M9@kjUGIhP^3gEe&?Kfu0AqQ8{v0(1yZMnj@2 zzngf51Uv!11`(#a>`cUm$RRBE9LG0;t=ey&pAyQH&g97CW~zD&Uod@lNf$^2O{dQz zdn2>>eiA0lMS7wLLG}IJO)y|7KFPwcGRYzW5DKD3>g^|S`nu%h6cltP#obR&cxwYtz( z*KFGqr?11Da!k&0n4kB;ipu8s)_Qg zsnp_7LMnnS@!zFInRPYcKqA@E<#WHVRB1yTCP@8^0S3K5yzNU)#nBT)-+h#_@obd) zfYW+=OmvjSDy=rB13WlJ{=XxcpRh9n_dEyMp@2JkJd?3Q-zny_mmeF9m2m?_pPrV= zF0&O_mWJ`lydlISUpJ)S@Hw0$svnZKk_J~h-tLmqT*dYrCwN`@eHZ!dfhzb-YZayESB0k1u?K8rN;Fd*IL#wUBeew za;j9po0coeUb$l*0AscUn<&@J4&m3qz9$@+xgrc);wd9bYo#JN8R5~=+HLYnO#rtt zs!{Y}7dl1}^HRBkvMiUX?LuIQHB?=IqXqzWgC`!-rX;AJi;;qE82rj9~!lQZ=ERxg^tcJc{O^6k_IU4f`RV{?@& z+h8fmxpLV^stx}O_?cKxfH>t5OP#;T%~TX9Q1?jGc18l&b5Qip&v_?mloaJ_o#DS zuzL8Y`*=c&AZaM&Ge}dq95E(%-D9Al&kTVC@!nmIE84C+Y3aO|%px^I_ifN35|a~S z_-b#JFYZ#N26lC?j`C6rhTaHVznVcZKLIlPK=-6meY~Mg6y1IWltrYpb|DB|w&p@w zc}#1Y*nApd-%tsp&%9s!ya$Sv#7WW6nlWqDbpJqh?H?IE1$r$~BUPNpAo_dr*Kr_f?K(KXFyQz}{1%dK*_DC#!{qsA^OWDTpuXJ^sSHax1W5nu11p6A zvVM#k`f^S_iZR*|o0GVM2%2Dc&DYzH1?DCXm;=lU#t4ujEoY(KH|*1+1CjGztMdjL z+JniC?IQhzoZvFaxyt9ZGO+?p6`v~icjqUe(w8CG2`GR@uS5_aLW69Bh(szo6*y1) zU#r_Fg)sJ?vjG0b%+z_oeJ}!FNVkkov|z`6wgQZ-amUWyT45yyyvymX_foA0w(?KK zOC9zG2H^&{I3_6McMz_DXVBGXZ2>I8?+Rc{tV+4|+puv%ARE6KkO1vKYuVX;oRY)z zzW;Uj;KX#=S$jMJh$39(WqB4TPeRE|Bj>PVQPY%4agwC*#n$aNl8A7>{K zDMoDn2-h&FzrUqU9uaB$S_-S<&=l&nHuJty!zk!a8&ESzSIGQ@*`)a3h72c=b`!wg zAW&LgRESjEh@y;GBCn4Hkq=jZ&y5pNL?&UaHfq9bEPvP3$Lx!_E+I4t zqM>fh6t4e9njX)|3)n@V65eBvQ(3)4j27+W)eX|?i3givkj>&fR0w4)fe%_Lf%- zx3c4!*#+T$;A-av$`R>!Gak-+TKAhKVE)1oPcPh7IJ6g4u6$((G2X`PzgR$gWYGm+ zb_Ggf51xrWb{R1t_K*I!;6M#laa5Zu4=a@ebckWV(8)1f3C643?M-Op(&A?0LmHS! zjSv4YmC7ha+8S7~ra5LG|HB?Qp`{J=^fAP8 zqn`Ao3)*Y)pktyPO!%j_#H$wI4q7q>@-4gaz)NV_u|SV=o@^On;ro(PUfMRrCgf|W zr9T*LNKfq2x1a9{m}bfTa(42J*M_Lt@Z7xDzB?rt(YTFR%%~bETVSSEGl(0f5Ovqd zyI7oD^D=A2#s~^jj;|?r6>Ghg*O}H}b;r(Tccout&J5bcNOn&>|*^Y4py{W5IZKiB{ zt`r3fXA=`{9Xc?;!k1(sU>othV!@T>$>SRdd$oc)y4D2o?+s|Q<)Rx!TS14YeM_Nf?V?Hdu88i!n zW@x1{6R@CdNAN~Nx{#Pp$7R4NcX#9_$sRulXt^0c81vIOe7{-yEO$0(1@xjy(hpS{ zHXGngNaabmJwb88P;(^dhDJaA48?F`&DlCT7N2)N)cb*Beq;4$2-<$>r_mE1o+;fX z*YZfz*efJ{@V!(mkd;UqEEGADGr28n_lFOrE&oa}>GW{Y2=rp(wHi)#TV@n9evWmY zE6!!ILHc$FKAWe4n;|to+6jWBbhd}J%GX9q68wJf@?a7E(ZtUvd1x$eBu;!-*%c;Xccbvg>!z3%K%>&h@7^C&IBK=0w?B-!40S_V+~-u;wZF z?;38`R3R!i(k$9X7>*caA0`c&`7P1!oKNS>y0Fgwpz86AMy!x0;sJPFy0QqSq8#F3 z#4s5Yl;Q`2DOoTpd`K$DobXRp)yHc`y7z8%X~?ZX2V6s#1+q$WM?v0`L(EJCJ64M) zt-&1z_5%MDSFpohLA403_m5~_>kEE72=Onf#BuWVM|)k&OWmFql}^ZZnJH*sO8rIH zxP?TIH2(*FEA$V#Uy~;w9W>4scuYp``|mOnZS4;2@9O(|JxVWfd!WZvS;LETVDkZc zoI3!nSmsnljoZ%9A(B|RJ8RoxgLjPi*ma{jey138&a>8dBUs}9``s#wlsZj^v5Hb% zD#dn^gT?-VCQB0)**2vG>>^t?q!INJ(wXQl?I&wpD^dxo;A#`}!I8-$vAhjtJdDN* zx_hv|QmffnVU8kwvn9|DnDbd($4(sSpdDz1g@8I%Q6f@lO)BiG!R8vo)p<=wr;tW< zgC769_1|XsmV!}XDyu9J^0~lMevoEe)eN%c9(=1qf+y12kjCTllH_^&A#p&f79`oG z(_5=Z8yT43G@Z)Io+(h@3NW!ZdfzKO3qt9AFh6=ZZ-AC6^GBbD4%B_2^r8{}9yDGD zeHPf0AM?Z96O^KWO;7J@?sEkv=u`<}b^Oz|HOo_=NWJ1d{Dgv%T2I57=eX*rtsqJ+ zrgD(>dvZR5QOm;ridQ9!Bk2&2(5U_gT`)ym51U|xjWP6(XXCcYd~R|}+=sX!`$pDq zH1zpe4c2)WZ4QFzgNLeg;$uK3>j|CtgaezG{>EQ%PvE}AL7sC#Vu{Jy?6)(j>bjw; z^|y+Utk?7IuB5W4>CFm|GJq{+5XaBBG7C8Jerjfg+Z%an&~8-70`H81t*Z6YbO>y7 zKay}w)Ax)6Mw4;SdcrXPnkQyp?LaTZ-%!W!FQf_{o2cVwXmy@mP#puyK=}&NAgR%? z3Y34chIl4;cfipByDMi~$1*)%36GTOk14@<=%#6QEx8Ow6Q{E1=V=;5np7DL`0ZRD zOcOaE!{SaYgAc}&6%?qpU-x9ePKgM~8QP|><+ zQB$U#spmA>Yd<-NuRug6Bmjot>)KC?M4u5kts5M+%CNo;*ZL)H2t=0)6^c_J%8rKofTE0a3_-fRR^<23ePFa5!N9N@L>XhU4LjPH$K zBL=}wu*Wb~-=T#%3L1=~O7_N%@6z}GX-^-o-y!jj1XtGd7_*fCl)K4Z`+F!5dQsqr zkPX+dml{@hBc#nRLE-%cpHV^^IZ6Sv-5ACQ^N(&_AzA$h5~Y8uVLp0mVjbY_CuoMh z>;P07@S<9HU9|2zMGm=?0iUyL0Xpbs&EOAqB;>!8~Xrydv@~0)tGw-L_(mWvkmm2 zknjbXc>$0A2V*5bHPpVJ2j87R z)=29GxvIwm4xSKBfQa{(I{D=}$z<&Qj@j7xdUq&W^q@b*svl;ymQXAdS~z*M@XkS& zswG{geM*8CXc0(K6nN1n5BjLMqrrvKQ?P$n$~YenCi%h&!3LOGxd06~^l)^8^8pKy zU`j9q?6HZ6Z$}Wiv{ttQT#)LTRAyU(tH}Hrjk5;%Q|3UF)#Tv$bwJVl;+SGEUL`-& znlpn_0ObuXi1wc~88ykp>#cH5cZQUS#eu#6Vo`wwgla z^-odJhZGgc^MmEn!DP0i?4|C|rqs@g(Gg%Qi0>T+RQTHI4E60B1ae`)FBD8!DyduY zJ`@1-Pe3vQfde;Z^UXtUWKQ+J>xz#EZvD=evN8b04(jOz(; zz(4kjHh6b9;`JsKsk+aUu82AoOQY5#cR0004u9XQ5Na)wEo}~eQ5Z--p^xRR{tssApS%3urNh6I@i(dY ze-F`LgLdcN$v9|;{@$Md?u`G7JN}=$^8dGCste~QG|eH#MJ#9A{Wp9rbNy9c_i6kW z)%6~kL?Fy5(ldq}53^5`$5l;$a6c$$yG(YOA4EYb<@*N$f6o5`q;57;2sUFB9RC&Z zpkf;wjqhzBEv`Hh-nnEA?Ct0;_ibIut21oU|FPBlpAXErAmpBH0FsymJo%oJU?`GC zJcZ7VA73y^Bc1jR&Aet2;Otk%3;oERDgJUAp#X`jq2@yQ5^{f~O0dNxI}d#rTkDnk z(TsU6Mk^CPP*C(V#%v*6aTuW1lVgOpXRdsCN*Ec@V=T;lVU z0Ot0#%bG!7S^*!XsXNI}ZP0y`GWE)_&}|yYn$L$6R~rcFe(VTz6vohh<*BE3cq_P= zG}r-W2=!OV_B^0D_ZE6M{3uqofd_AE{UF+gxc^y?4)(Hps5}o`XVUVJ=w{E{)NN4y zA^CsK;eVp-d11IJw7VS10yI?RX{aqDy$PUGd|Q**Uj`(Sh@AcbT^hVpR5ErJco9q& zCwPY8JijfQJVza6Uo>m<(4+sI&i?mbM)e-RNd}&X;sw24a^OK1{X@SapbJ^oKi^z{ z=9~gNv(x@S4jkpel_eowfg@HL+_6zNfpYnAE9_v{aRYq{=^{tkS9HPF+tbEB5$B7A z8SkHXLk;uqpH1hvqNoM_#y|FUmu7@kLmCdPfV19nl5rY@W|2uS%-%43(fF^ei0cvszb+{RBLpjvLhbN*?4rpglREpHxvy@Rn8(6+T`F+g$x4Tkv>SbBAb0MZc4+cPa;}iL&pLerQJnG z-lgZFTTqFV)c`KpkS>?W4t4#exp@6b^n00slVscxd@Vo_zCsMpR$*{N&rO1-W3m^> z=;@#y=Il^W?qE&UI^Xp+PTx{!^#5V+t;3?;*1ut8gN~Rep#q{{(I}FlU zs;vgxLzN3S;A*BV>{1{Jj&ipqV@S)BsNEep5BT$NP?ww;a2Cnoc3==)U(?MKOl8Q#FpmK zb)lmkuj|=`Br*GUvHq+{*I95r_3G^_8|&H~Z_}p;+G3y~;WOrXnXHz>mW~bX3uuJ!lRs*_vEvs8{bm^Or}@pj+Y37GA81{JG{B z*UXxG+v`8i#N-JxXzmhgKxrXG&2n@Q?WF zX5`Y>uj|P~%mVSo&=!@Mq6Smb)B}16YOP`#5+ZceiEZr7jsOX5&~}l!N}1&>pnpc+ ztZaXP>a=QWBZghb1ZlJO@MoUj(a_>9c|*4?xeXM#V9H^)`y>>L<>W`$>ncD5aY#(JqR z+E1Khaa#1U>zOz@{gk%;F5T6BrT_uGLW5s_o>x_ID2xFr8!qfmHYCR-Y=!;AYT7fxG)zgeDI+%ca;6Q_o@chx-GHqZ)CzMQ=vESYteY zqL%IKhJ*pw-;zHg3_R7x@OeVQy$PxZlb`i$epcbWufRKR6GoaJb4! zaR+w?%yEN}|7C&p>gZSaR6;)9PO!i2QnDCYnvgy_1B?RbvrU&YSjncN;-ReM@gy-n z_iH)lhS)t4kf))BRT+cL(rMCVSe2oiB^C`D4}|Bo64tNIm#||PY}o21xe}9JB1i{K zU4NQZ2(Ezf*kJlN&02@x0vacUf*5DHW2W#spaXN?b%I$!Rw{nhu{#_(RurGdG>~Y~ z5Qia3pUA`(s7#R2z;_CZ+xrV98AUx%@!ndt z1j83f^cfZi>35<}o$2-AT6z%gfa5?B5Ru@I+fSWP!#f17`C>6BzF@`=c7^ zYkYVBj}@31&$t2I!Fo?onf)18CxC(iB#IvGy(o&MDIIGKGb(!1`KB7MK_T-GpSN)i z3A(Zwg!PN?ulGI`^KZjks<2^NBMzS!;^h*QCQesvF&8QX zmxm>PiJgH*#P_PPji`N#an~un6wW^Tbg$+k4Mx0C$ zTJ5rF(mlx^dbs)`BmOsOite*tyff3W=W12Lm#;LiU)|5pa8fq-^_A-YXnn`Y^dTI3 zZIIusa)o2xLHEqo3`|AY$84)Qq#ef&rgx~|Oo@h<~v}STr!$PYPk|uY(RG3q2cq zMR(Bmle%bD7Pg)%tOj$}%SECsQ?EfkjA&Xec*Ol%RHpqe#b<&Zige9Hqv9;=>2W}s zzqXu7EPX&XL@c@{kf>8ukRwN(6{U11L(Td;l{%KYXKAV98a%_xE4{xjs&=0T*Unkf!N=j| zSFs;4zp(eXxQ4Mbg{@if!t*dNYSu0iDc9!d)MR$xB<+>{#2whiOVM=c6_xbc8Psu9 zg>K9E(-^1idyj;mk>{9Z_Je%!k+w#HxZp@zyNv{|kJtN#N&}L?Qnc zM$+a)GigFLW{x2lw(QwLy|%AOpa=u+OPBcUjQh?{`p+N6?*+UOpngT$W5rn_BO-$9 z8~bsKI%|L8kyV7e_uHrUoNaHZXz8>Veak;2>`JT)WvNdwSHzwn#g%tmjVV^6D$HU? zNt1MC3j$(}^K~EI_2Op_jd8bq+~zgtPWlXwL;LcMYm3Gd%gP_maQ74>H&(BoLc)LD zwK3K4S~8TgfW*<3wfnQRm}UB{pn%nZMYq0lUY&n0mMZi>S>eBCA0tilT{gC-%NwDon7L*iEVNDVAxuR19ajxXbYQ-h?C8hWVJ_ z@+oCpJ+ZAdD==(X--6j|ss9Ka#pi=g^!@wu1y^Ir;{y*RQx;E79;m+8W;#&rTg`B4 zAiYWMe6rrY%%0qZKc|0a%SSZBl+>7>Ay0$k(WZE**umMGOFy%EvHWZaT`jS`2I;Az z9;h`$SvR8*bgxB5gLK(sf)2+odUGIC$wSSp!i9@;(CtB!@{R6MqbOU=^=x3EkD(k< zh4q1HhSohRGeX2ku2~2OKwW0@CZ}gRqB`e zqaA7;S&GCMP>Q>of{_=i6Av5999?hZJw-1>1FPOjf|*u~Ucl#g663a}F{kJ=40<1y z-jy*=nO%K^&3SHVnRO*zSo;c&~W9z7+we8Vgjl>FzOe9+H7XmgFH zyHiPuf3ihsrQngPpuQgzwHkyp40^xdRsUj?c54K7{`ut6*4HJIOv%;f3|{t@j{)m>5$!nN3PH?5WL;Y zje#I1i+mh9ti28X2%Nj~orGJ2Zkm<_Px!$;zt$|Zi-IIxUaO&#tHCxvTsB99vN%_xtqh)a*S7D?StrL9 z_YUcOix*(DIaK|H59npNRQlAE{$6BG%<`J}%vh#=3QPd3yq|wZlu0|FP)elEuOpLG z$M&(MBshVm&RhR_byD`GLAg(*d%43T`+JRy4w9pyy8!7>7X2)5ZSrDAuz*@f8#Hm> zz4W40Sd%Wm1++;?h8HiE!2tuLw6~-7359TVxHy;mwzEIi+!R|3E=!#Jf-FOH(`LqR zNBc!w03xgIZ5O?^iME^*-PC~5_5!&xNUYFhX#&=#Ie+}B6i0~+-F;$&W`o87^2%KJ z?~tHtzMnLyd%X>vz*(eKi;!%$qa()^$D;|A!A9s)zYgp2VfUBuAq@Brd&GV|NAU_j zV+5}G9uC-+l&#a@G&}pbg_pvDUym|}CXRR8K7c8PwDbi0E`Uv%5(q^N(v=$cJ^0Yn zxb(I@PJn1=W4hANanpJEF7K-G1c4MZ>3dYc^U8Q8+!#;$Cks;_t`OG9%N877LdK4W z36wG|3h0-&8=)6ElO9`O-VJFZ(vQhRVDEM*|QXxV^!_XZV7$* z1MhjC5i%LHE_~n(ppa4plPB28Ig@$gL+cFH3#f>K{iI6p7@0kyCB7FjrH>Mis)GSW z;~}FE#T{fUW*p3Ss-CP3i4@;JIFr@QL7_mswVuVIpr9vfP+Ne6I?A0N7_7Y2jeSIa&%~h~?TAelCFph<8{Uxh6@PG%?K2ar<>o23ySjMHs-R;fNo= ztyRyxJ1;$BR#v2u-`^8D@9fWdUU<97Ku=5cCp0=81+q#_WVr($vlp`gUxhDo5WufR z89hJiO<^&@o7fo*SK{FlABl5`rDlqHXD;i~EhM+q0)|5`W4Z`G`*_FBN{av{ZXR@p zlgw)t@^R+M7mP9oOfqaOox+z}zfF+gyt~C};NANIk=K&JWhAq7Htdfb>`{RLsnJKS z$M!RT3 zlTpxzTCku8AuY+ooM?zQ7;U+Sa01}UhMMfHjC_IFT?Dk!+`JBOxRq!*)6_xNQWI6B zP8}9S(#46IaXN1hnI%{I_AY;1xs|e{%Id*2$TMxP2|^05-=eIkUA&FZAX$$xa75Ys|UJm+AVA;nmcJ46r+VKRv<}!08{% zqU8eQ|GCp0`^kxu_H_G_g&cvMIy<)lsK`%$uqR&cD(shI+j_#E5ms45{EeRUY<4bH_lzpC_nQ#{iLb4CBD< z*9*hsVTmyk9L?$QX$I>xsb5F2Yk1C}nFoD9cNEs)G--=UcI!41ZxcJZZB9T5Xhd)c zV#d(R*tDAddxQtW@ikR$$Jn~#YbU580VlG(*bFG6nO^A=*?^c2lRV4b9C0Bx*aB8zm|Enr5(^X=XVMJTFmcC$lkfRm zXNbApw~JlZW)HF#&{qdYzY!pXcrAb12R{DLFE+#-oB|-T3D~t^iGmkbr%Oix#lFSn zx}@h#@-^Q<@iH~4v7!s~G2)=G)XCw3h|?MpO^CmlZaJfs4Yqh|d|U%%3+Ob1^d_)Y zqHj4n(Eij&Fl-z{FP*rXQdWc@tOUegciqOZFB6uoYFIkJ#=NQxLy81GM7U4k0( z9~*mDheT`?_=*;1RiMFroVj5PCk>ldF>Y z#+^}?4ZWD~=0qP=G2_F`X|Ii`v%Q7kfMU7I+0$0^SQ8gV+Ou8yASr$iQw2YGy*Z9H zKahzo|41sPw4_>(@c8+Dy6vgW{*&Gu*qya{85rxDUEp4ziu>Vx)3Sm6dJ8n{=dAj_ z(0{JLj3U8T8|1zYCf zmD%O#7OgIkp|~vU^GN{HNWc8nr4bi5BRU&cG`LDy6HVwZ`YjbkbpqHjXo7QqZi4~*T&x$z4P^XLE^u^O>_Br{*!}n@%>hOVkQYooHAUs zE4R_iSeo#eCP?i4v!+170_JbQ%WU95r&A>o_{sO70)a@Y4s`Lm9iVNoxgSqS*U!&% z4;Dq~8}iZ8zEyG34oNWHEHfM{l8zWdMoq|c@dSoxyEGv;-jk{2(}v<@ILpq+lgMsM zzvyj>&CD>)#I#(+X2sj8;=G79MblpV?=77Nm^VoN3_lNRpW^zBjroG~EUKzL1MJ`F z2cE^;7>Tef6*AG(zLlk-V0F^ISVocX zVZ?@-xNXQ|!%$l9MkLiyAe)zmZF&?(D|?o`E-|c%$L^fEa)Uw+O#1!DhAY z`@lMCr@W0g!z!Z6TsXRzdfUfLoXdu14)@N1qxDyzp{#p!DP!IF_7_D+DJ@y8o}c?e zTB+Acj(d2f`8beIka!u*p=qdM=#Ap{)p%2p>qcn`xBhXaoWAAcBJ|46Hvv1$6d7T9 zWKoB`Pf=hIG%5x>BiX)ebN3MLkp~)4A?-dE_UTS-rtoVkPYlk13 z*{y%E zfVa-vYWF4!(0IpO=THOIu!I=Q1h^>kGQnkFY6un%K>RBQ?-8iKT6?$`P1EJF&IjK zQ3|sk8I5m{KdH=Q`6XoCCk_c6=s4`2W?|cRwEiOO!G&e9P0*?oPQw3sw#M#J+7YnP zgNw3GRW*6xpD`=Opz|@lpV3W?vGtUqUfU!3hIWL$&axbUEMv(nP7RG}!TxAGI;Cg=wL{8Swr@Eb=i3~z!k@egFt zT@DV=@jJJJ{@i-~3yPe8QN5{un9U~cO8;1*Ql~&oNjUqVdh=c<3$SoAuhr%Ld5!;b zO+>r`)}HvG?}MBFR8ByJ=!hQH`r}CBUu&Yi5;kY(u3xj8|5O*?Hzpcv_%^$8_l?|v z?IpL(&T;df>ImAqBVs}Sr2zc*zxMy%+e0;4Y$!9yJ$uHmvRNXR7Zd-z0G+d2Ofzs+sJ`W6~?GKyG=K>%yw z-psO@9TeFil&#l@%#9-PXuO<1P+_wLrz5erGSh)rCN<7JM zv4};IU|(htK3!*!SjdC<*{|=+LJci9fu6i)dH3OSry=XH_*tyH>LwpWJ%Q#3Xc{&W z3$_M|{Za+UmZ$AJgaEGY+Xd1NlyW&kMf__yUAS?2!r@&}l89;##LHt+$)phO8$Q zaPyilwrv6cp-ZpL{P9ls!&G@Xo#6T%2dag0rCOsL|9u1h=Ub+}x$&BjSO-@==p@5T zUO{6!wk0$VigB6V9kR&}RdZaSwJRthJVIB{MSlLzbHa@mw;!r|fZ1%dc;AV4cS|>S zx<%~V@mgpxCMw+9ReQwL?DXa;s;wcEx|De0;IV&s0Z8N%%2ir-q+Zcu+T^1Oz8sO1 z%g?ZeBb$2j$IESQk4nMGeWy-J{Zzr7CbOJPe%NE~ABT!?WaWm`oi4t+y*Bj<+*8nz zA7GSS`@KrMk8t`I`=56BKR%3 zmR;Med(HnyD9VXgT?S|DfR)DS+tAzppP%mk`=feeD%Q6vV;ORGC0=;)_(N}3$)(SG z8v%Y0)NZo*;l4cM> z^qDyQ5TUgRaPhYrIy6uN#TW*vpG3EmQSfDvg>k;)0~lq@o zzXRY?x0-b8Q~6>-H?@-P0&``k=&r+Xr_~jhYDGlpa{NXEB$TzaJb?KNWo!EGS<_mu zm#&`zxbYUsFfz>Th7amy3^=4L;G6U3Dh_@w0zYUT!gwn$VznX}XZTo1&N^bLZFqM> z=fPWCezqXl96qP05d@=stDda|JBi)=$41(omv7(Pr;P`i@~*-4RZC%xlLbC76#u~r zRwAQB-Bo>rZF`fP=oXMpvQ&>FSI!J5d;02pUTv zsuk_+B?y9z2|i!mRt zqLYA9%cep=0i}eg=y{-qNkRrZgu&aLFlubMuW{s253ULK^W@>=ARs-lilt?+E?HXOyF30V%yXnEQUEvCU_1bM4XH`p#ZR5 z+`ffb`xiuK*BbcL4OHg2o~nH!4&pwc9NVUh;e7k87>PW5v>Pgb9Wf1-q<##{U(; zp5mQTLd*RgZE1czmQ&b!XGt8=Psspn%P7_e42cG6BN7~UTjr(B^p+9a074MT)Xnv7 z3F?=0!Z`4IHBc)4cmsBJ#bE)`#F^np# zg-XCOrjU|RW#==&t-E~F)eWW)DpbB{KvAl_&ZKRtr~&n<5phbx-Qz9Py6?j9)GP;i z6k+6mNHu1le`w&%fWYRw18ni`hhD4%ADY0C-|gU{pc0Wgrh}Uy(z>Q~O|%s)WRgKr zdP>!f7@^Li%)H_cc@~^u(HJjm&N$l4ifa?FYUEs27NAZ-P|WF2P+2&hznBjU>e*a6 zj1TPtt2N|+K1JNp-UgHHf za|gSLeY(+%E-)o(K;iY|Qnq!0OkCNA27*S1E-PpaQr$vzfO)G`I1QY_>xzT?3oTiP z=*XJ4-Dw&TISJy!b2HFD1dUDBVCZ}cg;<2e!Pn$Rnei*XfWd7H5AX(%;@yzt{)<|$ z=h5mGxEuk6CtR5&@z3lUC_E$HaDmpgQqervB$dVue#w7d#xiaLfR z{R&W2%+00-?2R)p0M6lcfXHNlaA&iJg)!*qN-vbCrljUYumcz}G~t*&Xbxl)xip{q zo*hN2gZy!TdKcvUv@LGkw$^_cf#isUJ}2Z4@s1f#*KS#@!80Q=OVjl(sq<=drGnj5{ZhNPG z3aUpfeyKl9vE34oV^Y^e3IVxP8#)>6%GCQ(<^D>9{g*vD{ZXdL1N)xI_H-lYKr*dG z&u|@)lTQRo@_ictK$CEtItPyXKVy6W#jdOxG{S8J!sSNk4wi?Te^ILHqq9&lKAO+j}Y+IY*6$cZ&;Ulfc;Bbps@4OH1gzA zk$ZO25v<$o_B6Jr6l(%0ya{U1TRUjZ6G$|6IIz}oz%pz&M8W+&u`yeJ0L)o=$; zj~klE4!%LHkm@6%w;OgmK0=p(FX`{#EkynpYd^M2-Wz?+C`q&ez}_#nL{F2OT8?{U z5kQ0YaEUmEysbD(o+6i=JR~zfZSx8}^2;)faYF%Pd2seAEujuLV6BDuj6JY0I#9GY zGQ+8=C~K^-g3B-$kMMuJxBchcp_u_h99x{%i<_5%$!Q8I^8Ll;=89f?RGy0F0v^6}{ie
A| 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%0Dge10qF^k=O7p)LS| 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 M#Bmp7qv?D!?+HkkX&wC=aXY=e3D^-LHd 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 bEnM$)%C~KAlRE!BTKaQt5Y!BWYE literal 0 HcmV?d00001 diff --git a/src/components/Checkbox.astro b/src/components/Checkbox.astro new file mode 100644 index 000000000000000..5fcaa2441b4b775 --- /dev/null +++ b/src/components/Checkbox.astro @@ -0,0 +1,66 @@ +--- +import { z } from "astro:schema"; + +const props = z.object({ + label: z.string(), +}); + +const { label } = props.parse(Astro.props); +--- + + + + + + diff --git a/src/components/ProductCatalog.tsx b/src/components/DirectoryCatalog.tsx similarity index 95% rename from src/components/ProductCatalog.tsx rename to src/components/DirectoryCatalog.tsx index 7d405883ec48e2d..9eb7466952c4930 100644 --- a/src/components/ProductCatalog.tsx +++ b/src/components/DirectoryCatalog.tsx @@ -13,7 +13,7 @@ type Filters = { groups: string[]; }; -const ProductCatalog = ({ products }: { products: ProductData[] }) => { +const DirectoryCatalog = ({ products }: { products: ProductData[] }) => { const [filters, setFilters] = useState({ search: "", groups: [], @@ -74,7 +74,7 @@ const ProductCatalog = ({ products }: { products: ProductData[] }) => { setFilters({ ...filters, search: e.target.value })} /> @@ -116,7 +116,7 @@ const ProductCatalog = ({ products }: { products: ProductData[] }) => {
{productList.length === 0 && (
- No products found + No folders found

Try a different search term, or broaden your search by removing filters. @@ -163,4 +163,4 @@ const ProductCatalog = ({ products }: { products: ProductData[] }) => { ); }; -export default ProductCatalog; +export default DirectoryCatalog; diff --git a/src/components/HeaderDropdowns.tsx b/src/components/HeaderDropdowns.tsx index d18353dea2a1d57..b62f64ecf87cbd9 100644 --- a/src/components/HeaderDropdowns.tsx +++ b/src/components/HeaderDropdowns.tsx @@ -11,7 +11,7 @@ import { useState } from "react"; import { PiCaretDownBold } from "react-icons/pi"; const links = [ - { label: "Docs Directory", href: "/products/" }, + { label: "Docs Directory", href: "/directory/" }, { label: "APIs", href: "https://developers.cloudflare.com/api/", diff --git a/src/components/HomepageHero.astro b/src/components/HomepageHero.astro index 3684bcbd4a52c86..58eb97d67b2083e 100644 --- a/src/components/HomepageHero.astro +++ b/src/components/HomepageHero.astro @@ -45,7 +45,7 @@ if (image) {

); @@ -108,11 +103,6 @@ if (!releaseNotes) { <>
- {page.data.release_notes_product_area_name && ( -

- {entry.product} -

- )} {entry.title && {entry.title}} {}
diff --git a/src/components/PublicStats.astro b/src/components/PublicStats.astro index 0e7bef8d83595df..31424281f7f8929 100644 --- a/src/components/PublicStats.astro +++ b/src/components/PublicStats.astro @@ -6,7 +6,7 @@ type Props = z.infer; const mappings = { data_center_cities: "over 330 cities", - total_bandwidth: "over 388 Tbps network capacity", + total_bandwidth: "over 405 Tbps network capacity", network_peers: "over 13,000 network peers", } as const satisfies Record; diff --git a/src/components/ResourcesBySelector.astro b/src/components/ResourcesBySelector.astro index 76de754217d8f3e..5e690a56d8f39a3 100644 --- a/src/components/ResourcesBySelector.astro +++ b/src/components/ResourcesBySelector.astro @@ -52,6 +52,12 @@ const resources: Array | CollectionEntry<"stream">> = [ ); }); +if (resources.length === 0) { + throw new Error( + `[ResourcesBySelector] Couldn't resources related to your filtered options`, + ); +} + const facets = resources.reduce( (acc, page) => { if (!filterables) return acc; diff --git a/src/components/Stream.astro b/src/components/Stream.astro index dfac7032804a9fb..4e767df7f23e09d 100644 --- a/src/components/Stream.astro +++ b/src/components/Stream.astro @@ -2,6 +2,8 @@ import { z } from "astro:schema"; import { Badge } from "@astrojs/starlight/components"; import parse from "parse-duration"; +import Details from "./Details.astro"; +import { reference, getEntry } from "astro:content"; type Props = z.input; @@ -12,12 +14,53 @@ const props = z thumbnail: z.string().optional(), chapters: z.record(z.string(), z.string()).optional(), showMoreVideos: z.boolean().default(false), + expandChapters: z.boolean().default(false), }) - .strict(); + .strict() + .or( + z + .object({ + file: reference("stream"), + showMoreVideos: z.boolean().default(false), + expandChapters: z.boolean().default(false), + }) + .strict(), + ); + +const input = props.parse(Astro.props); + +let id; +let title; +let thumbnail; +let chapters; +const { showMoreVideos, expandChapters } = input; + +if ("id" in input) { + id = input.id; + title = input.title; + thumbnail = input.thumbnail; + chapters = input.chapters; +} else { + const { file } = input; + + const entry = await getEntry(file); + + if (!entry) { + throw new Error(`[Stream] Could not find "${file}"`); + } + + id = entry.data.id; + title = entry.data.title; + chapters = entry.data.chapters; -const { id, title, thumbnail, chapters, showMoreVideos } = props.parse( - Astro.props, -); + if (entry.data.thumbnail) { + if ("url" in entry.data.thumbnail) { + thumbnail = entry.data.thumbnail.url; + } else { + thumbnail = entry.data.thumbnail.timestamp; + } + } +} const BASE_URL = `https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/`; @@ -53,42 +96,43 @@ if (thumbnail) { { chapters && ( -

- Chapters -

    - {Object.entries(chapters).map(([chapter, time]) => { - const totalSeconds = parse(time, "s"); - - const thumbnail = new URL(thumbnailUrl); - thumbnail.searchParams.set("fit", "crop"); - thumbnail.searchParams.set("time", `${totalSeconds}s`); - - return ( -
  • - -
  • - ); - })} -
-

+
+

+

    + {Object.entries(chapters).map(([chapter, time]) => { + const totalSeconds = parse(time, "s"); + + const thumbnail = new URL(thumbnailUrl); + thumbnail.searchParams.set("fit", "crop"); + thumbnail.searchParams.set("time", `${totalSeconds}s`); + + return ( +
  • + +
  • + ); + })} +
+

+
) } diff --git a/src/components/homepage/FeaturedContentSection.astro b/src/components/homepage/FeaturedContentSection.astro index b017f51839c2ccc..ba3851b109b4b45 100644 --- a/src/components/homepage/FeaturedContentSection.astro +++ b/src/components/homepage/FeaturedContentSection.astro @@ -63,7 +63,7 @@ const { title, text, image, cards, imagePosition } = props.parse(Astro.props);
diff --git a/src/components/index.ts b/src/components/index.ts index 5ba0fb539f0548c..a4e2ef5690b6a49 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -7,6 +7,7 @@ export { Icon as AstroIcon } from "astro-icon/components"; export { default as AnchorHeading } from "./AnchorHeading.astro"; export { default as APIRequest } from "./APIRequest.astro"; export { default as AvailableNotifications } from "./AvailableNotifications.astro"; +export { default as Checkbox } from "./Checkbox.astro"; export { default as CompatibilityFlag } from "./CompatibilityFlag.astro"; export { default as CompatibilityFlags } from "./CompatibilityFlags.astro"; export { default as ComponentUsage } from "./ComponentUsage.astro"; diff --git a/src/components/overrides/Footer.astro b/src/components/overrides/Footer.astro index ef0400e4270d833..a608644f80e5811 100644 --- a/src/components/overrides/Footer.astro +++ b/src/components/overrides/Footer.astro @@ -13,7 +13,7 @@ const groups = Object.entries({ text: "New to Cloudflare?", href: "/fundamentals/", }, - { text: "Products", href: "/products/" }, + { text: "Directory", href: "/directory/" }, { text: "Sponsorships", href: "/sponsorships/", diff --git a/src/components/overrides/Head.astro b/src/components/overrides/Head.astro index fa44c498bb54d09..870214beb093d5c 100644 --- a/src/components/overrides/Head.astro +++ b/src/components/overrides/Head.astro @@ -35,26 +35,28 @@ if (currentSection) { let product = await getEntry("products", currentSection); // if entry for changelog, grab the first product value (which corresponds to the folder the entry is in) and use as the primary "product" if (currentSection === "changelog") { - const products = frontmatter.products + const products = frontmatter.products; if (products) { product = await getEntry("products", products[0]); } } if (product) { - let productMetaName = product.data.meta.title ? product.data.meta.title : "Cloudflare Docs"; + let productMetaName = product.data.meta.title + ? product.data.meta.title + : "Cloudflare Docs"; if (currentSection === "changelog") { - productMetaName = "Changelog" + productMetaName = "Changelog"; } const titleIdx = head.findIndex((x) => x.tag === "title"); let title: string; // Prefer the title set via frontmatter.head.title. If not, grab the regular frontmatter title value. - const existingTitle = head[titleIdx].content ? head[titleIdx].content?.split( - ` ${DEFAULT_TITLE_DELIMITER} `, - )[0]: frontmatter.title; + const existingTitle = head[titleIdx].content + ? head[titleIdx].content?.split(` ${DEFAULT_TITLE_DELIMITER} `)[0] + : frontmatter.title; title = `${existingTitle} Β· ${productMetaName}`; @@ -128,8 +130,13 @@ if ( if (frontmatter.pcx_content_type) { ["pcx_content_type", "algolia_content_type"].map((name) => { - const contentType = frontmatter.pcx_content_type - const updatedName = contentType ? (contentType.charAt(0).toUpperCase() + contentType.slice(1)).replace("-", " ") : "" + const contentType = frontmatter.pcx_content_type; + const updatedName = contentType + ? (contentType.charAt(0).toUpperCase() + contentType.slice(1)).replace( + "-", + " ", + ) + : ""; metaTags.push({ name, content: updatedName, @@ -217,7 +224,6 @@ metaTags.map((attrs) => { attrs, }); }); - --- diff --git a/src/components/overrides/PageTitle.astro b/src/components/overrides/PageTitle.astro index 18ef3bd5c143b3b..b6272ca7d61d0e5 100644 --- a/src/components/overrides/PageTitle.astro +++ b/src/components/overrides/PageTitle.astro @@ -25,8 +25,8 @@ const slug = Astro.locals.starlightRoute.entry.slug; const breadcrumbProps: Record = { crumbs: [ { - text: "Products", - href: "/products/", + text: "Directory", + href: "/directory/", }, ], truncated: true, diff --git a/src/components/overrides/TableOfContents.astro b/src/components/overrides/TableOfContents.astro index fa7d65227bb6683..7fbf22e63213504 100644 --- a/src/components/overrides/TableOfContents.astro +++ b/src/components/overrides/TableOfContents.astro @@ -15,11 +15,11 @@ const showFeedback = Astro.locals.starlightRoute.entry.data.feedback;

Tags

-
+
{tags.map((tag) => ( {tag} diff --git a/src/content/changelog/access/2025-07-01-Access-Supports-Customer-Metadata-Boundary.mdx b/src/content/changelog/access/2025-07-01-Access-Supports-Customer-Metadata-Boundary.mdx new file mode 100644 index 000000000000000..c7f5ea93bac1254 --- /dev/null +++ b/src/content/changelog/access/2025-07-01-Access-Supports-Customer-Metadata-Boundary.mdx @@ -0,0 +1,13 @@ +--- +title: Cloudflare Access Logging supports the Customer Metadata Boundary (CMB) +description: Access logs will now respect the CMB. +date: 2025-08-14 +products: + - access +--- + +Cloudflare Access logs now support the [Customer Metadata Boundary (CMB)](/data-localization/metadata-boundary/). If you have configured the CMB for your account, all Access logging will respect that configuration. + +:::note +For EU CMB customers, the logs will not be stored by Access and will appear as empty in the dashboard. EU CMB customers should utilize [Logpush](/logs/logpush/) to retain their Access logging, if desired. +::: diff --git a/src/content/changelog/access/2025-08-15-sftp.mdx b/src/content/changelog/access/2025-08-15-sftp.mdx new file mode 100644 index 000000000000000..035c27d1175f33a --- /dev/null +++ b/src/content/changelog/access/2025-08-15-sftp.mdx @@ -0,0 +1,9 @@ +--- +title: SFTP support for SSH with Cloudflare Access for Infrastructure +description: SSH with Cloudflare Access for Infrastructure now supports SFTP for easy file transfer. +date: 2025-08-15 +products: + - access +--- + +[SSH with Cloudflare Access for Infrastructure](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/) now supports SFTP. It is compatible with SFTP clients, such as Cyberduck. diff --git a/src/content/changelog/load-balancing/2025-08-06-zone-monitoring-improvements.mdx b/src/content/changelog/load-balancing/2025-08-06-zone-monitoring-improvements.mdx new file mode 100644 index 000000000000000..116a5fc681ec152 --- /dev/null +++ b/src/content/changelog/load-balancing/2025-08-06-zone-monitoring-improvements.mdx @@ -0,0 +1,20 @@ +--- +title: Improvements to Monitoring Using Zone Settings +description: Monitors configured with a probe zone have been migrated to new infrastructure. +date: 2025-08-06 +--- + +Cloudflare Load Balancing Monitors support loading and applying settings for a specific zone to monitoring requests to origin endpoints. This feature has been migrated to new infrastructure to improve reliability, performance, and accuracy. + +All zone monitors have been tested against the new infrastructure. There should be no change to health monitoring results of currently healthy and active pools. Newly created or re-enabled pools may need validation of their monitor zone settings before being introduced to service, especially regarding correct application of mTLS. + +### What you can expect: + +- More reliable application of zone settings to monitoring requests, including + - Authenticated Origin Pulls + - Aegis Egress IP Pools + - Argo Smart Routing + - HTTP/2 to Origin +- Improved support and bug fixes for retries, redirects, and proxied origin resolution +- Improved performance and reliability of monitoring requests withing the Cloudflare network +- Unrelated CDN or WAF configuration changes should have no risk of impact to pool health diff --git a/src/content/changelog/load-balancing/2025-08-15-asnum-support-in-custom-rules.mdx b/src/content/changelog/load-balancing/2025-08-15-asnum-support-in-custom-rules.mdx new file mode 100644 index 000000000000000..18fd58970b0d2ce --- /dev/null +++ b/src/content/changelog/load-balancing/2025-08-15-asnum-support-in-custom-rules.mdx @@ -0,0 +1,15 @@ +--- +title: Steer Traffic by AS Number in Load Balancing Custom Rules +description: You can now create Load Balancing custom rules to steer traffic based on the incoming request's Autonomous System Number (ASN). +date: 2025-08-15 +products: + - load-balancing +--- + +You can now create more granular, network-aware Custom Rules in Cloudflare Load Balancing using the Autonomous System Number (ASN) of an incoming request. + +This allows you to steer traffic with greater precision based on the network source of a request. For example, you can route traffic from specific Internet Service Providers (ISPs) or enterprise customers to dedicated infrastructure, optimize performance, or enforce compliance by directing certain networks to preferred data centers. + +![Create a Load Balancing Custom Rule using AS Num](~/assets/images/changelog/load-balancing/asnum-custom-rule.png) + +To get started, create a [Custom Rule](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) in your Load Balancer and select **AS Num** from the **Field** dropdown. diff --git a/src/content/changelog/security-center/2025-08-15-brand-protection-bulk-endpoint.mdx b/src/content/changelog/security-center/2025-08-15-brand-protection-bulk-endpoint.mdx new file mode 100644 index 000000000000000..fa70bedd4c01069 --- /dev/null +++ b/src/content/changelog/security-center/2025-08-15-brand-protection-bulk-endpoint.mdx @@ -0,0 +1,9 @@ +--- +title: Save time with bulk query creation in Brand Protection +description: Quickly create and save multiple Brand Protection queries via API. +date: 2025-08-15 +--- + +[Brand Protection](/security-center/brand-protection/) detects domains that may be impersonating your brand β€” from common misspellings (`cloudfalre.com`) to malicious concatenations (`cloudflare-okta.com`). Saved search queries run continuously and alert you when suspicious domains appear. + +You can now create and save multiple queries in a single step, streamlining setup and management. Available now via the [Brand Protection bulk query creation API](/api/resources/brand_protection/subresources/queries/methods/bulk/). diff --git a/src/content/changelog/waf/2025-08-18-waf-release.mdx b/src/content/changelog/waf/2025-08-18-waf-release.mdx new file mode 100644 index 000000000000000..6d4e3285ef8306e --- /dev/null +++ b/src/content/changelog/waf/2025-08-18-waf-release.mdx @@ -0,0 +1,169 @@ +--- +title: "WAF Release - 2025-08-18" +description: Cloudflare WAF managed rulesets 2025-08-18 release +date: 2025-08-18 +--- + +import { RuleID } from "~/components"; + +This week's update + +This week, a series of critical vulnerabilities were discovered impacting core enterprise and open-source infrastructure. These flaws present a range of risks, providing attackers with distinct pathways for remote code execution, methods to breach internal network boundaries, and opportunities for critical data exposure and operational disruption. + + +**Key Findings** + +- SonicWall SMA (CVE-2025-32819, CVE-2025-32820, CVE-2025-32821): A remote authenticated attacker with SSLVPN user privileges can bypass path traversal protections. These vulnerabilities enable a attacker to bypass security checks to read, modify, or delete arbitrary files. An attacker with administrative privileges can escalate this further, using a command injection flaw to upload malicious files, which could ultimately force the appliance to reboot to its factory default settings. + +- Ms-Swift Project (CVE-2025-50460): An unsafe deserialization vulnerability exists in the Ms-Swift project's handling of YAML configuration files.If an attacker can control the content of a configuration file passed to the application, they can embed a malicious payload that will execute arbitrary code and it can be executed during deserialization. + +- Apache Druid (CVE-2023-25194): This vulnerability in Apache Druid allows an attacker to cause the server to connect to a malicious LDAP server. By sending a specially crafted LDAP response, the attacker can trigger an unrestricted deserialization of untrusted data. If specific "gadgets" (classes that can be abused) are present in the server's classpath, this can be escalated to achieve Remote Code Execution (RCE). + +- Tenda AC8v4 (CVE-2025-51087, CVE-2025-51088): Vulnerabilities allow an authenticated attacker to trigger a stack-based buffer overflow. By sending malformed arguments in a request to specific endpoints, an attacker can crash the device or potentially achieve arbitrary code execution. + +- Open WebUI (CVE-2024-7959): This vulnerability allows a user to change the OpenAI URL endpoint to an arbitrary internal network address without proper validation. This flaw can be exploited to access internal services or cloud metadata endpoints, potentially leading to remote command execution if the attacker can retrieve instance secrets or access sensitive internal APIs. + +- BentoML (CVE-2025-54381): The vulnerability exists in the serialization/deserialization handlers for multipart form data and JSON requests, which automatically download files from user-provided URLs without proper validation of internal network addresses. This allowing attackers to fetch from unintended internal servicesβ€”including cloud metadata and localhost. + +- Adobe Experience Manager Forms (CVE-2025-54254): AN Improper Restriction of XML External Entity Reference ('XXE') vulnerability that could lead to arbitrary file system read in Adobe AEM (≀6.5.23). + +**Impact** + +These vulnerabilities affect core infrastructure, from network security appliances like SonicWall to data platforms such as Apache Druid and ML frameworks like BentoML. The code execution and deserialization flaws are particularly severe, offering deep system access that allows attackers to steal data, disrupt services, and establish a foothold for broader intrusions. Simultaneously, SSRF and XXE vulnerabilities undermine network boundaries, exposing sensitive internal data and creating pathways for lateral movement. Beyond data-centric threats, flaws in edge devices like the Tenda router introduce the tangible risk of operational disruption, highlighting a multi-faceted threat to the security and stability of key enterprise systems. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
Cloudflare Managed Ruleset + + 100574SonicWall SMA - Remote Code Execution - CVE:CVE-2025-32819, CVE:CVE-2025-32820, CVE:CVE-2025-32821LogDisabledThis is a New Detection
Cloudflare Managed Ruleset + + 100576Ms-Swift Project - Remote Code Execution - CVE:CVE-2025-50460LogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100585Apache Druid - Remote Code Execution - CVE:CVE-2023-25194LogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100834Tenda AC8v4 - Auth Bypass - CVE:CVE-2025-51087, CVE:CVE-2025-51088LogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100835Open WebUI - SSRF - CVE:CVE-2024-7959LogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100837SQLi - OOBLogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100841BentoML - SSRF - CVE:CVE-2025-54381LogDisabledThis is a New Detection
Cloudflare Managed Ruleset + + 100841ABentoML - SSRF - CVE:CVE-2025-54381 - 2LogDisabledThis is a New Detection
Cloudflare Managed Ruleset + + 100841BBentoML - SSRF - CVE:CVE-2025-54381 - 3LogDisabledThis is a New Detection
Cloudflare Managed Ruleset + + 100845Adobe Experience Manager Forms - XSS - CVE:CVE-2025-54254LogBlockThis is a New Detection
Cloudflare Managed Ruleset + + 100845AAdobe Experience Manager Forms - XSS - CVE:CVE-2025-54254 - 2LogBlockThis is a New Detection
\ No newline at end of file diff --git a/src/content/changelog/waf/scheduled-waf-release.mdx b/src/content/changelog/waf/scheduled-waf-release.mdx index 2d5b893d461a3fe..45e67e4563713af 100644 --- a/src/content/changelog/waf/scheduled-waf-release.mdx +++ b/src/content/changelog/waf/scheduled-waf-release.mdx @@ -1,7 +1,7 @@ --- -title: WAF Release - Scheduled changes for 2025-08-18 -description: WAF managed ruleset changes scheduled for 2025-08-18 -date: 2025-08-11 +title: WAF Release - Scheduled changes for 2025-08-25 +description: WAF managed ruleset changes scheduled for 2025-08-25 +date: 2025-08-18 scheduled: true --- @@ -21,124 +21,36 @@ import { RuleID } from "~/components"; - 2025-08-11 2025-08-18 + 2025-08-25 Log - 100574 + 100822_BETA - + - SonicWall SMA - Remote Code Execution - CVE:CVE-2025-32819, CVE:CVE-2025-32820, CVE:CVE-2025-32821 + WordPress:Plugin:WPBookit - Remote Code Execution - CVE:CVE-2025-6058 This is a New Detection - 2025-08-11 2025-08-18 + 2025-08-25 Log - 100576 + 100831 - + - Ms-Swift Project - Remote Code Execution - CVE:CVE-2025-50460 + Apache HTTP Server - Code Execution - CVE:CVE-2024-38474 This is a New Detection - 2025-08-11 2025-08-18 + 2025-08-25 Log - 100585 + 100846 - + - Apache Druid - Remote Code Execution - CVE:CVE-2023-25194 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100834 - - - - Tenda AC8v4 - Auth Bypass - CVE:CVE-2025-51087, CVE:CVE-2025-51088 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100835 - - - - Open WebUI - SSRF - CVE:CVE-2024-7959 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100837 - - - - SQLi - OOB - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100841 - - - - BentoML - SSRF - CVE:CVE-2025-54381 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100841A - - - - BentoML - SSRF - CVE:CVE-2025-54381 - 2 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100841B - - - - BentoML - SSRF - CVE:CVE-2025-54381 - 3 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100845 - - - - Adobe Experience Manager Forms - XSS - CVE:CVE-2025-54254 - This is a New Detection - - - 2025-08-11 - 2025-08-18 - Log - 100845A - - - - Adobe Experience Manager Forms - XSS - CVE:CVE-2025-54254 - 2 + Laravel - Remote Code Execution - CVE:CVE-2024-55661 This is a New Detection diff --git a/src/content/changelog/workers/2025-08-08-support-long-branch-names-preview-aliases.mdx b/src/content/changelog/workers/2025-08-08-support-long-branch-names-preview-aliases.mdx new file mode 100644 index 000000000000000..4b869cc6a72861c --- /dev/null +++ b/src/content/changelog/workers/2025-08-08-support-long-branch-names-preview-aliases.mdx @@ -0,0 +1,25 @@ +--- +title: Workers per-branch preview URLs now support long branch names +description: Branch names that create URLs longer than 63 characters now get hash-based preview URLs instead of failing, ensuring every pull request has a working preview link. +tags: + - workers +date: 2025-08-14T01:00:00Z +--- + +We've updated [preview URLs](/workers/configuration/previews/) for Cloudflare Workers to support long branch names. + +Previously, branch and Worker names exceeding the 63-character DNS limit would cause alias generation to fail, leaving pull requests without aliased preview URLs. This particularly impacted teams relying on descriptive branch naming. + +Now, Cloudflare automatically truncates long branch names and appends a unique hash, ensuring every pull request gets a working preview link. + +## How it works + +- **63 characters or less**: `-` β†’ Uses actual branch name as is +- **64 characters or more**: `---` β†’ Uses truncated name with 4-character hash +- **Hash generation**: The hash is derived from the full branch name to ensure uniqueness +- **Stable URLs**: The same branch always generates the same hash across all commits + +## Requirements and compatibility + +- **Wrangler 4.30.0 or later**: This feature requires updating to wrangler@4.30.0+ +- **No configuration needed**: Works automatically with existing preview URL setups \ No newline at end of file diff --git a/src/content/changelog/workers/2025-08-14-workers-terraform-and-sdk-improvements.mdx b/src/content/changelog/workers/2025-08-14-workers-terraform-and-sdk-improvements.mdx new file mode 100644 index 000000000000000..71100f87446e32c --- /dev/null +++ b/src/content/changelog/workers/2025-08-14-workers-terraform-and-sdk-improvements.mdx @@ -0,0 +1,133 @@ +--- +title: Terraform provider improvementsΒ β€”Β Python Workers support, smaller plan diffs, and API SDK fixes +description: Multiple improvements to the Workers Terraform resources and SDKs including fixes for plan diffs, file uploads, and Python Workers support. +products: + - workers +date: 2025-08-14 +--- + +The recent [Cloudflare Terraform Provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/workers_script) and SDK releases (such as [cloudflare-typescript](https://github.com/cloudflare/cloudflare-typescript)) bring significant improvements to the Workers developer experience. These updates focus on reliability, performance, and adding [Python Workers](/workers/languages/python/) support. + +## Terraform Improvements + +### Fixed Unwarranted Plan Diffs + +Resolved several issues with the `cloudflare_workers_script` resource that resulted in unwarranted plan diffs, including: + +- Using Durable Objects migrations +- Using some bindings such as `secret_text` +- Using smart placement + +A resource should never show a plan diff if there isn't an actual change. This fix reduces unnecessary noise in your Terraform plan and is available in Cloudflare Terraform Provider 5.8.0. + +### Improved File Management + +You can now specify `content_file` and `content_sha256` instead of `content`. This prevents the Workers script content from being stored in the state file which greatly reduces plan diff size and noise. If your workflow synced plans remotely, this should now happen much faster since there is less data to sync. This is available in Cloudflare Terraform Provider 5.7.0. + +```tf +resource "cloudflare_workers_script" "my_worker" { + account_id = "123456789" + script_name = "my_worker" + main_module = "worker.mjs" + content_file = "worker.mjs" + content_sha256 = filesha256("worker.mjs") +} +``` + +### Assets Headers and Redirects Support + +Fixed the `cloudflare_workers_script` resource to properly support headers and redirects for Assets: + +```tf +resource "cloudflare_workers_script" "my_worker" { + account_id = "123456789" + script_name = "my_worker" + main_module = "worker.mjs" + content_file = "worker.mjs" + content_sha256 = filesha256("worker.mjs") + assets = { + config = { + headers = file("_headers") + redirects = file("_redirects") + } + # Completion jwt from: + # https://developers.cloudflare.com/api/resources/workers/subresources/assets/subresources/upload/ + jwt = "jwt" + } +} +``` + +Available in Cloudflare Terraform Provider 5.8.0. + +### Python Workers Support + +Added support for uploading [Python Workers](/workers/languages/python/) (beta) in Terraform. You can now deploy Python Workers with: + +```tf +resource "cloudflare_workers_script" "my_worker" { + account_id = "123456789" + script_name = "my_worker" + content_file = "worker.py" + content_sha256 = filesha256("worker.py") + content_type = "text/x-python" +} +``` + +Available in Cloudflare Terraform Provider 5.8.0. + +## SDK Enhancements + +### Improved File Upload API + +Fixed an issue where Workers script versions in the SDK did not allow uploading files. This now works, and also has an improved files upload interface: + +```js +const scriptContent = ` + export default { + async fetch(request, env, ctx) { + return new Response('Hello World!', { status: 200 }); + } + }; +`; + +client.workers.scripts.versions.create('my-worker', { + account_id: '123456789', + metadata: { + main_module: 'my-worker.mjs', + }, + files: [ + await toFile( + Buffer.from(scriptContent), + 'my-worker.mjs', + { + type: "application/javascript+module", + } + ) + ] +}); +``` + +Will be available in cloudflare-typescript 4.6.0. A similar change will be available in cloudflare-python 4.4.0. + +### Fixed updating KV values + +Previously when creating a KV value like this: + +```js +await cf.kv.namespaces.values.update("my-kv-namespace", "key1", { + account_id: "123456789", + metadata: "my metadata", + value: JSON.stringify({ + hello: "world" + }) +}); +``` + +...and recalling it in your Worker like this: +```ts +const value = await c.env.KV.get<{hello: string}>("key1", "json"); +``` + +You'd get back this: `{metadata:'my metadata', value:"{'hello':'world'}"}` instead of the correct value of `{hello: 'world'}` + +This is fixed in cloudflare-typescript 4.5.0 and will be fixed in cloudflare-python 4.4.0. diff --git a/src/content/docs/1.1.1.1/infrastructure/ipv6-networks.mdx b/src/content/docs/1.1.1.1/infrastructure/ipv6-networks.mdx index 1213a091789bf01..7a9131d48905b2b 100644 --- a/src/content/docs/1.1.1.1/infrastructure/ipv6-networks.mdx +++ b/src/content/docs/1.1.1.1/infrastructure/ipv6-networks.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: reference title: Support for IPv6-only networks +tags: + - IPv6 sidebar: order: 3 slug: 1.1.1.1/infrastructure/ipv6-networks diff --git a/src/content/docs/aegis/about/ips-allocation.mdx b/src/content/docs/aegis/about/ips-allocation.mdx index ad833699160b570..905da97fdfa354f 100644 --- a/src/content/docs/aegis/about/ips-allocation.mdx +++ b/src/content/docs/aegis/about/ips-allocation.mdx @@ -1,6 +1,8 @@ --- title: IPs allocation pcx_content_type: concept +tags: + - IPv6 sidebar: order: 2 head: diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx index b9956d96b606467..97fd66c5262cdf4 100644 --- a/src/content/docs/agents/concepts/calling-llms.mdx +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -1,6 +1,8 @@ --- title: Calling LLMs pcx_content_type: concept +tags: + - LLM sidebar: order: 6 diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index 5bd4d932fe6602e..d290f2b81e94558 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -1,6 +1,9 @@ --- title: Agents pcx_content_type: concept +tags: + - AI + - LLM sidebar: order: 2 diff --git a/src/content/docs/agents/guides/remote-mcp-server.mdx b/src/content/docs/agents/guides/remote-mcp-server.mdx index 2dc474c8bd56467..aa8b3899de19e94 100644 --- a/src/content/docs/agents/guides/remote-mcp-server.mdx +++ b/src/content/docs/agents/guides/remote-mcp-server.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: Build a Remote MCP server +tags: + - MCP sidebar: order: 4 --- diff --git a/src/content/docs/agents/guides/test-remote-mcp-server.mdx b/src/content/docs/agents/guides/test-remote-mcp-server.mdx index 5a5c8e07e12eb46..a351ea7cbb59752 100644 --- a/src/content/docs/agents/guides/test-remote-mcp-server.mdx +++ b/src/content/docs/agents/guides/test-remote-mcp-server.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: Test a Remote MCP Server +tags: + - MCP sidebar: order: 6 --- diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 02c623e1ed2d9d7..c4f2452d8c3eebe 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -1,6 +1,6 @@ --- title: Build Agents on Cloudflare -type: overview + pcx_content_type: overview tags: - AI diff --git a/src/content/docs/agents/model-context-protocol/authorization.mdx b/src/content/docs/agents/model-context-protocol/authorization.mdx index fef350175217390..860cbe122db8fc9 100644 --- a/src/content/docs/agents/model-context-protocol/authorization.mdx +++ b/src/content/docs/agents/model-context-protocol/authorization.mdx @@ -1,5 +1,7 @@ --- title: Authorization +tags: + - MCP sidebar: order: 2 group: diff --git a/src/content/docs/agents/model-context-protocol/index.mdx b/src/content/docs/agents/model-context-protocol/index.mdx index b34d16375f8b955..1326b2f97a64a56 100644 --- a/src/content/docs/agents/model-context-protocol/index.mdx +++ b/src/content/docs/agents/model-context-protocol/index.mdx @@ -1,6 +1,8 @@ --- title: Model Context Protocol (MCP) pcx_content_type: navigation +tags: + - MCP sidebar: order: 4 group: diff --git a/src/content/docs/agents/model-context-protocol/mcp-agent-api.mdx b/src/content/docs/agents/model-context-protocol/mcp-agent-api.mdx index a6c0e12261d40dd..cbfd64c8dc34049 100644 --- a/src/content/docs/agents/model-context-protocol/mcp-agent-api.mdx +++ b/src/content/docs/agents/model-context-protocol/mcp-agent-api.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: McpAgent β€” API Reference +tags: + - MCP sidebar: order: 6 --- diff --git a/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx b/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx index 1353c95f6d79949..b1b8bd054b0a8da 100644 --- a/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx +++ b/src/content/docs/agents/model-context-protocol/mcp-servers-for-cloudflare.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: Cloudflare's own MCP servers +tags: + - MCP sidebar: order: 100 diff --git a/src/content/docs/agents/model-context-protocol/transport.mdx b/src/content/docs/agents/model-context-protocol/transport.mdx index 4a608cb36a3c4ff..627a12064933862 100644 --- a/src/content/docs/agents/model-context-protocol/transport.mdx +++ b/src/content/docs/agents/model-context-protocol/transport.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: Transport +tags: + - MCP sidebar: order: 5 --- diff --git a/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-ai-owner/connect-to-stripe.mdx b/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-ai-owner/connect-to-stripe.mdx index 22f2998b0e490fc..94f30d136e20d04 100644 --- a/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-ai-owner/connect-to-stripe.mdx +++ b/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-ai-owner/connect-to-stripe.mdx @@ -1,6 +1,8 @@ --- title: Connect Stripe pcx_content_type: concept +tags: + - Stripe sidebar: order: 4 --- diff --git a/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-site-owner/connect-to-stripe.mdx b/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-site-owner/connect-to-stripe.mdx index 2a297c60ecb50a9..6bc49a773cda530 100644 --- a/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-site-owner/connect-to-stripe.mdx +++ b/src/content/docs/ai-audit/features/pay-per-crawl/use-pay-per-crawl-as-site-owner/connect-to-stripe.mdx @@ -1,6 +1,8 @@ --- title: Connect Stripe pcx_content_type: concept +tags: + - Stripe sidebar: order: 4 --- diff --git a/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/index.mdx b/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/index.mdx index 487911efbaf43fb..d2777fecbd889da 100644 --- a/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/index.mdx +++ b/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/index.mdx @@ -1,5 +1,5 @@ --- -type: overview + pcx_content_type: reference title: Network Analytics v1 to Network Analytics v2 sidebar: diff --git a/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/schema-map.mdx b/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/schema-map.mdx index 2a2d682d545e45f..8614be7b89b5b72 100644 --- a/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/schema-map.mdx +++ b/src/content/docs/analytics/graphql-api/migration-guides/network-analytics-v2/schema-map.mdx @@ -1,5 +1,5 @@ --- -type: overview + pcx_content_type: reference title: NAv1 to NAv2 schema map sidebar: diff --git a/src/content/docs/api-shield/api-gateway.mdx b/src/content/docs/api-shield/api-gateway.mdx index 91983eb2ff3c64d..de26e0cc8e82249 100644 --- a/src/content/docs/api-shield/api-gateway.mdx +++ b/src/content/docs/api-shield/api-gateway.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: API Gateway sidebar: order: 7 diff --git a/src/content/docs/api-shield/index.mdx b/src/content/docs/api-shield/index.mdx index 710be1f0347418f..2d12f7fe6fcc133 100644 --- a/src/content/docs/api-shield/index.mdx +++ b/src/content/docs/api-shield/index.mdx @@ -1,7 +1,7 @@ --- title: Cloudflare API Shield pcx_content_type: overview -type: overview + sidebar: order: 1 head: @@ -12,7 +12,7 @@ head: import { Description, Feature, Plan, RelatedProduct, Render } from "~/components" -Identify and address your API vulnerabilities. +Identify and address your API vulnerabilities. @@ -35,7 +35,7 @@ Refer to the [Get started](/api-shield/get-started/) guide to set up API Shield. ## Features -Secure your APIs using API Shield's security features. +Secure your APIs using API Shield's security features. @@ -51,5 +51,5 @@ The full API Shield security suite is available as an Enterprise-only paid add-o ## Related products -Cloudflare DDoS protection secures websites, applications, and entire networks while ensuring the performance of legitimate traffic is not compromised. +Cloudflare DDoS protection secures websites, applications, and entire networks while ensuring the performance of legitimate traffic is not compromised. diff --git a/src/content/docs/api-shield/management-and-monitoring/api-routing.mdx b/src/content/docs/api-shield/management-and-monitoring/api-routing.mdx index a2a5856651b7c4e..8e34dcf45cf0ec3 100644 --- a/src/content/docs/api-shield/management-and-monitoring/api-routing.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/api-routing.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -type: overview + title: API Routing sidebar: order: 4 diff --git a/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx b/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx index 3f63d53d7873822..3a1be490822db5a 100644 --- a/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -type: overview + title: Build developer portals sidebar: order: 5 diff --git a/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx b/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx index 21a727fccefa3d3..2f7fd68a961a3ad 100644 --- a/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -type: overview + title: Endpoint labeling service sidebar: order: 2 diff --git a/src/content/docs/api-shield/management-and-monitoring/endpoint-management/index.mdx b/src/content/docs/api-shield/management-and-monitoring/endpoint-management/index.mdx index 9d4f307cd5874ee..c17815dba30ad97 100644 --- a/src/content/docs/api-shield/management-and-monitoring/endpoint-management/index.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/endpoint-management/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Endpoint Management sidebar: order: 1 diff --git a/src/content/docs/api-shield/management-and-monitoring/endpoint-management/schema-learning.mdx b/src/content/docs/api-shield/management-and-monitoring/endpoint-management/schema-learning.mdx index 73e25d2c2881999..f5b7cf8541cf5a4 100644 --- a/src/content/docs/api-shield/management-and-monitoring/endpoint-management/schema-learning.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/endpoint-management/schema-learning.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Schema learning sidebar: order: 2 diff --git a/src/content/docs/api-shield/management-and-monitoring/session-identifiers.mdx b/src/content/docs/api-shield/management-and-monitoring/session-identifiers.mdx index f6ea8a528b15c10..df908a87bde50ec 100644 --- a/src/content/docs/api-shield/management-and-monitoring/session-identifiers.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/session-identifiers.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -type: overview + title: Session identifiers sidebar: order: 3 diff --git a/src/content/docs/api-shield/plans.mdx b/src/content/docs/api-shield/plans.mdx index d08b0c770da8c62..5d23dfed7ba4a07 100644 --- a/src/content/docs/api-shield/plans.mdx +++ b/src/content/docs/api-shield/plans.mdx @@ -1,7 +1,7 @@ --- title: Plans pcx_content_type: overview -type: overview + sidebar: order: 3 @@ -11,7 +11,7 @@ Free, Pro, Business, and Enterprise customers without an API Shield subscription To subscribe to API Shield, upgrade to an Enterprise plan and contact your account team. -Limits to endpoints apply to Endpoint Management and Schema validation. Refer to the table below for limits based on your zone plan. +Limits to endpoints apply to Endpoint Management and Schema validation. Refer to the table below for limits based on your zone plan. | Plan type | Saved endpoints | Uploaded schemas | Total uploaded schema size | Rule action | | --- | --- | --- | --- | --- | diff --git a/src/content/docs/api-shield/reference/classic-schema-validation.mdx b/src/content/docs/api-shield/reference/classic-schema-validation.mdx index 3c249bb043148f5..51087e442c75689 100644 --- a/src/content/docs/api-shield/reference/classic-schema-validation.mdx +++ b/src/content/docs/api-shield/reference/classic-schema-validation.mdx @@ -1,7 +1,7 @@ --- title: Classic Schema validation (deprecated) pcx_content_type: how-to -type: overview + head: - tag: title content: Configure Classic Schema validation (deprecated) @@ -9,16 +9,16 @@ sidebar: badge: text: Deprecated order: 1 - label: Classic Schema validation + label: Classic Schema validation --- import { GlossaryTooltip } from "~/components" :::caution[Deprecation notice] -Classic Schema validation has been deprecated. +Classic Schema validation has been deprecated. -Upload all new schemas to [Schema validation 2.0](/api-shield/security/schema-validation/). +Upload all new schemas to [Schema validation 2.0](/api-shield/security/schema-validation/). ::: Use the **API Shield** interface to configure [API Schema validation](/api-shield/security/schema-validation/), which validates requests according to the API schema you provide. @@ -29,7 +29,7 @@ If you are in the Schema validation 2.0, you can make changes to your settings b :::note -This feature is only available for customers on an Enterprise plan. Contact your Cloudflare Customer Success Manager to get access. +This feature is only available for customers on an Enterprise plan. Contact your Cloudflare Customer Success Manager to get access. ::: ## Create an API Shield with Schema validation @@ -42,7 +42,7 @@ To configure Schema validation in the Cloudflare dashboard: 4. Enter a descriptive name for your policy and optionally edit the expression to trigger Schema validation. For example, if your API is available at `http://api.example.com/v1`, include a check for the *Hostname* field β€” equal to `api.example.com` β€” and a check for the *URI Path* field using a regular expression β€” matching the regex `^/v1`. :::caution[Important] -To validate the hostname, you must include the *Hostname* field explicitly in the rule, even if the hostname value is in the schema file. Any hostname value present in the schema file will be ignored. +To validate the hostname, you must include the *Hostname* field explicitly in the rule, even if the hostname value is in the schema file. Any hostname value present in the schema file will be ignored. ::: 5. Select **Next**. 6. Upload your schema file. diff --git a/src/content/docs/api-shield/security/api-discovery.mdx b/src/content/docs/api-shield/security/api-discovery.mdx index 7da2766713915a4..4419cd98a959653 100644 --- a/src/content/docs/api-shield/security/api-discovery.mdx +++ b/src/content/docs/api-shield/security/api-discovery.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: API Discovery sidebar: order: 1 @@ -59,7 +59,7 @@ API Discovery is an ongoing process. Check back regularly for new API Discovery :::note -Cloudflare will use your feedback on the ignored endpoints to better train the API Discovery Machine Learning model in a future release. +Cloudflare will use your feedback on the ignored endpoints to better train the API Discovery Machine Learning model in a future release. ::: ### Machine Learning-based Discovery @@ -71,14 +71,14 @@ To access Machine Learning-based Discovery: - 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain. - 2. Go to **API Shield** > **Discovery**. + 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain. + 2. Go to **API Shield** > **Discovery**. 3. Filter the source results by `Session Identifier` or `Machine Learning` to view results from each Discovery method. - 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain. + 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain. 2. Go to **Web assets** > **Discovery** 3. Filter the source results by `Session Identifier` or `Machine Learning` to view results from each Discovery method. diff --git a/src/content/docs/api-shield/security/authentication-posture.mdx b/src/content/docs/api-shield/security/authentication-posture.mdx index 641f41df9fe78c7..25a1b60b754e31f 100644 --- a/src/content/docs/api-shield/security/authentication-posture.mdx +++ b/src/content/docs/api-shield/security/authentication-posture.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Authentication Posture sidebar: order: 9 @@ -32,7 +32,7 @@ After configuring [session identifiers](/api-shield/get-started/#session-identif 4. Select an endpoint to see its authentication posture details on the endpoint details page. 5. Choose between the 24-hour and 7-day view options, and note any authentication changes over time. - + 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account and domain. @@ -44,7 +44,7 @@ After configuring [session identifiers](/api-shield/get-started/#session-identif -The main authentication widget displays how many successful requests over the last seven days had session identifiers included with them, and which identifiers were included with the traffic. +The main authentication widget displays how many successful requests over the last seven days had session identifiers included with them, and which identifiers were included with the traffic. The authentication-over-time chart shows a detailed breakdown over time of how clients successfully interacted with your API and which identifiers were used. A large increase in unauthenticated traffic may signal a security incident. Similarly, any successful unauthenticated traffic on an endpoint that is expected to be 100% authenticated can be a cause for concern. @@ -58,6 +58,6 @@ You can use the `cf.api_gateway.auth_id_present` field in [custom rules](/waf/cu Authentication Posture can only apply when customers accurately set up session identifiers in API Shield. As a reminder, session identifiers are meant to uniquely identify authenticated users of your API. If you are unsure of your API's session identifier, consult with your development team. -## Availability +## Availability Authentication Posture is available for all Enterprise subscriptions with API Shield. \ No newline at end of file diff --git a/src/content/docs/api-shield/security/bola-vulnerability-detection.mdx b/src/content/docs/api-shield/security/bola-vulnerability-detection.mdx index 8a6e54db38f11d6..8873b893fbd8d0d 100644 --- a/src/content/docs/api-shield/security/bola-vulnerability-detection.mdx +++ b/src/content/docs/api-shield/security/bola-vulnerability-detection.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Broken Object Level Authorization vulnerability detection sidebar: badge: @@ -21,14 +21,14 @@ BOLA vulnerabilities are as dangerous as an account takeover. Successfully explo Cloudflare labels endpoints with BOLA risk when we detect two distinct signals common with attacks exploiting BOLA: **Parameter pollution** and **Enumeration**. -- **Parameter pollution**: Cloudflare detects anomalies where one or more successful requests containing a value in an expected path, query string or header have that value duplicated in an unexpected, similar location. +- **Parameter pollution**: Cloudflare detects anomalies where one or more successful requests containing a value in an expected path, query string or header have that value duplicated in an unexpected, similar location. This behavior may be indicative of attackers trying to confuse the API’s authorization system and bypass security controls. - **Enumeration**: Cloudflare continually profiles all sessions on a per-endpoint basis and detects anomalous sessions that successfully request many unique data points from an API endpoint against what is normal. :::note -Sessions that have more random behavior or repetition have a higher chance of triggering an alert. +Sessions that have more random behavior or repetition have a higher chance of triggering an alert. The BOLA enumeration label requires an endpoint to have seen at least 10,000 sessions before being eligible for outlier detection. ::: diff --git a/src/content/docs/api-shield/security/graphql-protection/api.mdx b/src/content/docs/api-shield/security/graphql-protection/api.mdx index 7360ef12d37e7b3..cdd4974369bd197 100644 --- a/src/content/docs/api-shield/security/graphql-protection/api.mdx +++ b/src/content/docs/api-shield/security/graphql-protection/api.mdx @@ -1,7 +1,7 @@ --- title: Configure GraphQL malicious query protection via the API pcx_content_type: how-to -type: overview + sidebar: order: 2 label: API diff --git a/src/content/docs/api-shield/security/index.mdx b/src/content/docs/api-shield/security/index.mdx index c497a5b1d192989..f761902c1a6a809 100644 --- a/src/content/docs/api-shield/security/index.mdx +++ b/src/content/docs/api-shield/security/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: navigation -type: overview + title: Security sidebar: order: 4 diff --git a/src/content/docs/api-shield/security/jwt-validation/api.mdx b/src/content/docs/api-shield/security/jwt-validation/api.mdx index fbc3f0b1e530665..d28c54587a5345d 100644 --- a/src/content/docs/api-shield/security/jwt-validation/api.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/api.mdx @@ -1,7 +1,7 @@ --- title: Configure JWT validation via the API pcx_content_type: how-to -type: overview + sidebar: order: 2 label: API @@ -21,7 +21,7 @@ A token configuration defines a JSON Web Key Set (JWKs), which is used to valida :::note -A zone may have up to four token configurations. +A zone may have up to four token configurations. ::: Token configurations require the following information: @@ -179,7 +179,7 @@ To find the operation ID, refer to [Endpoint Management](/api-shield/management- A request must also match an operation covered by this rule to trigger an action. -Refer to [Apply a rule to operations](#apply-a-rule-to-operations) for more information. +Refer to [Apply a rule to operations](#apply-a-rule-to-operations) for more information. ::: A token validation rule's expression defines a security policy that a request must meet. @@ -234,7 +234,7 @@ You can configure which operations JWT validation is enforced on using the `sele :::note -Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that token validation rule. +Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that token validation rule. ::: For example, the following selector will apply a rule to all operations in `v1.example.com` and `v2.example.com`, except for two operations on these hosts: @@ -522,7 +522,7 @@ The input to updating the keys is the same as when creating a configuration wher Cloudflare will remove any fields that are unnecessary from each key and will drop keys that we do not support. -It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended. +It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended. ::: Use the `PUT` command to update keys. @@ -624,7 +624,7 @@ Here is an overview of how JWT validation processes incoming requests: :::note -The absence of matching keys directly marks the JWT as invalid. +The absence of matching keys directly marks the JWT as invalid. ::: 4. We validate the authenticity of the JWT by checking the signature using the selected key. @@ -632,14 +632,14 @@ The absence of matching keys directly marks the JWT as invalid. :::note -We allow a mismatch of up to 60 seconds to account for clock drifts between the Cloudflare network and the JWT issuer. A token may still be regarded as valid one minute after it was supposed to expire when both clocks are perfectly in sync. +We allow a mismatch of up to 60 seconds to account for clock drifts between the Cloudflare network and the JWT issuer. A token may still be regarded as valid one minute after it was supposed to expire when both clocks are perfectly in sync. ::: 6. Should the JWT contain a NBF claim (not before time), we validate that the JWT is already valid. :::note -The same accuracy applies as for EXP claims. As such, a token may be already regarded as valid one minute before its NBF claim in case of perfect synchronization between issuer and validator. +The same accuracy applies as for EXP claims. As such, a token may be already regarded as valid one minute before its NBF claim in case of perfect synchronization between issuer and validator. ::: 7. The final validation result and whether a token was present at all is made available to the WAF which applies the policy’s configured action (`log`/`block`). diff --git a/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx b/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx index 69c495473e00cf1..afa8d6b70713ea0 100644 --- a/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx @@ -1,7 +1,7 @@ --- title: Configure the Worker pcx_content_type: how-to -type: overview + sidebar: order: 3 head: diff --git a/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx b/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx index 861cd710ea75f02..6dec5945a9d4a47 100644 --- a/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx @@ -1,7 +1,7 @@ --- title: Enhance Transform Rules pcx_content_type: how-to -type: overview + sidebar: order: 4 head: @@ -37,6 +37,6 @@ As an example, to send the `x-send-jwt-claim-user` request header to the origin, 7. Set the value to: ```txt wrap lookup_json_string(http.request.jwt.claims[""][0], "claim_name") - ``` + ``` `` is your token configuration ID found in JWT validation and `claim_name` is the JWT claim you want to add to the header. \ No newline at end of file diff --git a/src/content/docs/api-shield/security/schema-validation/api.mdx b/src/content/docs/api-shield/security/schema-validation/api.mdx index afb1643ebbd4437..6a22733904e37ca 100644 --- a/src/content/docs/api-shield/security/schema-validation/api.mdx +++ b/src/content/docs/api-shield/security/schema-validation/api.mdx @@ -1,7 +1,7 @@ --- title: Configure Schema Validation via the API pcx_content_type: how-to -type: overview + sidebar: label: API head: diff --git a/src/content/docs/api-shield/security/sequence-analytics.mdx b/src/content/docs/api-shield/security/sequence-analytics.mdx index 9eeba4ff715a445..54e18d1884e71c9 100644 --- a/src/content/docs/api-shield/security/sequence-analytics.mdx +++ b/src/content/docs/api-shield/security/sequence-analytics.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Sequence Analytics sidebar: order: 3 diff --git a/src/content/docs/api-shield/security/sequence-mitigation/api.mdx b/src/content/docs/api-shield/security/sequence-mitigation/api.mdx index a6ac488ced0f0c4..175af2119743a70 100644 --- a/src/content/docs/api-shield/security/sequence-mitigation/api.mdx +++ b/src/content/docs/api-shield/security/sequence-mitigation/api.mdx @@ -1,7 +1,7 @@ --- title: Configure Sequence Mitigation via the API pcx_content_type: how-to -type: overview + sidebar: order: 3 label: API diff --git a/src/content/docs/api-shield/security/sequence-mitigation/manage-sequence-rules.mdx b/src/content/docs/api-shield/security/sequence-mitigation/manage-sequence-rules.mdx index ec36541842c9ec0..ad19b9281baa414 100644 --- a/src/content/docs/api-shield/security/sequence-mitigation/manage-sequence-rules.mdx +++ b/src/content/docs/api-shield/security/sequence-mitigation/manage-sequence-rules.mdx @@ -1,7 +1,7 @@ --- title: Manage sequence rules pcx_content_type: how-to -type: overview + sidebar: order: 2 label: Manage sequence rules @@ -35,10 +35,10 @@ Cloudflare recommends creating sequence rules using WAF custom rules. Refer to t - Select **Set as ending endpoint**. 7. Choose an action that corresponds to the security model type: - **Allow**: This will create a positive security model by defining approved sequences on your API. - - **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API. + - **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API. :::note - If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence. + If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence. ::: 8. Select **Create rule**. @@ -59,10 +59,10 @@ Cloudflare recommends creating sequence rules using WAF custom rules. Refer to t - Select **Set as ending endpoint**. 7. Choose an action that corresponds to the security model type: - **Allow**: This will create a positive security model by defining approved sequences on your API. - - **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API. + - **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API. :::note - If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence. + If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence. ::: 8. Select **Create rule**. diff --git a/src/content/docs/api-shield/security/volumetric-abuse-detection.mdx b/src/content/docs/api-shield/security/volumetric-abuse-detection.mdx index b8434c69c984e5a..cd7b86496abf454 100644 --- a/src/content/docs/api-shield/security/volumetric-abuse-detection.mdx +++ b/src/content/docs/api-shield/security/volumetric-abuse-detection.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -type: overview + title: Volumetric Abuse Detection sidebar: order: 2 @@ -45,7 +45,7 @@ Cloudflare recommends choosing the overall rate limit recommendation, as our ana :::note[p-values] -p-values describe what percentile of your traffic fits below the value. For example, if your p90 value is `83`, then 90% of your sessions had maximum request rates less than 83 requests per 10 minutes. +p-values describe what percentile of your traffic fits below the value. For example, if your p90 value is `83`, then 90% of your sessions had maximum request rates less than 83 requests per 10 minutes. ::: In **Endpoints**, you can review our confidence in the recommendation and how many unique sessions we have seen over the last seven (7) days. In general, endpoints with fewer unique sessions and high variability of user behavior will have lower confidence scores. @@ -65,7 +65,7 @@ Refer to the [Rules documentation](https://developers.cloudflare.com/waf/rate-li method="GET" /> -## Special cases +## Special cases diff --git a/src/content/docs/autorag/concepts/what-is-rag.mdx b/src/content/docs/autorag/concepts/what-is-rag.mdx index 374e05198b357c3..1f74c46ef26690d 100644 --- a/src/content/docs/autorag/concepts/what-is-rag.mdx +++ b/src/content/docs/autorag/concepts/what-is-rag.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: concept title: What is RAG +tags: + - LLM sidebar: order: 1 --- diff --git a/src/content/docs/autorag/index.mdx b/src/content/docs/autorag/index.mdx index a8e0194559c9a3c..740c957a7140b84 100644 --- a/src/content/docs/autorag/index.mdx +++ b/src/content/docs/autorag/index.mdx @@ -1,7 +1,7 @@ --- pcx_content_type: overview title: Overview -type: overview + description: Build scalable, fully-managed RAG applications with Cloudflare AutoRAG. Create retrieval-augmented generation pipelines to deliver accurate, context-aware AI without managing infrastructure. tags: - AI diff --git a/src/content/docs/bots/concepts/bot-tags.mdx b/src/content/docs/bots/concepts/bot-tags.mdx index 090b383ed6780aa..b6fa103bb25e42f 100644 --- a/src/content/docs/bots/concepts/bot-tags.mdx +++ b/src/content/docs/bots/concepts/bot-tags.mdx @@ -1,5 +1,5 @@ --- -type: overview + pcx_content_type: reference title: Bot tags sidebar: @@ -15,7 +15,7 @@ Use these tags to learn more about your bot traffic and better inform security s :::note -Bot tags are only available to Enterprise customers who have purchased Bot Management. +Bot tags are only available to Enterprise customers who have purchased Bot Management. ::: ## Potential values diff --git a/src/content/docs/bots/plans/biz-and-ent.mdx b/src/content/docs/bots/plans/biz-and-ent.mdx index 96fe91d67887255..21435e09891268e 100644 --- a/src/content/docs/bots/plans/biz-and-ent.mdx +++ b/src/content/docs/bots/plans/biz-and-ent.mdx @@ -1,6 +1,6 @@ --- title: Business -type: document + pcx_content_type: reference hidden: true sidebar: diff --git a/src/content/docs/bots/plans/bm-subscription.mdx b/src/content/docs/bots/plans/bm-subscription.mdx index d72a4971f7733b6..eeaf439d3fd186a 100644 --- a/src/content/docs/bots/plans/bm-subscription.mdx +++ b/src/content/docs/bots/plans/bm-subscription.mdx @@ -1,6 +1,6 @@ --- title: Enterprise Bot Management -type: document + pcx_content_type: reference hidden: true sidebar: diff --git a/src/content/docs/bots/plans/free.mdx b/src/content/docs/bots/plans/free.mdx index ecfc16648c89537..cdeb15b23a13a82 100644 --- a/src/content/docs/bots/plans/free.mdx +++ b/src/content/docs/bots/plans/free.mdx @@ -1,6 +1,6 @@ --- title: Free -type: document + pcx_content_type: reference hidden: true sidebar: diff --git a/src/content/docs/bots/plans/index.mdx b/src/content/docs/bots/plans/index.mdx index 90a151cf8d63ade..5e94bb1db31a59d 100644 --- a/src/content/docs/bots/plans/index.mdx +++ b/src/content/docs/bots/plans/index.mdx @@ -1,6 +1,6 @@ --- title: Plans -type: overview + hideChildren: true pcx_content_type: navigation sidebar: diff --git a/src/content/docs/bots/plans/pro.mdx b/src/content/docs/bots/plans/pro.mdx index ddded82aa764656..f3d3c3f3f2890d3 100644 --- a/src/content/docs/bots/plans/pro.mdx +++ b/src/content/docs/bots/plans/pro.mdx @@ -1,6 +1,6 @@ --- title: Pro -type: document + pcx_content_type: reference hidden: true sidebar: diff --git a/src/content/docs/browser-rendering/how-to/ai.mdx b/src/content/docs/browser-rendering/how-to/ai.mdx index c2eef6e0c165540..f04ffff4c8adfff 100644 --- a/src/content/docs/browser-rendering/how-to/ai.mdx +++ b/src/content/docs/browser-rendering/how-to/ai.mdx @@ -2,6 +2,7 @@ title: Use browser rendering with AI tags: - AI + - LLM sidebar: order: 2 --- diff --git a/src/content/docs/browser-rendering/platform/playwright-mcp.mdx b/src/content/docs/browser-rendering/platform/playwright-mcp.mdx index 68afac210fec314..910460a06682583 100644 --- a/src/content/docs/browser-rendering/platform/playwright-mcp.mdx +++ b/src/content/docs/browser-rendering/platform/playwright-mcp.mdx @@ -2,6 +2,8 @@ pcx_content_type: concept title: Playwright MCP description: Deploy a Playwright MCP server that uses Browser Rendering to provide browser automation capabilities to your agents. +tags: + - MCP sidebar: order: 6 badge: Beta diff --git a/src/content/docs/browser-rendering/rest-api/json-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/json-endpoint.mdx index a36a2bde7698258..9b89ae21ef90816 100644 --- a/src/content/docs/browser-rendering/rest-api/json-endpoint.mdx +++ b/src/content/docs/browser-rendering/rest-api/json-endpoint.mdx @@ -1,6 +1,8 @@ --- pcx_content_type: how-to title: /json - Capture structured data +tags: + - JSON sidebar: order: 9 --- diff --git a/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx index 6494b2287e96ac1..9e8d475be629cb7 100644 --- a/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx +++ b/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx @@ -40,8 +40,7 @@ curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser- -d '{ "url": "https://example.com/", "addStyleTag": [ - { "content": "body { font-family: Arial; }" }, - { "url": "https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" } + { "content": "body { font-family: Arial; }" } ] }' \ --output "output.pdf" diff --git a/src/content/docs/cache/how-to/cache-rules/create-api.mdx b/src/content/docs/cache/how-to/cache-rules/create-api.mdx index 99deace52cd0935..d9b90dd57565ae0 100644 --- a/src/content/docs/cache/how-to/cache-rules/create-api.mdx +++ b/src/content/docs/cache/how-to/cache-rules/create-api.mdx @@ -1,7 +1,7 @@ --- title: Create a rule via API pcx_content_type: how-to -type: overview + sidebar: order: 4 head: diff --git a/src/content/docs/cache/how-to/cache-rules/examples/index.mdx b/src/content/docs/cache/how-to/cache-rules/examples/index.mdx index 024ae949f9e946d..6208644d7d4c461 100644 --- a/src/content/docs/cache/how-to/cache-rules/examples/index.mdx +++ b/src/content/docs/cache/how-to/cache-rules/examples/index.mdx @@ -1,5 +1,5 @@ --- -type: overview + hideChildren: false pcx_content_type: navigation title: Examples diff --git a/src/content/docs/cache/how-to/tiered-cache.mdx b/src/content/docs/cache/how-to/tiered-cache.mdx index 93e2e1cf6d408f4..117db25baaf67c3 100644 --- a/src/content/docs/cache/how-to/tiered-cache.mdx +++ b/src/content/docs/cache/how-to/tiered-cache.mdx @@ -32,7 +32,7 @@ Smart Tiered Cache does not work when an origin is behind an [anycast](https://w You need to be careful when updating your origin IPs/DNS records while Smart Tiered Cache is enabled. Depending on the changes made, it may cause the existing assigned upper tiers to change, resulting in an increased `MISS` rate as cache is refilled in the new upper tiers. If the origin is switched to a network behind anycast, it will significantly reduce the effectiveness of Smart Tiered Cache. -If you need to use anycast or regional unicast and want to use Smart Tiered cache, contact your account team. +If you need to use anycast or regional unicast and want to use Smart Tiered cache, please engage your account team. ### Generic Global Tiered Cache @@ -46,7 +46,7 @@ Regional Cache instructs Cloudflare to check a regional hub data center near the ### Custom Tiered Cache -Custom Tiered cache allows Enterprise customers to work with their account team to set a custom topology that fits your specific needs, for instance you have close upper tiers or you have an unique traffic pattern. If you want a custom topology, please contact your account team. +Custom Tiered cache allows Enterprise customers to work with their account team to set a custom topology that fits your specific needs, for instance you have close upper tiers or you have an unique traffic pattern. If you want a custom topology, please engage your account team. ## Availability diff --git a/src/content/docs/cache/index.mdx b/src/content/docs/cache/index.mdx index 3060b7c1e6115fe..cdc5b7182dea792 100644 --- a/src/content/docs/cache/index.mdx +++ b/src/content/docs/cache/index.mdx @@ -20,7 +20,7 @@ Cache content across Cloudflare's global server network. Cache stores copies of frequently accessed content (such as images, videos, or webpages) in geographically distributed data centers that are located closer to end users than origin servers, reducing server load and improving website performance. - + ## Features diff --git a/src/content/docs/cache/plans.mdx b/src/content/docs/cache/plans.mdx index 6efdff44ea12438..98c45525e1c6078 100644 --- a/src/content/docs/cache/plans.mdx +++ b/src/content/docs/cache/plans.mdx @@ -1,7 +1,7 @@ --- title: Plans pcx_content_type: reference -type: overview + sidebar: order: 2 head: diff --git a/src/content/docs/cloudflare-challenges/challenge-types/javascript-detections.mdx b/src/content/docs/cloudflare-challenges/challenge-types/javascript-detections.mdx index f44df2d52d67f43..dee5f11b80cff7d 100644 --- a/src/content/docs/cloudflare-challenges/challenge-types/javascript-detections.mdx +++ b/src/content/docs/cloudflare-challenges/challenge-types/javascript-detections.mdx @@ -1,6 +1,6 @@ --- -type: overview + pcx_content_type: reference title: JavaScript Detections sidebar: @@ -9,29 +9,29 @@ sidebar: import { Render, Tabs, TabItem, GlossaryTooltip } from "~/components" -JavaScript Detections is a type of Challenge separate from Cloudflare’s Challenge Pages or Turnstile. Javascript Detections helps Cloudflare's [bot solutions](/bots/) identify automated requests. +JavaScript Detections is a type of Challenge separate from Cloudflare’s Challenge Pages or Turnstile. Javascript Detections helps Cloudflare's [bot solutions](/bots/) identify automated requests. -While Challenge Pages and Turnstile rely on client-side signals to determine the authenticity of a request, Bot Management’s JavaScript Detections relies on network-side signals and run on every single request made to your website. +While Challenge Pages and Turnstile rely on client-side signals to determine the authenticity of a request, Bot Management’s JavaScript Detections relies on network-side signals and run on every single request made to your website. -## Process +## Process -JavaScript Detections is implemented on your website via a lightweight, invisible JavaScript code snippet that follows Cloudflare's [privacy standards](https://www.cloudflare.com/privacypolicy/). +JavaScript Detections is implemented on your website via a lightweight, invisible JavaScript code snippet that follows Cloudflare's [privacy standards](https://www.cloudflare.com/privacypolicy/). -JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile application traffic is unaffected. +JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile application traffic is unaffected. JavaScript Detections has a lifespan of 15 minutes. However, the code is injected again before the session expires. After page load, the script is deferred and utilizes a separate thread (where available) to ensure that performance impact is minimal. The snippets of JavaScript will contain a source pointing to the Challenge Platform, with paths that start with `/cdn-cgi/challenge-platform/…` Once JavaScript Detections is injected on the HTML page, the visitor's browser will run the JavaScript code snippet and a `cf_clearance` cookie is issued to the visitor. The information in JavaScript Detections is stored in the `cf_clearance` cookie and is used to populate `js_detection.passed`. - If the visitor is verified and a `cf_clearance` cookie is issued, it will contain the outcome: `cf.bot_management.js.detection.passed` = `true` -- If the verification fails, the cookie will contain the outcome: `cf.bot_management.js.detection.passed` = `false` +- If the verification fails, the cookie will contain the outcome: `cf.bot_management.js.detection.passed` = `false` :::note The `cf_clearance` cookie cannot exceed the maximum size of 4096 bytes. ::: :::caution -Enforcement against bots does **not** occur even if the cookie is flagged false. +Enforcement against bots does **not** occur even if the cookie is flagged false. You must enable JavaScript Detections and then create a custom WAF rule using the `cf.bot_management.js.detection.passed` field to block or challenge a failed request. ::: @@ -70,7 +70,7 @@ The `cf.bot_management.js_detection.passed` field should never be used in a WAF ```txt wrap - (http.request.uri.path eq "/api/v4/user/create" and http.request.method eq "POST" and not cf.bot_management.verified_bot) + (http.request.uri.path eq "/api/v4/user/create" and http.request.method eq "POST" and not cf.bot_management.verified_bot) and (cf.bot_management.score lt 30 or !cf.bot_management.js_detection.passed) ``` @@ -91,7 +91,7 @@ Refer to the [WAF documentation](/waf/custom-rules/create-dashboard/) for more i If you enable JavaScript Detections via the dashboard, Cloudflare will insert a script tag in all HTML pages served on your website. If you would prefer to limit where JavaScript Detections is served, you can do so with the JavaScript Detections API script. -The JavaScript Detections API allows you more granular control over when and where JavaScript Detections is injected on your website, as well as an option for callback handling (for logging or other additional actions). +The JavaScript Detections API allows you more granular control over when and where JavaScript Detections is injected on your website, as well as an option for callback handling (for logging or other additional actions). You can explicitly add a script reference to `/cdn-cgi/challenge-platform/scripts/jsd/api.js` and your own code calling `window.cloudflare.jsd.executeOnce` on specific HTML pages of your website. @@ -103,7 +103,7 @@ The following script must be added to every page that you wish to have JavaScrip ```js wrap