Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ edition = "2021"
# the ROOT manifest (`[workspace.package].version`), so it MUST be set here for a
# release to fire (§3.6). The library crates (dig-node-core/dig-runtime/dig-wallet)
# keep their own independent versions — only the released binary tracks the workspace version.
version = "0.75.5"
version = "0.75.6"

# Release hardening, matching digstore: keep integer-overflow checks ON in release.
# The node parses untrusted serialized input and does offset/length arithmetic over
Expand Down
31 changes: 22 additions & 9 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -3999,19 +3999,32 @@ durable holder side effect is a remotely-triggerable amplification.

Landing therefore gates on BOTH axes:

1. **The `/s/` HTTP surface derives a request-provenance label from the `Sec-Fetch-Site` request
header**, orthogonal to the §21.7 read-origin label. ONLY an explicit, case-insensitive `cross-site`
value is `CrossSite`; `same-origin`, `same-site`, `none`, an unknown value, AND an ABSENT header are
all `FirstParty`. Absence MUST map to `FirstParty` — non-browser clients (the CLI, the SDK) send no
`Sec-Fetch-*` header, and treating absence as cross-site would silently stop every CLI/SDK read from
landing.
1. **Every browser-reachable read surface derives a request-provenance label from the `Sec-Fetch-Site`
request header**, orthogonal to the §21.7 read-origin label. This covers BOTH the `/s/` plaintext
serve surface AND the `POST /` JSON-RPC read methods (`dig.getContent`, `dig.fetchRange`), whose
miss-path landing legs (the implicit warm/backfill/reshare fired when the resource is not held
locally) would otherwise let a SAME-ORIGIN capsule page `POST dig.getContent` and drive landing —
the loopback address labels it `Local`, so §21.7 alone permits it. ONLY an explicit, case-insensitive
`cross-site` value is `CrossSite`; `same-origin`, `same-site`, `none`, an unknown value, AND an ABSENT
header are all `FirstParty`. Absence MUST map to `FirstParty` — non-browser clients (the CLI, the SDK)
send no `Sec-Fetch-*` header, and treating absence as cross-site would silently stop every CLI/SDK
read from landing.
2. **A read lands only when it is BOTH `Local` (§21.7) AND `FirstParty`.** A `CrossSite` request collapses
its landing origin to `Peer`: the bytes are served identically, but no warm, reshare, promotion, or
announce fires. The READ MUST NEVER be blocked, throttled, or altered by provenance — only the side
effect is suppressed.
3. **The collapse is applied ONCE, at the serve seam**, and the collapsed origin flows to the landing
legs; the leaf gates (§21.7) are unchanged. This axis is HTTP-only (`serve_content_plaintext` has no
peer-wire callers); the peer tier remains gated by §21.7's read-origin alone.
3. **The collapse is applied ONCE per landing site via the shared `landing_origin(origin, provenance)`
fold**, and the collapsed `land_origin` flows to the landing legs; the leaf gates (§21.7) are
unchanged. On the `/s/` path the fold is applied at the serve seam; on the `POST /` JSON-RPC path it
is applied at the top of each read handler and the collapsed origin replaces the raw origin at every
landing site (`content_miss_envelope`/`range_miss_envelope` → the reshare chain, AND
`maybe_backfill_capsule`) — the raw read-origin is used everywhere else. Each transport threads the
provenance EXPLICITLY through `handle_rpc`/`dispatch` (a required argument, never inferred): the
browser-facing HTTP POST classifies the header, every trusted/non-browser caller (the control
surface, the in-process FFI, the peer-RPC server) passes `FirstParty`. This axis applies only to
browser-reachable HTTP surfaces; the peer wire remains gated by §21.7's read-origin alone
(`landing_origin(Peer, FirstParty) == Peer`, so a peer read still never lands). It complements §21.9's
token-gate on the EXPLICIT `cache.fetchAndCache` landing method.

Honest residuals: a browser predating `Sec-Fetch-Site` (all current major browsers send it) presents no
header and is treated as first-party; and a same-origin store-to-store request within a shared serving
Expand Down
17 changes: 17 additions & 0 deletions crates/dig-node-core/src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,23 @@ pub fn from_sec_fetch_site(hdr: Option<&str>) -> RequestProvenance {
}
}

/// Collapse the two landing axes (#1654/#1956) into the single [`ReadOrigin`] the miss-path landing
/// legs (`maybe_backfill_capsule`, the miss-envelope→`fetch_resource`→`spawn_capsule_reshare` chain)
/// gate on. A FIRST-PARTY request keeps its transport origin — a loopback operator read (or a CLI/SDK
/// read with no `Sec-Fetch-*` header) still lands. A CROSS-SITE request — one the browser reports was
/// driven by another origin's page — folds to [`Peer`], so it serves the bytes but effects no durable
/// holder side effect (no cache-write, no DHT announce, no reshare). PURE: the ONE place the two axes
/// meet, shared by both the `/s/` plaintext serve path (#1654) and the JSON-RPC dispatch landing legs
/// (#1956), so the two surfaces can never drift.
///
/// [`Peer`]: ReadOrigin::Peer
pub(crate) fn landing_origin(origin: ReadOrigin, provenance: RequestProvenance) -> ReadOrigin {
match provenance {
RequestProvenance::FirstParty => origin,
RequestProvenance::CrossSite => ReadOrigin::Peer,
}
}

// -- The digstore-bound proof verifier -------------------------------------------------------------

/// The REAL [`ProofVerifier`] for dig-download's whole-resource check: decodes the digstore
Expand Down
Loading
Loading