# 0060 — Web serving gets its own access surface (`WEB`); `XFER` is retired, not repurposed

Status: accepted (2026-09-06 WEBSERVE grill round 2, releases#272 / #249 / #246)

## Context

#249 proposed gating cross-node web serving on the existing `XFER` access surface, renamed
`HTTP`, default-allow like `DISCOVER`. Measured before ruling (main `8a21a3b0`): the transfer
INITIATORS (`fetch_file`, `push_file`) have zero production callers — no verb opens the Xfer
stream, so the operator's premise that no user- or agent-facing surface uses it holds on that
side. The SERVE side is live: the daemon gates the inbound Xfer stream on `XFER`, knock codes
can be minted for it, rules can name it; zero grant rows named it on the measuring node. The
design record already says how new facets get their surface — CONTEXT.md's access-surface
entry ratifies that *webservice facets mint their ids when the capability is built* — and names
`XFER` as the next surface expected to grow a sender stamp.

## Decision

- **Mint `WEB`** — one row in the open surface vocabulary, no schema change (the `FORK`
  precedent). It gates every served resource reached across the subnet; the owning node runs
  the check under the handshake-proven origin. **Default-allow within the subnet**: content in
  the serving registry is there by a deliberate act (ADR-0057), so the deny lever is for
  lockdown, not the default.
- **Retire `XFER`**, do not rename it. The pull-model attachment (ADR-0058) supersedes the
  transfer machinery, so the Xfer stream family, its serve gate, its tests and the surface row
  leave the tree together, as a close rider on #246. A stored rule that names a retired surface
  is REPORTED at load (`ACCESS_SURFACE_RETIRED`), never silently dropped.

## Alternatives rejected

- **Repurpose `XFER` → `HTTP`.** Same end state, but an existing id changes meaning under any
  rule that names it, the attributability plan keyed on `XFER` has to be re-ruled, and the
  superseded transfer code stays alive under a new name. Rejected: nothing is cheaper about it
  except the row count, which is one either way.
- **Deny-by-default for `WEB` on closed subnets.** Rejected with #249's reasoning: exposure is
  already explicit at registration; a second gate at every read would make the registry a list
  of things nobody can fetch.

## Consequences

- Access vocabulary: `WEB` joins the v1 set; `XFER` is documented as retired from the #246
  close onward, and the "expected next to grow a sender stamp" note moves to `WEB`.
- Pre-existing `XFER` grants anywhere in the fleet surface as a load-time report, which is the
  census that tells us whether anyone ever used it.
- **The progress record is NOT the stream family, and the retire set stops at the family**
  (doyle, 2026-09-07, off the rider's own census — recorded here so the next census does not
  re-retire it). `spt_store::xfer::{XferProgress, transfers_dir, write_progress_at}` are the
  SHELL CHANNEL's durable progress record: their consumers are `shellchan.rs` (file ops kept
  progress-queryable) and the CLI, neither of which has anything to do with the WAN transport.
  They keep their names — a rename would be churn outside this rider. What leaves is the Xfer
  stream family, its wire record, its serve gate and its surface row. "Its tests" means tests
  of the family and the gate; a test that pins the progress record stays with the record.
- **`REQ-REACH-1`'s title is amended, not retired**: it read *off-node remote-drive detection
  + file transfer*, and only the second half goes. Its `int` stage survives on the remote-drive
  cell (`tests/dispatch.rs`), which never depended on the transfer family; the transfer-specific
  `int` tags leave with the family they cover.
