From ed8af39e814ac3cf45d41b29d52b9e23fc49d620 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 20 Aug 2026 07:55:49 -0700 Subject: [PATCH 1/2] docs(protocol): document DIG_NODE_FORWARD_ON_MISS forwarded-ask gate Adds the FORWARDED ASK bullet to the redirect-on-miss section of peer-network.md (and its 13 locale mirrors), covering the DIG_NODE_FORWARD_ON_MISS env var: default OFF, fail-closed on any unrecognised value, the peer-recruitment behaviour, the ~1,300+ outbound dial/DHT-walk amplification cost of one admitted miss, and the disclosure radius of enabling it. This is the docs sibling of dig-node PR #258 (v0.128.0), which shipped the forwarded ask but left it undocumented alongside the existing DIG_NODE_ON_MISS=fetch setting. Closes #75 Co-Authored-By: Claude --- docs/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ .../current/protocol/peer-network.md | 6 ++++++ 14 files changed, 84 insertions(+) diff --git a/docs/protocol/peer-network.md b/docs/protocol/peer-network.md index 4f1480d..9dc690a 100644 --- a/docs/protocol/peer-network.md +++ b/docs/protocol/peer-network.md @@ -813,6 +813,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** An operator-level setting: instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to every caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). - **PROXY (opt-in per request, `params.proxy`, default `false`).** A caller-level alternative to fetch-through, for a caller that cannot itself reach any named holder (e.g. NAT asymmetry): setting `proxy: true` on `dig.getContent` / `dig.fetchRange` asks THIS node to fetch the resource, over the identical chain-anchored, merkle-verified path, and return the bytes directly instead of redirecting. Automatic fetch-on-miss stays off by default — the caller opts in per request. The node serves the bytes but does **not** become a holder of the content by doing so (a proxied read never triggers reshare/backfill), so `proxy: true` cannot be used to plant attacker-chosen inventory on a node. A miss already reveals the requested content id to the node you ask; setting `proxy: true` additionally reveals to the serving holder that you wanted that resource — the same disclosure a direct read from that holder would make. +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/hi/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/id/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/ru/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/tr/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md index 5ec3fb2..f008c70 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/protocol/peer-network.md @@ -696,6 +696,12 @@ A content read (`dig.getContent`, `dig.fetchRange`, or a peer range stream) may - **FETCH-THROUGH (opt-in, `DIG_NODE_ON_MISS=fetch`).** Instead of redirecting, the node **pulls** the resource from the holder(s) via the [multi-source download](#multi-source) (verified against the chain-anchored root), caches it, and **serves it directly** — transparent to the caller, one round-trip, and the node now holds it. If the fetch fails the node falls back to the redirect (still never a silent 404 while a holder exists). +- **FORWARDED ASK (opt-in, `DIG_NODE_FORWARD_ON_MISS`, default OFF).** An operator-level setting: on a miss, the node also asks its own connected peers whether THEY hold the content, merging any holders they name into the redirect. Unset, empty, or any value other than `on`/`1`/`true`/`yes` (case-insensitive) leaves it disabled — a misspelled value cannot turn it on. Off, a miss is answered from this node's own DHT lookup alone, exactly as if the setting did not exist. + + **Enabling it is a real amplification decision, not a small one.** A relay token is charged once per admitted miss and buys several outbound asks; those asks recruit further peers who each ask further peers again, so **one admitted request can fan out to on the order of 1,300+ outbound dials and DHT lookups across the network**, not just at this node. That cost is borne by every node downstream of you, not only your own, which is why the setting defaults off and why turning it on is an operator decision to make deliberately, not a knob to flip for a marginal cache-hit improvement. + + **It also tells your peers what you are looking for.** Asking a peer "do you hold X?" discloses X to that peer, the same disclosure a direct read from a holder already makes — but with the forwarded ask, that disclosure now reaches every peer recruited into the fan-out, not just the one peer you originally asked. + **The redirect is a READ-TIER response.** It carries only what the caller needs to reach a holder — it exposes no peer/write/control surface — so it is served on both the mTLS peer/control tier and, where the read path is public ([§0](#dual-transport)), the anonymous read tier. **Bounded hops (no loops).** The redirect carries a `redirect_depth` (the number of redirects already followed) and the `max_redirects` cap. A caller **echoes `redirect_depth`** in its re-request `params`; a node that receives a request already at/over the cap answers the plain not-found instead of another redirect, so a set of nodes can never bounce a caller in a loop. A node **never redirects a caller back to itself** (its own `peer_id` is excluded from the providers). From fb0cb8168d997cb9f7dc5a314ae3b7564da7ee98 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 20 Aug 2026 08:38:05 -0700 Subject: [PATCH 2/2] chore(release): bump version to 0.16.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 22facaf..bd4819a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docs-dig-net", - "version": "0.16.0", + "version": "0.16.1", "private": true, "scripts": { "docusaurus": "docusaurus",