Hold 0069's destination set and its redirect rule as values (#69) - #287
Merged
Conversation
0069 decides that the set of destinations is exactly the origins of the servers the operator configured, that a redirect is followed only where it stays inside the origin the request was sent to, and that a name is resolved only for a host in the set. None of the three was anywhere in the tree: every use of Origin outside the module defining it was 0027's connection accounting, which counts requests against an origin rather than deciding whether one may be reached at all. src/server/destinations.rs holds the set, the comparison and the redirect rule. A set nobody configured admits nobody, which is 0068's sentence and what makes the check in #70 unambiguous. The comparison is over the whole origin, so a scheme downgrade and a second port on one host are two origins rather than one host. A redirect is compared against the origin the request went to and never against the whole set, so one configured server cannot move a request onto another one: 0101 places that decision with the operator, and a server asking is not the operator answering. The refusal is built at 0037's mapping point and carries ReadingSite::CrossOriginRedirectRefused, which is the value that keeps 0004's reversal measurement three populations rather than one count. The failure this prevents is the one 0069 was written before the code to stop: following a redirect anywhere is one line of configuration on an HTTP client, it is invisible in every test against a fake server that does not redirect, and the first time it matters is an operator whose server redirects artwork to a content network, at which point an address that frequently says where somebody lives has been going to a third party for as long as that deployment existed. AdmittedOrigin is produced by the comparison and by nothing else, so a later connect written against Origin is one that skipped it. Nothing consumes one today, because nothing here connects, resolves or requests. What #69 still needs is its fourth condition, which is the check in #70, and that check does not exist. #70's own last reading says what it waits on is the comparison being written rather than an issue; this is that comparison. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
src/server/ is an area in .github/coverage/pinned-surface, and the rule that
makes that register hold is that every tracked .rs file under an area is on the
surface and the run refuses one that is not listed. The module the previous
commit added was not, and the check said so rather than measuring it:
src/server/destinations.rs is on the pinned surface and is not listed in
.github/coverage/pinned-surface.
The row carries the reason on the same line as the path, which is what that
register asks for: what a defect there does is send an address and a device
identity to a host the operator never chose, or admit a host on a core nothing
has been configured on, where 0068 says the set is empty.
Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The issue this belongs to
Refs #69. It reaches part of that issue and its fourth condition is not met, so
no closing keyword is written here on purpose: the last two landings on this
board wrote "does not close #N" and GitHub read the keyword out of the sentence
with the negation discarded, on #107 and again on #29.
What changed
docs/decisions/0069-every-host-the-core-may-contact.mddecides three things andnone of them was anywhere in
src/. The set of destinations is exactly theorigins of the servers the operator configured. A redirect is followed only where
it stays inside the origin the request was sent to. A name is resolved only for a
host in the set, because a lookup is itself a request carrying the name.
src/server/destinations.rsholds all three as values.Destinationsis theregister, empty until somebody configures a server.
Destinations::admitcompares a whole origin against it and hands back an
AdmittedOrigin, which hasno other constructor.
Destinations::followdecides a redirect against theorigin the request went to.
WhatARedirectDoes::Refusedcarries the failure,built at 0037's mapping point rather than by a caller.
What was there before was the origin type and nothing that used it for this.
Every use of
Originoutside the module defining it is 0027's connectionaccounting, which counts requests against an origin rather than deciding whether
one may be reached:
What failure it prevents
The one 0069 was written before the code in order to stop, and it has not
happened here because there is no transport yet. Following a redirect anywhere is
the default in every HTTP client anybody would reach for, it is one line of
configuration, it is invisible in every test against a fake server that does not
redirect, and the first time it matters is an operator whose server redirects
artwork to a content network. At that point the core has been sending an address
and a user agent to a host the operator never chose for as long as that
deployment has existed, and on a self-hosted server the address frequently says
where the person lives.
The second is the resolution order. Checking the host after resolving it reads as
equivalent and is not, and the difference is visible only to somebody watching the
network rather than reading the code.
AdmittedOriginis where that order iswritten down: the host a resolver may be given comes off a value the comparison
produced.
What I decided that 0069 left open
A redirect is compared against the origin the request went to and never against
the whole set. 0069 follows a redirect only where it stays inside the origin
that was already in the set, and refuses one going anywhere else. Read exactly,
that refuses a configured server redirecting to a SECOND configured server. Read
conveniently, it admits it. I took the exact reading, because what the convenient
one admits is one server deciding that another answers for it, and
docs/decisions/0101-what-the-core-trusts.mdplaces that decision with theoperator: the person is trusted for which servers the core may talk to, and a
server is not trusted to move a request onto one of them.
The offset a refused redirect reports is the start of the location. 0004 fixes
the payload as the site, what was expected, and an offset, and forbids the bytes
there. A refused redirect consumed none of what it was handed, so the offset is
the start rather than a position inside something partly parsed. It is a named
constant carrying that reason rather than a bare zero.
Evidence
Read at the commit being pushed.
The gate legs that run without a network on this machine, each printing its own
verdict line:
What a guard here refuses, and the proof it bites
Six deliberate violations, each a one-change neighbour of what landed, each run
with
cargo test --locked --lib server::destinations. The green run is the oneunder Evidence above: 14 passed, 0 failed.
Comparing hosts rather than whole origins, which is the alternative 0069
prices by name.
.find(|held| *held == origin)became.find(|held| held.host() == origin.host()):Following a redirect to anything in the set, which is the convenient reading
of 0069's sentence. An
if let Some(admitted) = self.admit(location)arm was putin front of the comparison:
The redirect rule comparing hosts.
location == sent_to.origin()becamelocation.host() == sent_to.origin().host():Forgetting one server emptying the set, which is the shortest implementation
of removal.
held.retain(|kept| kept != origin)becameheld.clear():A second sign-in against one server adding a second row. The
containsarmwas deleted:
An unconfigured core reading as unrestricted rather than closed, which is the
mistake 0068 and #70 are about. An early
if self.rows() == 0arm returning theorigin was added:
What this does not cover
It refuses nothing that is happening. The refusal 0069 wants is a request not
being sent, and nothing in this crate sends one. What is here answers correctly
about an origin and produces the failure value a caller would hand back. Whether
any caller asks is #27 for the transport and #70 for the test.
Nothing consumes an
AdmittedOrigin. The property that a connect writtenagainst
Originis one that skipped the comparison is available rather than held:it starts holding on the day something connects.
Originstill hands its host toanybody who has one, and this change does not narrow that, because that parse is
0028's rather than 0069's.
0069 says the refused location is named in the payload, and the landed failure
type cannot carry it. This is a disagreement between two records that I met by
building and did not resolve:
The payload carries an offset and forbids the bytes at it, and a
Locationheaderis part of the answer, so the location cannot be named there at all. A client is
told that a cross-origin redirect was refused and is not told where to. Nothing
here changes either record, and no issue is opened for it: it is written in this
body and named on #69.
No
Scope:line exists on #69, so the hygiene check prints that the pathcomparison was not made rather than making it.
The
targetsleg did not run here. It compiles the library for 0113's seventriples and this machine has no cross-compilation set up for them; the gate is
where that verdict comes from.
The
thread-detectorleg did not run here. It uses a nightly compiler thismachine does not carry.
Nothing is measured. No number about what this comparison costs is in this
body, and #65 is where a measured one would come from.
The empty set is proven against an empty register and not against a running
core. There is no core to start, so nothing shows that a core comes up with the
set empty. What is shown is that the only constructor produces an empty one and
that the only way a row arrives is a caller supplying an origin.
Who has read it
Nobody other than me. There was no second reader available for it, and the
evidence above stands in place of one.