The Sender Is the Posting Hub

Some hub guards decide by the sender of a delivery. The clearest one is the stamped-field guard: a node's hub admits a write to a stamped field only from itself, and everything arriving from another address is a client write. Such a guard is only as good as the sender it reads.

PostOptions is a record, so posting code can write o => o.WithTarget(x) with { Sender = y }. Until #6553 the delivery left with whatever address the caller wrote: code running in the portal process — a compiled module, a NodeType or Code node the mesh compiled — could name a node's own address as the sender of a patch and pass that node's owner-only guard. No external client could do it (the wire ingresses stamp every delivery they accept, see Participant Ingress), but in-process code could.

The rule

hub.Post stamps the sender itself: it is the address of the hub that posts. A sender the caller wrote that differs is replaced by the posting hub's address, and the hub logs one [ForeignSender] warning per message type and call site, naming the claimed address and the calling code's stack. The key holds only stable data — the claimed address is caller-controlled and may be fresh on every post — and the set is capped per hub, so a misbehaving caller cannot grow it or flood the log. The call site is read off the stack, skipping the hub's own Post/Observe plumbing and Rx, so it names the code that wrote the sender. The post is not refused — it goes out as the hub that actually sent it, so the reply comes back to that hub and a sender-keyed guard judges the real poster.

There is one sanctioned exception, and only the messaging assembly can mark it (PostOptions.CarriedByParent(), internal): a parent carrying a post its hosted hub can no longer send itself — a correlated reply or a release (IReleasesRemoteState) posted while that hub is tearing down. The carried delivery keeps the hosted hub's address (host-qualified on the way up, the same qualification ordinary upward routing applies), because that is who posted it.

Everything else that legitimately moves a delivery under an address other than the current hub's is routing, not posting: hierarchical routing re-qualifies the sender with its host on the way up, the routing services and grains forward a delivery whose sender was stamped where it was posted, and ResponseFor retargets a reply at the request's sender without touching the reply's own sender. None of these go through a caller-written Sender.

Measured

Not established