From d807dea174f98c81e6d934da6067b65b79b28d2d Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Tue, 16 Jun 2026 16:47:42 +0700 Subject: [PATCH 1/2] docs: cover undocumented API features and fix inaccuracies Audit the docs against the api repo's interface contract and close the user-facing gaps, plus correct several factual errors verified against api/ and apiserver/ source. New coverage: - WAF rate limiting (limits, keys, shadow mode, waf.limitMetrics) - GitHub link management in the API catalog - project.metrics / project.storageMetrics, disk.metrics - registry.get / getProjectStorage / metrics examples - IPFS/IPNS/DNSLink route targets (API-only) - cache override priority/mode fields Corrections: - audit log: outcomes are success/failure (not forbidden/error); denials are not logged (authz returns before recordAudit); filters are after/before + lowercase resourceType, no action filter; retention is a 1-year TTL, not project lifetime - roles permission table: rewritten from the lowercase catalog; removed non-grantable strings, added missing namespaces, fixed casing - sidecars: only the Cloud SQL Auth Proxy is supported, not generic containers Co-Authored-By: Claude Opus 4.8 (1M context) --- content/access/audit-log.md | 78 +++++++++++++++++---------- content/access/projects.md | 15 ++++++ content/access/roles.md | 61 ++++++++++++++------- content/api/conventions.md | 25 +++++++-- content/deployments/configuration.md | 27 ++++++++-- content/networking/cache.md | 5 ++ content/networking/routes.md | 13 +++++ content/networking/waf.md | 79 ++++++++++++++++++++++++++++ content/registry/overview.md | 20 +++++++ content/storage/disks.md | 16 ++++++ 10 files changed, 283 insertions(+), 56 deletions(-) diff --git a/content/access/audit-log.md b/content/access/audit-log.md index dfe1f83..fc9be8d 100644 --- a/content/access/audit-log.md +++ b/content/access/audit-log.md @@ -2,25 +2,36 @@ title: 'Audit log' linkTitle: 'Audit log' weight: 5 -description: 'Who did what, when. Filterable by resource, outcome, and time range.' -lead: 'Every state-changing API call lands in the audit log — actor, action, resource, outcome, and timestamp. Use it to answer "who deployed that?" and "what was tried but blocked?"' +description: 'Who did what, when. Filterable by resource, actor, outcome, and time range.' +lead: 'Every state-changing API call that passes authorization lands in the audit log — actor, action, resource, outcome, and timestamp. Use it to answer "who deployed that?" and "which writes failed?"' --- ## What gets logged -Every call that creates, updates, or deletes a resource — `deployment.deploy`, -`deployment.rollback`, `domain.create`, `route.delete`, `role.bind`, -`serviceAccount.createKey`, and so on — is recorded. Read-only calls -(`*.list`, `*.get`, `*.metrics`) are not. +Every call that creates, updates, or deletes a resource — a deploy, a rollback, +a domain create, a route delete, a role grant, a service-account key create, and +so on — is recorded once it passes authorization. Read-only calls (`*.list`, +`*.get`, `*.metrics`) are not. + +{{< callout type="note" >}} +**Permission denials are not logged.** A call rejected by the permission check +returns before the write is attempted, so it never reaches the audit log. The +log records *authorized* writes — the ones that ran — not access attempts. To +reason about who *can* do what, use [roles](/access/roles/), not the audit log. +{{< /callout >}} Each entry captures: - **Actor** — the principal who made the call (user email or service-account - email), plus their type. -- **Action** — the API function name, e.g. `deployment.deploy`. -- **Resource** — the type, ID, name, and location of the affected resource. -- **Outcome** — `success`, `forbidden`, or `error`. -- **Detail** — a short human-readable summary (e.g. *"Deployed revision 7"*). + email), plus their type (`User` or `ServiceAccount`). +- **Action** — the verb that ran: `deploy`, `create`, `delete`, `rollback`, + `grant`, `revoke`, and so on. +- **Resource** — the `type` (`deployment`, `domain`, `role`, …, lowercase), plus + the id, name, and location of the affected resource. +- **Outcome** — `success` or `failure`. A `failure` is an authorized call that + *ran but errored* — a validation error, a conflict, a downstream failure — not + a permission denial. +- **Detail** — a short human-readable summary (e.g. *"revision 7"*). - **Created at** — when the call happened, in UTC. ## Filter and browse @@ -28,50 +39,59 @@ Each entry captures: The Audit Logs page lets you narrow by: - **Resource type** — Deployment, Domain, Route, Disk, Role, ServiceAccount, … -- **Outcome** — success, forbidden, error. +- **Outcome** — success or failure. - **Date range** — today, last 7 days, last 30 days, last 90 days, last year, or a custom range. -The same filters are available on the API: +The `auditLog.list` function takes the same filters — plus an `actor` filter the +console doesn't expose — and a `limit`. `resourceType` and `outcome` match +exactly, and the resource type is **lowercase** (`deployment`, not +`Deployment`). The time window is `after` / `before` (RFC 3339). There is no +`action` filter — narrow by `resourceType`, then read the `action` field on each +entry. ```bash curl https://api.deploys.app/auditLog.list \ -H "Authorization: Bearer $DEPLOYS_TOKEN" \ -d '{ "project": "acme", - "resourceType": "Deployment", + "resourceType": "deployment", "outcome": "success", - "from": "2026-05-01T00:00:00Z", - "to": "2026-06-01T00:00:00Z" + "after": "2026-05-01T00:00:00Z", + "before": "2026-06-01T00:00:00Z", + "limit": 200 }' ``` -The response is a paginated list of entries you can sift through or pipe -through `jq` for ad-hoc analysis. +The response is a list of entries you can sift through or pipe through `jq` for +ad-hoc analysis. ## Common queries -- **"Who deployed the bad release?"** — filter by `Deployment` resource type, - action `deployment.deploy`, and the rough time window. The actor on the +- **"Who deployed the bad release?"** — filter by `deployment` resource type and + the rough time window, then look for `action: "deploy"`. The actor on the matching entry is your culprit (or your hero). -- **"What was blocked?"** — outcome `forbidden`. Useful when adjusting - [roles](/access/roles/) — a string of failures usually means someone needs a - permission you forgot to add. -- **"What did the CI service account touch yesterday?"** — set the actor email - on the API call (the console doesn't expose this filter directly). +- **"Which writes failed?"** — outcome `failure`. These are calls that were + *allowed* but errored while running — a bad request body, a name conflict, a + downstream failure — so it's a debugging aid for automation, not a record of + blocked access. +- **"What did the CI service account touch yesterday?"** — set `actor` to the + service-account email plus an `after` / `before` window (the console doesn't + expose the actor filter directly). ## Retention -Entries are retained for the lifetime of the project. Deleting a resource -doesn't delete its audit history; deleting the *project* eventually purges -it, but a record of project deletion itself is retained. +Entries are kept for **one year** after they're written, then purged +automatically by the database's row-level TTL — no action needed on your part. +Deleting a resource doesn't remove its existing audit history; the entries age +out on the same one-year clock. ## Streaming to your SIEM Two patterns work well: - **Pull periodically.** A small service account with `auditLog.list` polls - every few minutes for new entries (filter by `from` ≥ last-seen + every few minutes for new entries (filter by `after` ≥ last-seen `createdAt`) and forwards to your aggregator. - **Pull at quarter-of-the-hour cadence** if you only need rough near-real-time. Run a cron deployment with `--type CronJob` and diff --git a/content/access/projects.md b/content/access/projects.md index 9de0a5c..c7b5096 100644 --- a/content/access/projects.md +++ b/content/access/projects.md @@ -61,6 +61,21 @@ Returns the project's current monthly usage rolled up by resource type. The same data drives the project dashboard and feeds the [billing report](/billing/usage-reports/). +For charts rather than a single rollup, two API functions return time-series +over a `timeRange` (`7d`, `30d`, or `90d`): + +- **`project.metrics`** — CPU, memory, disk, egress, replica, and static-storage + usage over time, the series behind the project dashboard. +- **`project.storageMetrics`** — static-site storage held over time. + +```bash +curl https://api.deploys.app/project.metrics \ + -H "Authorization: Bearer $DEPLOYS_TOKEN" \ + -d '{ "project": "acme", "timeRange": "30d" }' +``` + +Both need only `project.get`. + ## Deleting a project A project can be deleted only when it's empty — every deployment, domain, diff --git a/content/access/roles.md b/content/access/roles.md index 838a263..9313c3f 100644 --- a/content/access/roles.md +++ b/content/access/roles.md @@ -34,27 +34,47 @@ deploys role create \ --permissions "project.get,deployment.list,deployment.get,deployment.deploy,registry.list" ``` -The `--permissions` flag takes a comma-separated list of API function names. -Each function name (e.g. `deployment.deploy`) is one permission — the same -string you'd POST to as `https://api.deploys.app/`. - -The most useful permissions: +The `--permissions` flag takes a comma-separated list of permission strings. +A permission is `.`, and unlike the API function names it is +**always lowercase** — the `serviceAccount.createKey` call, for example, is +guarded by the `serviceaccount.key.create` permission. Matching is exact, so the +casing matters: `serviceAccount.createKey` in a role grants nothing. The +authoritative list is whatever `role.permissions` returns; the most useful ones: | Group | Permissions | |---|---| -| Project | `project.get`, `project.update`, `project.delete`, `project.usage` | -| Deployment | `deployment.list`, `deployment.get`, `deployment.deploy`, `deployment.delete`, `deployment.pause`, `deployment.resume`, `deployment.rollback`, `deployment.metrics`, `deployment.revisions` | -| Domain | `domain.list`, `domain.get`, `domain.create`, `domain.delete`, `domain.purgeCache` | -| Route | `route.list`, `route.create`, `route.delete` | +| Project | `project.get`, `project.delete` | +| Deployment | `deployment.list`, `deployment.get`, `deployment.deploy`, `deployment.delete` | +| Domain | `domain.list`, `domain.get`, `domain.create`, `domain.delete`, `domain.purgecache` | +| Route | `route.list`, `route.get`, `route.create`, `route.delete` | +| Firewall (WAF) | `waf.list`, `waf.get`, `waf.set`, `waf.delete` | +| Cache | `cache.list`, `cache.get`, `cache.set`, `cache.delete` | | Disk | `disk.list`, `disk.get`, `disk.create`, `disk.update`, `disk.delete` | -| Registry | `registry.list`, `registry.delete`, `registry.deleteManifest`, `registry.untag` | -| Pull secret | `pullSecret.list`, `pullSecret.create`, `pullSecret.delete` | -| Role | `role.list`, `role.create`, `role.delete`, `role.bind` | -| Service account | `serviceAccount.list`, `serviceAccount.create`, `serviceAccount.delete`, `serviceAccount.createKey` | -| Billing | `billing.get`, `billing.report`, `billing.listInvoices` | -| Audit | `auditLog.list` | - -The wildcard `*` matches everything. +| Registry | `registry.list`, `registry.get`, `registry.pull`, `registry.push` | +| Pull secret | `pullsecret.list`, `pullsecret.get`, `pullsecret.create`, `pullsecret.delete` | +| Env group | `envgroup.list`, `envgroup.get`, `envgroup.create`, `envgroup.update`, `envgroup.delete` | +| Workload identity | `workloadidentity.list`, `workloadidentity.get`, `workloadidentity.create`, `workloadidentity.delete` | +| Service account | `serviceaccount.list`, `serviceaccount.get`, `serviceaccount.create`, `serviceaccount.delete`, `serviceaccount.key.create`, `serviceaccount.key.delete` | +| Role | `role.list`, `role.get`, `role.create`, `role.delete`, `role.bind` | +| GitHub | `github.list`, `github.link`, `github.unlink`, `github.update` | +| Email | `email.list`, `email.send` | +| Dropbox | `dropbox.list`, `dropbox.upload` | +| Static sites | `site.publish` | +| Audit | `auditlog.list` | + +Some actions don't have their own permission — they ride on a broader one. +`deployment.metrics`, `deployment.revisions`, `deployment.rollback`, +`deployment.pause`, and `deployment.resume` are all covered by `deployment.get` +or `deployment.deploy`; `registry.delete` / `deleteManifest` / `untag` are +covered by `registry.push`; `project.usage` and `project.metrics` by +`project.get`. Granting the made-up string does nothing — grant the broader +permission instead. + +The wildcard `*` matches everything, and each namespace has a `.*` +(for example `domain.*`) covering that namespace's actions. + +Billing access isn't a project permission: billing calls are authorized by +**ownership of the billing account**, not by a role in the project. ## Binding roles @@ -104,10 +124,11 @@ The audit log records permission denials too — failed calls show up with - **Deployer for CI**, restricted to `deployment.deploy` and the read calls needed to inspect status. CI never needs to manage roles or delete projects. -- **Viewer for the on-call rotation**, plus `deployment.metrics` and - `auditLog.list` if you want them to debug without changing anything. +- **Viewer for the on-call rotation**, plus `auditlog.list` if you want them to + debug without changing anything. (Viewer already has `deployment.get`, which + covers metrics and revisions.) - **Operator** with everything except `project.delete`, `role.bind`, and - `serviceAccount.createKey`. Day-to-day powerful, but can't change who has + `serviceaccount.key.create`. Day-to-day powerful, but can't change who has access or generate new machine credentials. Keep `admin` to the smallest practical group; everyone else gets a tailored diff --git a/content/api/conventions.md b/content/api/conventions.md index 8b5d5c5..c66817f 100644 --- a/content/api/conventions.md +++ b/content/api/conventions.md @@ -93,8 +93,10 @@ The big picture. Each row is a fully-qualified API function. | `domain.list` / `.get` / `.create` / `.delete` | Domain CRUD | | `domain.purgeCache` | CDN cache purge for a domain | | `route.list` / `.create` / `.createV2` / `.delete` | Route CRUD | -| `waf.list` / `.get` / `.set` / `.delete` | Firewall zone CRUD | -| `waf.metrics` | Firewall match counts over time | +| `waf.list` / `.get` / `.set` / `.delete` | Firewall zone CRUD (rules + rate limits) | +| `waf.metrics` / `.limitMetrics` | Firewall match counts and rate-limit decisions over time | +| `cache.list` / `.get` / `.set` / `.delete` | Cache-override zone CRUD | +| `cache.metrics` | Cache-override decision counts over time | ### Storage and registry @@ -132,12 +134,27 @@ The big picture. Each row is a fully-qualified API function. | `billing.listInvoices` / `.getInvoice` / `.downloadInvoice` | Invoices | | `billing.uploadTransferSlip` | Submit a bank-transfer receipt | +### GitHub + +For [build-and-deploy from GitHub](/automation/deploy-from-github/). These manage +the link between a repository and the service account it deploys as. + +| Function | What it does | +|---|---| +| `github.list` | Repositories linked in the project | +| `github.link` / `.unlink` | Link or unlink a repository to a service account | +| `github.update` | Change a link's service account, deploy trigger, or production branch | + +The keyless token exchange and build/deploy status reporting (`github.exchangeToken`, +`github.notify`) are authenticated by the workflow's GitHub OIDC token and called +by the [build-and-deploy action](/automation/deploy-from-github/), not directly. + ### Other | Function | What it does | |---|---| -| `email.list` | Email domains attached to the project | -| `dropbox.list` / `.metrics` | Dropbox uploads (alpha) | +| `email.list` / `.send` | List project email domains; send a transactional email | +| `dropbox.list` / `.metrics` | [Dropbox](/storage/dropbox/) stored files and usage | ## Typed clients diff --git a/content/deployments/configuration.md b/content/deployments/configuration.md index bd65d42..9ee67c7 100644 --- a/content/deployments/configuration.md +++ b/content/deployments/configuration.md @@ -126,9 +126,30 @@ Optional `subPath` mounts a sub-directory of the disk only. ## Sidecars — `sidecars` -Each entry has its own `name`, `image`, `port`, `resources`, `command`, `args`, -and `env`. Use them sparingly — they share the pod with the main container and -its lifecycle. +A sidecar is a helper container that shares the pod with your main container and +its lifecycle. Today the only supported sidecar is the **Cloud SQL Auth Proxy**, +configured under `cloudSqlProxy` — you don't supply an arbitrary image: + +```json +"sidecars": [ + { + "cloudSqlProxy": { + "instance": "my-project:asia-southeast1:main", + "port": 5432, + "credentials": "" + } + } +] +``` + +- **`instance`** — required; the Cloud SQL instance connection name. +- **`port`** — the local port the proxy listens on (default `3300`). Your app + connects to the database at `127.0.0.1:`. +- **`credentials`** — optional service-account JSON for the proxy; omit it to use + the deployment's ambient credentials. + +The platform runs this as a `cloudsql-proxy` container alongside yours. Arbitrary +sidecar containers (your own image, command, and env) aren't supported yet. ## TTL and one-shot jobs — `ttl` diff --git a/content/networking/cache.md b/content/networking/cache.md index 2c38062..2f2ffab 100644 --- a/content/networking/cache.md +++ b/content/networking/cache.md @@ -72,6 +72,11 @@ A `cache` override is described by a few fields: errors. - **`status`** — optional; force only these origin response statuses (e.g. `[200, 301]`). Empty forces every cacheable status. +- **`priority`** — orders the `cache` rules against each other; the lowest number + wins and declaration order breaks ties. `0` resolves to the default (`100`). + `bypass` rules aren't ordered — a matching bypass always wins. +- **`mode`** — `enforce` (default) applies the override; `shadow` evaluates and + counts it without changing caching. See [Roll out safely](#roll-out-safely). ## The filter expression diff --git a/content/networking/routes.md b/content/networking/routes.md index 39c4ca7..f2f3ce2 100644 --- a/content/networking/routes.md +++ b/content/networking/routes.md @@ -53,6 +53,19 @@ three types when you create or edit a route: | **Redirect** | `redirect://https://example.com` | Return an HTTP redirect to the given URL. | | **External server (HTTP)** | `http://[:port]` | Front a server you run yourself — see [below](#external-server-http). | +### Content-addressed targets (API only) + +Three more target schemes serve content from the platform's shared IPFS gateway +instead of a deployment. They're accepted by `route.createV2` but aren't in the +console's target picker — set them through the API, and the console will display +(and round-trip) an existing one unchanged. + +| Type | `target` value | What it does | +|---|---|---| +| **IPFS** | `ipfs://` | Serve an immutable IPFS object by content id. | +| **IPNS** | `ipns://` | Serve a mutable IPNS name (resolves to its current object). | +| **DNSLink** | `dnslink://` | Serve content published via a domain's DNSLink record. | + ## Routes with config (v2) The `routeV2` flow lets you set any of the target types above and attach extra diff --git a/content/networking/waf.md b/content/networking/waf.md index 781f897..2e2b6d0 100644 --- a/content/networking/waf.md +++ b/content/networking/waf.md @@ -82,6 +82,73 @@ priority 90 — log — request.headers['user-agent'].contains('bot') on the metrics page for a day, then flip it to `block` once you've confirmed it's catching what you expect (and not what you don't). +## Rate limiting + +Alongside the block/log/allow rules, a zone can carry **rate limits** — counters +that reject (or just watch) traffic arriving faster than a threshold. Limits are +independent of the rules: they're evaluated for every request the zone covers, +so a request that passes every rule can still be rejected by a limit. + +A limit sorts requests into **buckets** and rejects a bucket once it exceeds +`rate` requests per `window`. What defines a bucket is the `key`: + +| Key | One bucket per | +|---|---| +| `ip` | client IP (the default) | +| `host` | request hostname | +| `asn` | client network (autonomous system number) | +| `country` | client country | +| `header:` | value of a request header | +| `cookie:` | value of a cookie | + +List several to bucket on the combination — `["ip", "host"]` limits each IP +*per host*. With no key the limit defaults to `["ip"]`. + +Limits live on the same zone as the rules. Set them with `waf.set`, in a +`limits` array next to `rules` — and, like the rules, `waf.set` replaces the +whole zone, so send the full `limits` list every time: + +```json +"limits": [ + { + "description": "100 req/min per IP", + "key": ["ip"], + "rate": 100, + "window": "1m" + }, + { + "description": "Throttle login to slow credential stuffing", + "key": ["ip"], + "rate": 5, + "window": "1m", + "filter": "request.path == '/login' && request.method == 'POST'", + "status": 429, + "message": "Too many attempts — slow down." + } +] +``` + +Each limit understands: + +| Field | | Meaning | +|---|---|---| +| `rate` | required | Max requests per `window` per bucket (> 0). | +| `window` | required | Go duration, `1s`–`1h` (e.g. `30s`, `1m`, `1h`). | +| `key` | optional | Bucket characteristics (above); default `["ip"]`. | +| `algorithm` | optional | `fixed` (default) fixed window, or `sliding` for a smoother rolling window. | +| `mode` | optional | `enforce` (default) rejects; `shadow` only counts — see below. | +| `status` | optional | Response status when limited: `429` (default) or `503`. | +| `message` | optional | Response body when limited (default `Too Many Requests`). | +| `filter` | optional | A CEL expression (the same `request.*` surface as rule expressions) scoping the limit to matching requests; empty means every request. A filter that errors at runtime fails *open* — the limit is skipped — so a bad filter can't reject good traffic. | + +A zone holds up to 20 limits. + +**Size a limit in shadow mode first.** Set `"mode": "shadow"` and the limit +counts matches without rejecting anything. Watch the limited share on the metrics +page for a day or two, confirm the threshold only catches abuse, then flip it to +`enforce`. It's the rate-limit equivalent of rolling out a rule as `log` before +`block`. + ## Metrics The Firewall metrics page plots matches per (rule, action) over a selectable @@ -96,3 +163,15 @@ curl https://api.deploys.app/waf.metrics \ -d '{ "project": "acme", "location": "gke.cluster-rcf2", "timeRange": "1d" }' ``` + +Rate limits have their own series via `waf.limitMetrics`, returned per +(limit, result) where `result` is `allowed` or `limited`. Charting the limited +share — `limited / (allowed + limited)` — is how you size a `shadow` limit +before enforcing it. + +```bash +curl https://api.deploys.app/waf.limitMetrics \ + -H "Authorization: Bearer $DEPLOYS_TOKEN" \ + -d '{ "project": "acme", "location": "gke.cluster-rcf2", + "timeRange": "1d" }' +``` diff --git a/content/registry/overview.md b/content/registry/overview.md index da76921..9e4615b 100644 --- a/content/registry/overview.md +++ b/content/registry/overview.md @@ -96,6 +96,26 @@ Storage is metered and billed — see the **Usage** button in the top-right of the Registry page for the current size of each repository over time. Trim unused tags and manifests to keep the bill in check. +The same numbers are available from the API. `registry.get` returns one +repository's current size; `registry.getProjectStorage` returns the whole +project's registry footprint; and `registry.metrics` returns storage and egress +as time-series over a `timeRange` (`7d`, `30d`, or `90d`) — the series behind the +Usage charts. + +```bash +# one repository's size right now +curl https://api.deploys.app/registry.get \ + -d '{ "project": "acme", "repository": "acme/web" }' + +# the project's total registry storage +curl https://api.deploys.app/registry.getProjectStorage \ + -d '{ "project": "acme" }' + +# storage + egress over time +curl https://api.deploys.app/registry.metrics \ + -d '{ "project": "acme", "timeRange": "30d" }' +``` + ```bash # delete a tag (frees nothing if the manifest is still tagged elsewhere) curl https://api.deploys.app/registry.untag \ diff --git a/content/storage/disks.md b/content/storage/disks.md index b7f9097..cacd6ba 100644 --- a/content/storage/disks.md +++ b/content/storage/disks.md @@ -75,6 +75,22 @@ doesn't need to restart, but the filesystem inside the container may not see the new space until the container is restarted or runs `resize2fs` (depending on the filesystem). +## Usage over time + +`disk.metrics` returns two time-series for a disk — **usage** (bytes actually +written) and **size** (the provisioned capacity) — over a `timeRange` (`1h`, +`6h`, `12h`, `1d`, `2d`, `7d`, or `30d`). It's how you spot a volume trending +toward full before it gets there, so you can resize ahead of an outage. + +```bash +curl https://api.deploys.app/disk.metrics \ + -H "Authorization: Bearer $DEPLOYS_TOKEN" \ + -d '{ "project": "acme", "location": "gke.cluster-rcf2", + "name": "uploads", "timeRange": "7d" }' +``` + +The same data backs the usage chart on the disk's page in the console. + ## Delete a disk ```bash From 07e0eebd8371203a55e81b043cec387a2ecb7ba2 Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Tue, 16 Jun 2026 16:58:30 +0700 Subject: [PATCH 2/2] docs: drop deprecated ipfs/ipns/dnslink route targets These content-addressed schemes are deprecated; don't document them. Co-Authored-By: Claude Opus 4.8 (1M context) --- content/networking/routes.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/content/networking/routes.md b/content/networking/routes.md index f2f3ce2..39c4ca7 100644 --- a/content/networking/routes.md +++ b/content/networking/routes.md @@ -53,19 +53,6 @@ three types when you create or edit a route: | **Redirect** | `redirect://https://example.com` | Return an HTTP redirect to the given URL. | | **External server (HTTP)** | `http://[:port]` | Front a server you run yourself — see [below](#external-server-http). | -### Content-addressed targets (API only) - -Three more target schemes serve content from the platform's shared IPFS gateway -instead of a deployment. They're accepted by `route.createV2` but aren't in the -console's target picker — set them through the API, and the console will display -(and round-trip) an existing one unchanged. - -| Type | `target` value | What it does | -|---|---|---| -| **IPFS** | `ipfs://` | Serve an immutable IPFS object by content id. | -| **IPNS** | `ipns://` | Serve a mutable IPNS name (resolves to its current object). | -| **DNSLink** | `dnslink://` | Serve content published via a domain's DNSLink record. | - ## Routes with config (v2) The `routeV2` flow lets you set any of the target types above and attach extra