From cb9a82e5bfda33d24947695f63e643ab7c9e74e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Mon, 2 Nov 2026 06:28:16 +0100 Subject: [PATCH 1/5] Document Spacefast infrastructure and security --- bun.lock | 10 +--- components.ts | 2 + components/WpCloudDocs.astro | 16 ++++++ content/(dynamic)/logs.mdx | 12 +++-- content/(serve)/domains.mdx | 6 ++- content/(serve)/routing.mdx | 2 + content/infrastructure/automated-failover.mdx | 26 ++++++++++ content/infrastructure/ddos-protection.mdx | 28 ++++++++++ content/infrastructure/defensive-mode.mdx | 37 ++++++++++++++ .../domain-verification-records.mdx | 40 +++++++++++++++ content/infrastructure/edge-request-logs.mdx | 51 +++++++++++++++++++ .../infrastructure/filesystem-permissions.mdx | 32 ++++++++++++ .../infrastructure/http-security-headers.mdx | 45 ++++++++++++++++ content/infrastructure/ip-ranges.mdx | 31 +++++++++++ content/infrastructure/meta.ts | 20 ++++++++ .../infrastructure/origin-edge-servers.mdx | 30 +++++++++++ content/infrastructure/rate-limiting.mdx | 37 ++++++++++++++ .../infrastructure/server-specs-settings.mdx | 33 ++++++++++++ content/infrastructure/tls-certificates.mdx | 44 ++++++++++++++++ content/meta.ts | 1 + package.json | 2 +- styles/Spacefast/spelling-exceptions.txt | 7 +++ 22 files changed, 496 insertions(+), 16 deletions(-) create mode 100644 components/WpCloudDocs.astro create mode 100644 content/infrastructure/automated-failover.mdx create mode 100644 content/infrastructure/ddos-protection.mdx create mode 100644 content/infrastructure/defensive-mode.mdx create mode 100644 content/infrastructure/domain-verification-records.mdx create mode 100644 content/infrastructure/edge-request-logs.mdx create mode 100644 content/infrastructure/filesystem-permissions.mdx create mode 100644 content/infrastructure/http-security-headers.mdx create mode 100644 content/infrastructure/ip-ranges.mdx create mode 100644 content/infrastructure/meta.ts create mode 100644 content/infrastructure/origin-edge-servers.mdx create mode 100644 content/infrastructure/rate-limiting.mdx create mode 100644 content/infrastructure/server-specs-settings.mdx create mode 100644 content/infrastructure/tls-certificates.mdx diff --git a/bun.lock b/bun.lock index 46d832f3..f21c9a21 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "docs", "dependencies": { "blume": "2.2.6", - "zod": "4.6.0", + "zod": "4.6.5", }, "devDependencies": { "@spacefast/routing": "0.0.24", @@ -1665,7 +1665,7 @@ "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], - "zod": ["zod@4.6.0", "", {}, "sha512-iIvwyDnebKYpww2ta0DjaNOL8RnVLmPMhgWyOzlW9y0EIIxv5gl+H6Y0ONpt83HqjGqkk78uWp6xWtpxzZdPbw=="], + "zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -1705,8 +1705,6 @@ "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="], - "@modelcontextprotocol/sdk/zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="], - "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], "@rollup/pluginutils/picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], @@ -1759,12 +1757,8 @@ "astro/vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="], - "astro/zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="], - "blume/@types/node": ["@types/node@22.20.4", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA=="], - "blume/zod": ["zod@4.6.5", "", {}, "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q=="], - "body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "cliui/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], diff --git a/components.ts b/components.ts index b4799473..5b74a559 100644 --- a/components.ts +++ b/components.ts @@ -3,7 +3,9 @@ import { defineComponents } from "blume"; import Breadcrumbs from "./components/Breadcrumbs.astro"; import Pagination from "./components/Pagination.astro"; import Sidebar from "./components/Sidebar.astro"; +import WpCloudDocs from "./components/WpCloudDocs.astro"; export default defineComponents({ layout: { Breadcrumbs, Pagination, Sidebar }, + mdx: { WpCloudDocs }, }); diff --git a/components/WpCloudDocs.astro b/components/WpCloudDocs.astro new file mode 100644 index 00000000..231e9d75 --- /dev/null +++ b/components/WpCloudDocs.astro @@ -0,0 +1,16 @@ +--- +import { contentHref } from "blume/components/content/base-href.ts"; + +interface Props { + title: string; + href: string; +} + +const { title, href } = Astro.props; +--- + + diff --git a/content/(dynamic)/logs.mdx b/content/(dynamic)/logs.mdx index 8740ee54..b10482b9 100644 --- a/content/(dynamic)/logs.mdx +++ b/content/(dynamic)/logs.mdx @@ -7,15 +7,16 @@ sidebar: Use `sf logs` for requests, `sf logs runtime` for your code's output, and `sf builds logs` for build failures. -## Three streams +## Four streams | Stream | What it holds | How to read it | | --- | --- | --- | -| Access | Every request the edge served | `sf logs`, dashboard **Logs** with source **Access** | +| Access | Requests that reached the origin | `sf logs`, dashboard **Logs** with source **Access** | +| Edge | Requests handled by the edge, including cache hits and challenges | [`sf logs edge`](/infrastructure/edge-request-logs), dashboard **Logs** with source **Edge Logs** | | Runtime | Lines your own code wrote | `sf logs runtime`, dashboard **Logs** with source **App** | | Build | A build runner's output | `sf builds logs ` | -Access and runtime are per Space. Build logs belong to one build. +Access, edge, and runtime are per Space. Build logs belong to one build. ## Read them @@ -27,7 +28,7 @@ sf logs https://example.com access sf logs runtime --follow ``` -The first positional is a target, which can be a Space id, slug, live URL, or custom domain. The second is the kind. The command shifts a bare kind out of the first slot, so `sf logs runtime` and `sf logs docs runtime` both work. The kind defaults to `access`, and anything other than `access` or `runtime` is refused. +The first positional is a target, which can be a Space id, slug, live URL, or custom domain. The second is the kind. The command shifts a bare kind out of the first slot, so `sf logs runtime` and `sf logs docs runtime` both work. The kind defaults to `access`. Use `edge` for requests handled by the edge, including cache hits and security challenges. See [Edge request logs](/infrastructure/edge-request-logs) for its filters and query limits. | Flag | Default | What it does | | --- | --- | --- | @@ -77,7 +78,7 @@ A record is written on the origin, shipped off the box, and indexed before it ca `--request-id` and `--handler` are applied over pages already fetched, because the provider indexes neither. That makes them precise but not free, so give a `--limit` that covers the window you care about. -The `since` and `until` window exists on the API query, but the CLI exposes no flags for it. +Use `--since` and `--until` for an ISO 8601 time window. Edge logs have their own [window and retention limits](/infrastructure/edge-request-logs#filters-and-time-windows). ## Retention @@ -99,5 +100,6 @@ sf builds logs bld_123 --follow | Operation | Route | | --- | --- | | [`listSpaceAccessLogs`](/api/reference/activity/listspaceaccesslogs) | `GET /v1/spaces/{spaceId}/logs/access` | +| [`listSpaceEdgeLogs`](/api/reference/activity/listspaceedgelogs) | `GET /v1/spaces/{spaceId}/logs/edge` | | [`listSpaceRuntimeLogs`](/api/reference/activity/listspaceruntimelogs) | `GET /v1/spaces/{spaceId}/logs/runtime` | | [`listBuildLogs`](/api/reference/builds/listbuildlogs) | `GET /v1/builds/{buildId}/logs` | diff --git a/content/(serve)/domains.mdx b/content/(serve)/domains.mdx index caa2dcc7..6a2c272a 100644 --- a/content/(serve)/domains.mdx +++ b/content/(serve)/domains.mdx @@ -70,7 +70,7 @@ A domain belongs to a **team**, not to a Space. You add it once to the team's in An unassigned domain has no records to show. Instructions appear once the domain is assigned to a Space, which is why `sf domains add` assigns in the same command. -Each record the API returns has four fields: `type`, `name`, `value`, and `purpose`. Adding the apex `example.com` produces six of them in the common case, because the `www` twin is set up alongside it. +Each record the API returns has four fields: `type`, `name`, `value`, and `purpose`. The apex and `www` can each need address and verification records. The table below shows example record shapes, not a fixed list for every domain. | Type | Name | Value | Purpose | | --- | --- | --- | --- | @@ -81,7 +81,7 @@ Each record the API returns has four fields: `type`, `name`, `value`, and `purpo | `AAAA` | `example.com` | the IPv6 address in your instructions | `routing` | | `AAAA` | `www.example.com` | the IPv6 address in your instructions | `routing` | -The TXT value carries your team id and proves you control the zone. The address records are generated for your hostname, so copy the exact values from your own output rather than the ones above. +Spacefast ownership records prove control for your team. Instructions can also include a separate WP Cloud TXT value at the hostname itself. Copy every required record from your own output, including the exact name and value. See [Domain verification records](/infrastructure/domain-verification-records) for conflicts with older proofs. :::warning[Delete the old address records first] Every observed `A` record has to point at Spacefast. A leftover record from your previous host sitting beside the correct one blocks verification, and the diagnostics will report the hostname as not configured while both are live. The same rule applies to `AAAA` when IPv6 is offered. @@ -89,6 +89,8 @@ Every observed `A` record has to point at Spacefast. A leftover record from your Spacefast generates `A`, `AAAA` and `TXT` records only. There is no CNAME or ALIAS instruction. +Certificates are provisioned and renewed automatically once the hostname can be validated. See [TLS certificates](/infrastructure/tls-certificates) for issuance checks and retries, and [IP ranges](/infrastructure/ip-ranges) for inbound and outbound address behavior. + ## Apex and www travel together If the hostname you add is the registrable apex or its `www` twin, both hostnames get set up. `example.com` pulls in `www.example.com`, and `www.example.com` pulls in `example.com`. Any other subdomain, like `app.example.com`, is connected on its own. diff --git a/content/(serve)/routing.mdx b/content/(serve)/routing.mdx index 3e2344cc..b82d81c5 100644 --- a/content/(serve)/routing.mdx +++ b/content/(serve)/routing.mdx @@ -59,6 +59,8 @@ Two more tokens can appear on a line. Query matchers sit between the source and ## `_headers` +For a security policy example and browser checks, see [HTTP and security headers](/infrastructure/http-security-headers). + An unindented line starts a matcher block. Indented lines under it are operations. `!Name` removes a header. ```text _headers diff --git a/content/infrastructure/automated-failover.mdx b/content/infrastructure/automated-failover.mdx new file mode 100644 index 00000000..2e70e769 --- /dev/null +++ b/content/infrastructure/automated-failover.mdx @@ -0,0 +1,26 @@ +--- +title: Automated failover +description: How regional replicas keep Spacefast sites available when an origin fails. +--- + +Spacefast sites run on infra with primary and secondary origin servers in different geographic data centers. WP Cloud continuously replicates site data between them and can move traffic when the primary server or its data center becomes unavailable. + +## What happens during failover + +WP Cloud monitors origin health and performance. When a failure requires a switch, it redirects traffic to the secondary origin. Once the primary is restored, traffic returns to it automatically. + +You do not need to republish your Space or change its DNS records. The public address reaches the [edge network](/infrastructure/origin-edge-servers), which routes requests to the active origin. + +The active origin location and outbound IP address can change during a switch. Do not use either as a permanent identifier for your Space. See [IP ranges](/infrastructure/ip-ranges) before connecting an external service that requires an IP allowlist. + +## Cached responses during an origin error + +Graceful failover is a separate protection. If an origin returns an HTTP 5xx error, the edge may serve an eligible cached response instead. It can keep an already cached page available while the origin has a problem. + +This does not repair application errors or create cached copies of responses that were never stored. Personalized pages, API calls that bypass the cache, and writes still depend on a working origin. See [Caching](/caching) for what Spacefast caches. + +## Data location + +The redundant copy lives in another region. An origin preference is not a guarantee that all site data stays in one geographic location. WP Cloud can store site data in both the United States and the European Union. + + diff --git a/content/infrastructure/ddos-protection.mdx b/content/infrastructure/ddos-protection.mdx new file mode 100644 index 00000000..a8902e0a --- /dev/null +++ b/content/infrastructure/ddos-protection.mdx @@ -0,0 +1,28 @@ +--- +title: DDoS protection +description: How edge routing, caching, and traffic classification protect your Space. +--- + +Spacefast sites inherit WP Cloud's platform-level protection against denial-of-service and distributed denial-of-service attacks. It operates without a setup step or a plugin in your Space. + +## Before traffic reaches your application + +Anycast routing distributes inbound requests across the edge network. The edge can serve eligible cached responses, classify suspicious traffic, and apply [rate limits](/infrastructure/rate-limiting) before requests consume origin resources. + +WP Cloud monitors the network and adjusts protections as traffic changes. Caching and filtering can absorb repeated or unwanted requests, but they do not guarantee that every application remains available under every attack. + +## Browser challenges + +[Defensive Mode](/infrastructure/defensive-mode) adds browser challenges during suspected bot or DDoS activity. Certain suspicious traffic can also receive a challenge independently of Defensive Mode. + +A challenge normally returns HTTP `403`. A rate limit normally returns `429`. Inspect [edge request logs](/infrastructure/edge-request-logs) to distinguish them before changing your application. + +For a known unwanted pattern, Spacefast also supports traffic rules through `sf rules`. A firewall rule can block a request or ask for a browser challenge. The [CLI reference](/cli/reference#sf-rules) lists the supported matches and actions. + +## During an incident + +Check whether legitimate visitors or integrations are failing, then preserve request samples. Include the affected hostname, UTC timestamp, URL, source IP address, complete `User-Agent`, and the response status when contacting Spacefast support. + +Send traffic directly to Spacefast's supplied DNS addresses where possible. An extra proxy can hide classification signals and change how visitors reach the edge. If you use one, include that detail in the incident report. + + diff --git a/content/infrastructure/defensive-mode.mdx b/content/infrastructure/defensive-mode.mdx new file mode 100644 index 00000000..8c671d13 --- /dev/null +++ b/content/infrastructure/defensive-mode.mdx @@ -0,0 +1,37 @@ +--- +title: Defensive Mode +description: Understand browser challenges and their effect on visitors and automated clients. +--- + +Defensive Mode challenges browsers before they reach a site, reducing unwanted automated traffic. Spacefast sites use WP Cloud's challenge system as part of their edge protection. + +A browser-check page does not, by itself, prove that Defensive Mode is active. Traffic classification and a Spacefast firewall rule can also trigger a challenge. + +## What visitors see + +Most challenges use an automated browser check. The visitor briefly sees a checking page, completes the check, and continues to the requested URL. The usual automated check can take up to five seconds. The platform can require a harder challenge with an action such as selecting a checkbox. + +Challenge responses use HTTP `403`. A client that cannot complete the challenge does not reach the requested page. HTTP `429` belongs to [rate limiting](/infrastructure/rate-limiting), a separate mechanism. + +API clients, webhooks, uptime monitors, and other automated services may be unable to solve a browser challenge. Test essential integrations when adding challenge rules. + +## What triggers a challenge + +| Trigger | Behavior | +| --- | --- | +| Manual Defensive Mode | WP Cloud supports an expiration from 30 minutes through seven days. Contact Spacefast support if site-wide protection is needed during an incident. | +| Automatic Defensive Mode | The infra can temporarily enable protection after a PHP resource-limit event. | +| Traffic classification | Suspicious or spoofed requests can be challenged even when Defensive Mode is off. | +| Spacefast firewall rule | A rule with the `challenge` action targets the request patterns you choose. | + +The platform challenge system cannot be fully disabled. Ending a manual mode or removing your own rule does not turn off classification challenges. + +For targeted rules, see [`sf rules`](/cli/reference#sf-rules). These rules are separate from the site-wide Defensive Mode setting in the WP Cloud API. + +## Help legitimate automation + +Send a specific, accurate `User-Agent`, such as `ExampleMonitor/1.0`. Do not impersonate a browser or a known crawler. Sending a Googlebot header from outside Google's network can itself trigger a spoofed-crawler challenge. + +An accurate header does not bypass protection. For a false positive, preserve the timestamp, source IP, full URL, and complete `User-Agent` from [edge request logs](/infrastructure/edge-request-logs), then contact Spacefast support. + + diff --git a/content/infrastructure/domain-verification-records.mdx b/content/infrastructure/domain-verification-records.mdx new file mode 100644 index 00000000..7f74b0dc --- /dev/null +++ b/content/infrastructure/domain-verification-records.mdx @@ -0,0 +1,40 @@ +--- +title: Domain verification records +description: Publish the exact TXT records needed to prove control of a Space hostname. +--- + +Spacefast uses DNS verification records to prove that you control a hostname before it serves your Space. Copy the exact record names and values from your domain's setup instructions. + +## Get the records for your hostname + +```bash +sf domains add example.com --space my-site +sf domains diagnostics example.com --space my-site +``` + +The dashboard's domain setup also shows the required records. Add them wherever your DNS is managed. For the complete connection flow, see [Custom domains](/domains). + +Instructions can include both a Spacefast ownership record and a WP Cloud verification record. They prove different claims. Do not substitute one for the other or build a TXT value from an example. + +## When WP Cloud verification is required + +A hostname already used by another WP Cloud client can require an extra TXT record before it can attach to Spacefast. Spacefast retrieves that proof and includes it in the DNS instructions. + +The upstream value starts with `atomic-domain-` and belongs at the exact hostname being verified. The apex `example.com` and `www.example.com` can require separate values. + +Publish only the currently required WP Cloud verification value at each hostname. Multiple distinct TXT values starting with `atomic-domain-` at the same hostname can prevent verification, even when one matches Spacefast's instructions. Remove a superseded WP Cloud proof when moving the hostname. Keep unrelated TXT records, including email authentication records. + +A CNAME cannot coexist with the required TXT record at the same hostname. Follow Spacefast's address-record instructions instead. + +## Check and retain the proof + +```bash +sf domains check example.com --space my-site +sf domains diagnostics example.com --space my-site +``` + +DNS propagation can delay a successful check. Inspect every hostname in diagnostics; a verified apex does not prove that `www` is ready. + +Keep required verification records after setup so future checks can still prove control. A domain's verification state, routing readiness, and [TLS certificate](/infrastructure/tls-certificates) state are separate. A TXT record alone does not make the hostname live. + + diff --git a/content/infrastructure/edge-request-logs.mdx b/content/infrastructure/edge-request-logs.mdx new file mode 100644 index 00000000..12f4eb19 --- /dev/null +++ b/content/infrastructure/edge-request-logs.mdx @@ -0,0 +1,51 @@ +--- +title: Edge request logs +description: Inspect edge cache hits, rate limits, and browser challenges for a Space hostname. +--- + +Edge request logs show requests handled by the edge, including cached responses, rate limits, and browser challenges that may never reach your Space's origin. + +## Read edge requests + +```bash +sf logs edge --space my-site +sf logs edge --space my-site --hostname example.com --status 429 +sf logs edge --space my-site --status 403 --json +``` + +In the dashboard, open the Space's logs and select the edge view. For application output and origin requests, use [Access and runtime logs](/logs). + +Each query covers one assigned hostname and defaults to the primary hostname. Use `--hostname` to inspect a different mapped domain. An apex and its `www` hostname are separate queries. + +## Filters and time windows + +| CLI flag | Selects | +| --- | --- | +| `--hostname` | One hostname assigned to the Space | +| `--remote-addr` | Client IPv4 or IPv6 address | +| `--ja3-hash` | JA3 TLS fingerprint, exactly 32 hexadecimal characters | +| `--method` | HTTP method, such as `GET` | +| `--status` | HTTP response status | +| `--user-agent` | Exact complete `User-Agent` value | +| `--asn` | Source network's autonomous system number | +| `--since`, `--until` | ISO 8601 timestamps for the query window | + +Repeat a filter flag to include more values. Values within one field use OR; different fields use AND. + +The default window is the past hour. A query can span at most one hour within the past 24 hours, and your plan's retention can shorten that window. Results arrive newest first. Use smaller windows to investigate busy periods. + +## What a record contains + +Records include `timestamp`, `hostname`, `method`, `path`, `status`, client IP, user agent, country, timing, and `cacheStatus`. Rate-limit details appear in `rateLimited` and `rateLimitReason`. Browser-check details appear in `defensiveMode.cookieStatus`, `challengeReason`, and `challengeResult`. + +Some details can be `null`. Access credentials in request URLs are redacted. + +## Pagination and truncation + +Spacefast returns up to 100 entries per page through `GET /v1/spaces/{spaceId}/logs/edge`. Continue with `pagination.nextCursor`, or the CLI's `--cursor`. A cursor refers to a fixed snapshot and expires after five minutes; the original window and filters still apply. + +The underlying query can return at most 5,000 records. An `edge_logs_truncated` warning means the snapshot may omit matches. Paging cannot recover records absent from that snapshot. Narrow the time range or add filters. Reaching the end of a cursor does not prove you exported every matching request. + +For traffic trends, use [Stats](/stats). Edge logs are individual request records, not a complete analytics export or a live stream. + + diff --git a/content/infrastructure/filesystem-permissions.mdx b/content/infrastructure/filesystem-permissions.mdx new file mode 100644 index 00000000..9c381d2b --- /dev/null +++ b/content/infrastructure/filesystem-permissions.mdx @@ -0,0 +1,32 @@ +--- +title: Filesystem permissions +description: Understand PHP filesystem controls and how they differ from published versions and application data. +--- + +A published Space version is an immutable snapshot. Changing files means publishing a new version. WP Cloud's PHP filesystem permissions are a separate control over writes made by PHP web requests. + +## What the infra control does + +WP Cloud supports the `php_fs_permissions` site setting: + +| Value | Effect on PHP web requests | +| --- | --- | +| `rw` | PHP can read and write the site's filesystem. This is WP Cloud's default. | +| `ro` | PHP can read files but cannot write them. Uploads, updates, and other file-writing operations can fail. | +| `loggedin` | Changes write behavior for some logged-in WordPress requests. The feature is evolving and requires testing against the site's actual workflows. | + +These are upstream capabilities, not fields to add to `sf.jsonc`. Spacefast manages the filesystem policy for its sites. Use [publish](/publish), [Storage](/object-storage), and the documented [WordPress tools](/wordpress) for the changes your application needs. + +## Read-only files do not mean read-only data + +A PHP filesystem restriction does not make the database read-only or prevent WordPress administration from changing database content. It also does not change SSH or SFTP access controls. + +For your Space, keep the two kinds of data separate. Published version files stay with their snapshot. Application records belong in [Database](/database), and mutable media belongs in [Storage](/object-storage). + +## Security incidents + +Read-only mode can help contain filesystem changes during an investigation. It does not remove malicious files or rotate compromised credentials. It can also break legitimate uploads, plugin updates, scheduled tasks, and integrations that write files. + +Contact Spacefast support before depending on an infra filesystem restriction. Check all affected application workflows after a policy change, including logged-out requests and background work. + + diff --git a/content/infrastructure/http-security-headers.mdx b/content/infrastructure/http-security-headers.mdx new file mode 100644 index 00000000..602484d5 --- /dev/null +++ b/content/infrastructure/http-security-headers.mdx @@ -0,0 +1,45 @@ +--- +title: HTTP and security headers +description: Set application security headers while leaving transport policy to the platform. +--- + +Set security headers for your published pages in `_headers` or the supported routing configuration. Spacefast manages transport headers, including HTTP Strict Transport Security, at the platform level. + +## Add a header policy + +Place `_headers` in the directory you publish. For example: + +```text _headers +/* + X-Content-Type-Options: nosniff + Referrer-Policy: strict-origin-when-cross-origin + X-Frame-Options: DENY +``` + +This example prevents MIME sniffing, limits referrer information, and blocks framing. If your page must appear inside another site, choose an appropriate framing policy before copying it. + +Publish the change with your site. Rules apply to the URL the visitor requested, including when a rewrite serves another file. Matching header blocks accumulate. See [Redirects, rewrites, and headers](/routing) for ordering, removals, and validation. + +## Which settings belong where? + +| Header | What to know | +| --- | --- | +| `Content-Security-Policy` | Restricts scripts, frames, fonts, and other resources. Start with a report-only policy when practical and test required integrations. | +| `Access-Control-Allow-*` | Controls browser cross-origin access. Test the real requesting origin and any `OPTIONS` preflight. | +| `X-Frame-Options` | Controls framing. A restrictive policy can break embeds. | +| `X-Content-Type-Options` | Use `nosniff` to prevent MIME sniffing. | +| `Referrer-Policy` | Controls which referrer details accompany outgoing requests. | +| `Strict-Transport-Security` | Managed by the infra. Authored routing rules cannot replace it. | +| `Cache-Control` | Allowed for browser responses, with a platform-managed caching warning. Shared caching follows [Spacefast's caching rules](/caching). | + +Inspect the exact URL instead of assuming every response has the same headers. Application routes, published files, errors, and cached responses can take different paths. + +## Check the result + +```bash +curl -sS -D - -o /dev/null https://example.com/path/ +``` + +Test while logged out and repeat the request to inspect cached responses. A successful `curl` request does not prove that a browser permits a cross-origin response or that a Content Security Policy allows every required resource. Check the browser console and the application's real forms, scripts, embeds, and payment flows. + + diff --git a/content/infrastructure/ip-ranges.mdx b/content/infrastructure/ip-ranges.mdx new file mode 100644 index 00000000..cc3e2ce5 --- /dev/null +++ b/content/infrastructure/ip-ranges.mdx @@ -0,0 +1,31 @@ +--- +title: IP ranges +description: Use the DNS addresses Spacefast returns and account for changing outbound addresses. +--- + +Copy the DNS records Spacefast gives you for your hostname. Inbound addresses route visitors to the edge; they do not identify the server running your Space. + +## Inbound traffic + +Spacefast uses WP Cloud's Anycast network. The same published address can send visitors to different edge locations, usually near the requester, before a request reaches the origin. + +Connect a domain through the [custom domain flow](/domains). The CLI and dashboard return the required address and verification records. Use those exact values, including the hostname on each record. + +WP Cloud's default inbound load-balancer range is `192.0.79.128/26`, but approved addresses can differ between partner configurations. Do not select an address from that range yourself or copy one from another Space. Spacefast obtains the addresses for your setup. + +```bash +sf domains add example.com --space my-site +sf domains diagnostics example.com --space my-site +``` + +## Outbound connections + +A request from your Space to an external service uses an origin pool's outbound address. That address can change after [automated failover](/infrastructure/automated-failover), relocation, or replacement of the underlying site. + +Outbound addresses can be shared with other sites. An IP allowlist covering a complete infra range does not authenticate your application, and a single observed address is not a stable integration contract. Use the external service's authentication mechanism. If it also requires an IP allowlist, contact Spacefast support to discuss the requirement before depending on a fixed address. + +## Keep DNS and location separate + +A public DNS lookup tells you where to send inbound traffic. It does not reveal a permanent origin location or the address an outbound connection will use. Changing DNS is not how you select an origin region. + + diff --git a/content/infrastructure/meta.ts b/content/infrastructure/meta.ts new file mode 100644 index 00000000..57c6f40a --- /dev/null +++ b/content/infrastructure/meta.ts @@ -0,0 +1,20 @@ +import { defineMeta } from "blume"; + +export default defineMeta({ + title: "Infrastructure", + collapsed: true, + pages: [ + "automated-failover", + "ip-ranges", + "origin-edge-servers", + "server-specs-settings", + "ddos-protection", + "defensive-mode", + "rate-limiting", + "http-security-headers", + "filesystem-permissions", + "edge-request-logs", + "domain-verification-records", + "tls-certificates", + ], +}); diff --git a/content/infrastructure/origin-edge-servers.mdx b/content/infrastructure/origin-edge-servers.mdx new file mode 100644 index 00000000..e5b2c628 --- /dev/null +++ b/content/infrastructure/origin-edge-servers.mdx @@ -0,0 +1,30 @@ +--- +title: Origin and edge servers +description: How requests reach the edge, use the cache, and continue to the origin. +--- + +The edge receives requests close to your visitors. The origin stores site data and handles requests the edge cannot answer from cache. + +## A request through Spacefast + +1. Your hostname resolves to an Anycast address. Network routing takes the visitor to an edge location. +2. The edge applies traffic protections and can return an eligible cached response. +3. A request that needs the origin continues to the site running your Space. Spacefast serves the published files or runs the application behavior the request needs. + +Edge Cache and origin caching are separate layers. A cache hit at the edge avoids an origin request. An origin cache hit can avoid running WordPress again. See [Caching](/caching) for Spacefast's response and invalidation rules. + +## Origin regions + +WP Cloud operates origin locations in Amsterdam, Ashburn, Dallas, and Los Angeles, with edge locations across more regions. The public IP address does not identify the physical origin. + +Spacefast manages site placement. A WP Cloud origin preference is a provisioning choice, not a per-request routing rule or a Spacefast setting for moving an existing Space. WP Cloud can relocate sites for platform health and performance, and [failover](/infrastructure/automated-failover) can temporarily change the active origin. + +Site replicas can span the United States and the European Union. Do not infer a data-residency guarantee from an origin location, a DNS answer, or the edge that served one request. + +## Which logs show the request? + +[Edge request logs](/infrastructure/edge-request-logs) include requests handled at the edge, including cache hits and security challenges that never reach the origin. [Access and runtime logs](/logs) cover origin requests and application output. + +Use [Stats](/stats) to inspect traffic trends. A missing origin log entry does not mean the edge never received the request. + + diff --git a/content/infrastructure/rate-limiting.mdx b/content/infrastructure/rate-limiting.mdx new file mode 100644 index 00000000..fcc95011 --- /dev/null +++ b/content/infrastructure/rate-limiting.mdx @@ -0,0 +1,37 @@ +--- +title: Rate limiting +description: Diagnose visitor-facing 429 responses and distinguish edge limits from application capacity. +--- + +A request to your Space can receive HTTP `429` when traffic matches an infra rate limit or exceeds application capacity. Occasional limits on scanners and unwanted bots are expected. Investigate when legitimate visitors or integrations cannot continue. + +## Edge traffic limits + +WP Cloud classifies requests using signals such as request rate, URL patterns, user agent, proxy characteristics, and connection behavior. Limits can apply to a pattern, a site, or the wider platform. + +Thresholds can change as traffic changes. Do not build a client around an undocumented requests-per-second allowance. Send an accurate `User-Agent` and reduce repeated requests when a limit appears. + +## Resource limits are different + +A visitor-facing rate-limit page can also represent a PHP resource-limit event, recorded by WP Cloud as HTTP `599`. That means a PHP connection was not available in time; it does not require CPU usage to reach a maximum. + +Spacefast also limits concurrent application work. When that admission limit is reached, it returns `429` with `Retry-After`. Respect that header and retry with backoff. Repeating the same work immediately adds pressure. + +A [Defensive Mode](/infrastructure/defensive-mode) challenge uses `403` instead. Look at the request details before treating every rejected request as the same problem. + +## Find the affected requests + +```bash +sf logs edge --space my-site --status 429 +sf logs access --space my-site +``` + +[Edge request logs](/infrastructure/edge-request-logs) show cache handling, rate-limit reasons, and challenge details. Origin [access and runtime logs](/logs) help explain requests that reached your application. Compare the same hostname and time window. + +For an authorized crawler or integration, reduce its request rate, check for loops and repeated missing URLs, and confirm its identity header. If a legitimate workflow remains blocked, contact Spacefast support with exact request samples. + +## Management API limits + +Limits on calls to `api.spacefast.com` are a separate contract. See [API rate limits](/api/rate-limits) for response headers, quotas, and retry behavior. + + diff --git a/content/infrastructure/server-specs-settings.mdx b/content/infrastructure/server-specs-settings.mdx new file mode 100644 index 00000000..8e9c6305 --- /dev/null +++ b/content/infrastructure/server-specs-settings.mdx @@ -0,0 +1,33 @@ +--- +title: Server specifications and settings +description: Managed hardware, PHP settings, and the configuration boundaries for a Space. +--- + +Spacefast manages the servers behind your Space. You publish files and configure application behavior; the infra handles hardware, replication, and the shared edge network. + +## Underlying infra + +WP Cloud runs origin pools on AMD EPYC processors with NVMe storage and redundant 25 Gbit networking per server. Primary and secondary servers sit in different regions for [automated failover](/infrastructure/automated-failover). Hardware and software change as the platform upgrades pools. + +Those are pool specifications, not dedicated resources reserved for each Space. Your product entitlements come from your [plan limits](/limits). + +## PHP and compression + +WP Cloud's default PHP memory limit is 512 MB per request. The platform supports larger per-site values, but Spacefast manages the settings for its sites. A WP Cloud capability does not create a matching Spacefast configuration field. + +The infra supports Brotli and gzip compression. A client that accepts Brotli can receive it; gzip is available as a fallback. Compression headers belong to the platform, so do not set `Content-Encoding` in your published header rules. + +For application access to WordPress, use the documented [WordPress commands and Abilities](/wordpress). The underlying PHP configuration is not a promise that arbitrary uploaded PHP files will execute. + +## Configuration boundaries + +| Change | Spacefast path | +| --- | --- | +| Redirects, rewrites, and response headers | Publish `_redirects`, `_headers`, or the supported [routing configuration](/routing). | +| Application environment variables | Use [Environment variables](/environment-variables). | +| Runtime configuration | Use the documented [Zero runtime configuration](/zero-runtime). | +| Storage and resource entitlements | Check [Limits](/limits). | + +Spacefast rejects authored `.htaccess` and `.user.ini` files. You cannot replace the managed server configuration or `php.ini` through a publish. Use the supported configuration for the behavior you need. + + diff --git a/content/infrastructure/tls-certificates.mdx b/content/infrastructure/tls-certificates.mdx new file mode 100644 index 00000000..db206350 --- /dev/null +++ b/content/infrastructure/tls-certificates.mdx @@ -0,0 +1,44 @@ +--- +title: TLS certificates +description: Automatic HTTPS, per-hostname certificate checks, and recovery from blocked issuance. +--- + +Spacefast provisions and renews HTTPS certificates for your Space's hostnames automatically. For a custom domain, issuance depends on correct DNS and a reachable validation path. + +## Provisioning and renewal + +WP Cloud manages certificates through Let's Encrypt and Google Trust Services. Issuance uses the ACME HTTP-01 challenge, so each hostname must resolve to the supplied infra addresses and allow validation over HTTP. + +The apex and `www` are validated independently. One can have a working certificate while the other is still pending. Check every hostname returned by your domain setup. + +Renewals happen automatically. Failed attempts are requeued with increasing delays, so correct the DNS or configuration problem before requesting another attempt. + +## Check a certificate + +```bash +sf domains diagnostics example.com --space my-site +``` + +The diagnostics report DNS, verification, and SSL state for each hostname. The UI and API use the familiar name SSL in some fields; the connection uses TLS. + +To inspect the certificate presented by a public hostname: + +```bash +openssl s_client -connect example.com:443 -servername example.com /dev/null | openssl x509 -noout -issuer -dates +``` + +Issuer names and chains can change. Do not pin an integration to a particular issuer common name. + +## When issuance is blocked + +Check that the hostname's address records match Spacefast's instructions. Remove old addresses that still send some requests elsewhere. If CAA records restrict certificate authorities, allow the authorities used for issuance. Check that an extra proxy or redirect does not block the HTTP validation request. + +After fixing the cause, use **Retry SSL** in the domain's dashboard controls or `POST /v1/domains/{domainId}/ssl/retry`. Retries are rate limited; repeated retries do not repair a DNS or CAA error. + +See [Custom domains](/domains#troubleshooting) for diagnostic codes such as `ssl_pending` and `ssl_renewal_blocked`. + +## Protocol support + +WP Cloud disables TLS 1.0 and TLS 1.1. Modern clients negotiate TLS 1.2 or TLS 1.3. Some TLS 1.2 ciphers remain for older-client compatibility, so evaluate scanner findings against the protocol and cipher the affected client actually negotiates. + + diff --git a/content/meta.ts b/content/meta.ts index 5a1250f9..bd345204 100644 --- a/content/meta.ts +++ b/content/meta.ts @@ -10,6 +10,7 @@ export default defineMeta({ "publish", "serve", "dynamic", + "infrastructure", "account", "reference", ], diff --git a/package.json b/package.json index f03777b8..4dd20154 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "blume": "2.2.6", - "zod": "4.6.0" + "zod": "4.6.5" }, "devDependencies": { "@spacefast/routing": "0.0.24", diff --git a/styles/Spacefast/spelling-exceptions.txt b/styles/Spacefast/spelling-exceptions.txt index 301e1788..33b925dd 100644 --- a/styles/Spacefast/spelling-exceptions.txt +++ b/styles/Spacefast/spelling-exceptions.txt @@ -5,11 +5,13 @@ accountless allowlist allowlisted alphanumerics +Anycast api apis approver approver's argv +Ashburn Astro async Automattic @@ -21,6 +23,7 @@ Blume's boolean booleans Bot's +Brotli browsable buildable burstable @@ -64,6 +67,7 @@ esbuild ETag exif extensionless +failover Favicon fetchable Figma @@ -72,8 +76,10 @@ followable forwardable frontmatter fsynced +Gbit github globals +Googlebot Gravatar grayscale Gridsome @@ -132,6 +138,7 @@ npx nullable Nullable Nuxt +NVMe oauth onboarding OpenAPI From 327aa14dd0d9ccd8ee6ad1255e35b87724eb39ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Sun, 8 Nov 2026 05:07:16 +0100 Subject: [PATCH 2/5] Name the dashboard's Retry HTTPS button as it is labelled --- content/(serve)/domains.mdx | 2 +- content/infrastructure/tls-certificates.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/(serve)/domains.mdx b/content/(serve)/domains.mdx index f9b12af8..f6875d29 100644 --- a/content/(serve)/domains.mdx +++ b/content/(serve)/domains.mdx @@ -211,7 +211,7 @@ www.example.com purpose=www dns=not_configured txt=missing ssl=missing | `verification_required` | The hostname needs proof of DNS control to keep serving. | Add the verification TXT record. | | `domain_ownership_required` | Another Space serves this hostname. | Publish the claim's TXT record, then verify to move it here. | | `ssl_pending` | Certificate issuance is in progress. | Wait. | -| `ssl_renewal_blocked` | A DNS record, usually CAA, is blocking issuance. | Fix the record, then retry SSL. | +| `ssl_renewal_blocked` | A DNS record, usually CAA, is blocking issuance. | Fix the record, then retry HTTPS. | | `provider_pending` | The edge has not observed the hostname yet. | Wait. | | `provider_rejected` | The hostname claim was rejected. | Contact support. | | `provider_error` | Attaching or detaching the hostname failed. | Contact support. | diff --git a/content/infrastructure/tls-certificates.mdx b/content/infrastructure/tls-certificates.mdx index db206350..517cd2a2 100644 --- a/content/infrastructure/tls-certificates.mdx +++ b/content/infrastructure/tls-certificates.mdx @@ -33,7 +33,7 @@ Issuer names and chains can change. Do not pin an integration to a particular is Check that the hostname's address records match Spacefast's instructions. Remove old addresses that still send some requests elsewhere. If CAA records restrict certificate authorities, allow the authorities used for issuance. Check that an extra proxy or redirect does not block the HTTP validation request. -After fixing the cause, use **Retry SSL** in the domain's dashboard controls or `POST /v1/domains/{domainId}/ssl/retry`. Retries are rate limited; repeated retries do not repair a DNS or CAA error. +After fixing the cause, use **Retry HTTPS** on the domain's page in the dashboard (it appears while a certificate is failing) or `POST /v1/domains/{domainId}/ssl/retry`. Retries are rate limited; repeated retries do not repair a DNS or CAA error. See [Custom domains](/domains#troubleshooting) for diagnostic codes such as `ssl_pending` and `ssl_renewal_blocked`. From 64d2d82f2b67d6e5d807cb0d1ae7ba03eaea723f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Sun, 8 Nov 2026 05:12:47 +0100 Subject: [PATCH 3/5] Answer the review: agent Markdown footer, edge logs, and Functions egress - blume.config.ts: a Markdown serializer for WpCloudDocs, so .md pages, llms-full.txt and MCP get the footer as Markdown instead of raw JSX. - CLI storage guide: sf logs takes access, edge or runtime, and access means origin requests; arguments, description and errors now say so. - Edge request logs: only the six multi-value filters repeat; --hostname, --since and --until take one value. - IP ranges: origin egress is the origin pool, Functions egress is Cloudflare's shared network. --- blume.config.ts | 6 ++++++ content/cli/storage.mdx | 8 ++++---- content/infrastructure/edge-request-logs.mdx | 2 +- content/infrastructure/ip-ranges.mdx | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/blume.config.ts b/blume.config.ts index 1329d7c5..622b4149 100644 --- a/blume.config.ts +++ b/blume.config.ts @@ -167,6 +167,12 @@ export default defineConfig({ }, agents: { llmsTxt: { details: llmsDetails }, + // The WP Cloud footer, written out as Markdown for .md pages, llms-full.txt + // and MCP: without this the component ships as raw JSX. + markdownComponents: { + WpCloudDocs: ({ props }) => + `Spacefast is built on Automattic's [WP Cloud](https://wp.cloud/). Using the [Partner API](${deploymentBase}/platforms/partner-api)? See [${String(props.title)}](${String(props.href)}) on WP Cloud Docs.`, + }, // The Website publishes Spacefast's agent skill at the site root; a second, // generated Docs skill would compete with it. skillMd: false, diff --git a/content/cli/storage.mdx b/content/cli/storage.mdx index fd201d29..4e1d5c03 100644 --- a/content/cli/storage.mdx +++ b/content/cli/storage.mdx @@ -5,7 +5,7 @@ sidebar: order: 23 --- -List your app's stored objects and read access or runtime logs within your plan's retention window. Runtime lines take time to appear, and static Spaces have no runtime logs. +List your app's stored objects and read access, edge, or runtime logs within your plan's retention window. Runtime lines take time to appear, and static Spaces have no runtime logs. Every command here takes the global flags (`--api-url`, `--profile`, `--token`, `-y`/`--yes`, `--json`) and the space selection flags (`--space`, `-o`/`--team`, `--claim-token`). See [the CLI overview](/cli). @@ -84,7 +84,7 @@ With `--json`, `data` carries `deleted`. Read a Space's logs. -`access` is every request the edge served. `runtime` is what your code logged, with the request id and handler for each line. A static Space has no runtime lines. +`access` is every request that reached your Space's origin. `edge` is every request the edge served, cache hits included; see [Edge request logs](/infrastructure/edge-request-logs) for its filters. `runtime` is what your code logged, with the request id and handler for each line. A static Space has no runtime lines. A line you just triggered takes a while to appear — it's written on the origin, shipped, and indexed before it can be read back. **An empty page means not yet, not broken.** Keep paging while the cursor is there: a page can come back empty while there's still more to read. @@ -98,7 +98,7 @@ sf logs [target] [kind] [--space ] [--limit ] [-f] [--cursor ] | Argument | What it is | | --- | --- | | `[target]` | Space ID, slug, live URL, or domain. Defaults to the linked Space | -| `[kind]` | `access` or `runtime`. Defaults to `access` | +| `[kind]` | `access`, `edge`, or `runtime`. Defaults to `access` | A bare kind in the first slot works: `sf logs runtime` is the same as `sf logs --space runtime`. @@ -136,5 +136,5 @@ Log history is a plan limit. A request that reaches past your retention window i | Code | Exit | When | | --- | --- | --- | -| `validation_error` | 2 | `kind` is not `access` or `runtime` | +| `validation_error` | 2 | `kind` is not `access`, `edge`, or `runtime` | | `validation_error` | 2 | `--request-id` or `--handler` passed with the access log | diff --git a/content/infrastructure/edge-request-logs.mdx b/content/infrastructure/edge-request-logs.mdx index 12f4eb19..68cd7b64 100644 --- a/content/infrastructure/edge-request-logs.mdx +++ b/content/infrastructure/edge-request-logs.mdx @@ -30,7 +30,7 @@ Each query covers one assigned hostname and defaults to the primary hostname. Us | `--asn` | Source network's autonomous system number | | `--since`, `--until` | ISO 8601 timestamps for the query window | -Repeat a filter flag to include more values. Values within one field use OR; different fields use AND. +`--remote-addr`, `--ja3-hash`, `--method`, `--status`, `--user-agent`, and `--asn` can be repeated to include more values. `--hostname`, `--since`, and `--until` take one value each. Values within one field use OR; different fields use AND. The default window is the past hour. A query can span at most one hour within the past 24 hours, and your plan's retention can shorten that window. Results arrive newest first. Use smaller windows to investigate busy periods. diff --git a/content/infrastructure/ip-ranges.mdx b/content/infrastructure/ip-ranges.mdx index cc3e2ce5..771adf3a 100644 --- a/content/infrastructure/ip-ranges.mdx +++ b/content/infrastructure/ip-ranges.mdx @@ -20,7 +20,7 @@ sf domains diagnostics example.com --space my-site ## Outbound connections -A request from your Space to an external service uses an origin pool's outbound address. That address can change after [automated failover](/infrastructure/automated-failover), relocation, or replacement of the underlying site. +A request your Space's origin makes to an external service uses an origin pool's outbound address. Functions workers are different: they send from Cloudflare's shared network, so an allowlist built on the origin pool does not cover them. See [Functions outbound HTTP](/functions#outbound-http). That address can change after [automated failover](/infrastructure/automated-failover), relocation, or replacement of the underlying site. Outbound addresses can be shared with other sites. An IP allowlist covering a complete infra range does not authenticate your application, and a single observed address is not a stable integration contract. Use the external service's authentication mechanism. If it also requires an IP allowlist, contact Spacefast support to discuss the requirement before depending on a fixed address. From 2edde4979562105d2d735f41594c1ec46e4f5073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Sun, 8 Nov 2026 05:14:08 +0100 Subject: [PATCH 4/5] Keep the failover caveat next to the origin-pool address it describes --- content/infrastructure/ip-ranges.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/content/infrastructure/ip-ranges.mdx b/content/infrastructure/ip-ranges.mdx index 771adf3a..aa572dea 100644 --- a/content/infrastructure/ip-ranges.mdx +++ b/content/infrastructure/ip-ranges.mdx @@ -20,7 +20,9 @@ sf domains diagnostics example.com --space my-site ## Outbound connections -A request your Space's origin makes to an external service uses an origin pool's outbound address. Functions workers are different: they send from Cloudflare's shared network, so an allowlist built on the origin pool does not cover them. See [Functions outbound HTTP](/functions#outbound-http). That address can change after [automated failover](/infrastructure/automated-failover), relocation, or replacement of the underlying site. +A request your Space's origin makes to an external service uses an origin pool's outbound address. That address can change after [automated failover](/infrastructure/automated-failover), relocation, or replacement of the underlying site. + +Functions workers are different: they send from Cloudflare's shared network, so an allowlist built on the origin pool does not cover them. See [Functions outbound HTTP](/functions#outbound-http). Outbound addresses can be shared with other sites. An IP allowlist covering a complete infra range does not authenticate your application, and a single observed address is not a stable integration contract. Use the external service's authentication mechanism. If it also requires an IP allowlist, contact Spacefast support to discuss the requirement before depending on a fixed address. From eb7b5389f74bd1c64fee0be0fec05aed60c301f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Sun, 8 Nov 2026 05:21:50 +0100 Subject: [PATCH 5/5] Describe edge logs as requests handled at the edge, with their query limits --- content/cli/storage.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/cli/storage.mdx b/content/cli/storage.mdx index 4e1d5c03..bb4d82f7 100644 --- a/content/cli/storage.mdx +++ b/content/cli/storage.mdx @@ -84,7 +84,7 @@ With `--json`, `data` carries `deleted`. Read a Space's logs. -`access` is every request that reached your Space's origin. `edge` is every request the edge served, cache hits included; see [Edge request logs](/infrastructure/edge-request-logs) for its filters. `runtime` is what your code logged, with the request id and handler for each line. A static Space has no runtime lines. +`access` covers requests that reached your Space's origin. `edge` covers requests handled at the edge, cache hits included. Each edge query reads one hostname (the primary unless you pass `--hostname`), and a busy window can be truncated; see [Edge request logs](/infrastructure/edge-request-logs) for its filters and limits. With `runtime` you get what your code logged, with the request id and handler for each line. A static Space has no runtime lines. A line you just triggered takes a while to appear — it's written on the origin, shipped, and indexed before it can be read back. **An empty page means not yet, not broken.** Keep paging while the cursor is there: a page can come back empty while there's still more to read.