@takosjp/yurucommu-core 4.1.2 → 4.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/backend/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
wrapRuntimeBindings,
|
|
10
10
|
wrapRuntimeMessageBatch,
|
|
11
11
|
type PortableWorkerBindings,
|
|
12
|
-
type RuntimeLane,
|
|
13
12
|
} from "./runtime/lane.ts";
|
|
14
13
|
import {
|
|
15
14
|
configuredAppUrl,
|
|
@@ -939,20 +938,28 @@ function mountStaticFallback(app: YurucommuApp): void {
|
|
|
939
938
|
* a readiness probe that reported `APP_URL` missing on a Worker whose origin
|
|
940
939
|
* only its own traffic can reveal would never go ready.
|
|
941
940
|
*
|
|
942
|
-
* It runs on the
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
941
|
+
* It runs on EVERY lane, because the lane names the SHAPE OF THE BINDINGS and
|
|
942
|
+
* not who chose the endpoint. A Takoform-hosted Worker on the production
|
|
943
|
+
* Takoserver receives raw Cloudflare bindings — the `cloudflare` lane — and its
|
|
944
|
+
* origin is still allocated by a `WorkerEndpoint` after the `WorkerVersion`
|
|
945
|
+
* that would have carried `APP_URL` was sealed, and the Takoform module passes
|
|
946
|
+
* no `APP_URL` either. Gating the inference on the lane left exactly that
|
|
947
|
+
* install unable to ever name itself, and so never ready.
|
|
948
|
+
*
|
|
949
|
+
* What makes the request URL trustworthy is a property of the runtime rather
|
|
950
|
+
* than of the binding shape: the origin on the request is the origin the
|
|
951
|
+
* request actually arrived on, and no forwarded header is ever consulted (see
|
|
952
|
+
* runtime/public-origin.ts). The remaining risk on a Worker deployed straight
|
|
953
|
+
* to Cloudflare — it also answers on workers.dev and on every custom domain and
|
|
954
|
+
* route pattern its account holds, so the first hostname to arrive would name
|
|
955
|
+
* the instance for good — is answered the same way it always was: an operator
|
|
956
|
+
* who owns more than one of those hostnames sets `APP_URL`, which always wins.
|
|
950
957
|
*
|
|
951
958
|
* It never fails a request. When no origin can be established — the request is
|
|
952
|
-
* plain http, KV is unbound, an operator hand-wrote the pin
|
|
953
|
-
* stays unset, which `/readyz` already reports as a hard
|
|
954
|
-
* Turning that into a 500 would take the readiness probe down
|
|
955
|
-
* replace a precise answer with a generic one.
|
|
959
|
+
* plain http on a routable host, KV is unbound, an operator hand-wrote the pin
|
|
960
|
+
* — `APP_URL` simply stays unset, which `/readyz` already reports as a hard
|
|
961
|
+
* missing binding. Turning that into a 500 would take the readiness probe down
|
|
962
|
+
* with it and replace a precise answer with a generic one.
|
|
956
963
|
*/
|
|
957
964
|
function publicOriginMiddleware() {
|
|
958
965
|
let warned = false;
|
|
@@ -961,16 +968,6 @@ function publicOriginMiddleware() {
|
|
|
961
968
|
next: Next,
|
|
962
969
|
) => {
|
|
963
970
|
if (configuredAppUrl(c.env) !== null) return next();
|
|
964
|
-
// An unrecognised lane declaration is refused at the binding boundary by
|
|
965
|
-
// wrapRuntimeBindings. Reaching here with one means the app was composed
|
|
966
|
-
// directly, and the safe reading of "not a lane I know" is "do not infer".
|
|
967
|
-
let lane: RuntimeLane;
|
|
968
|
-
try {
|
|
969
|
-
lane = resolveRuntimeLane(c.env.YURUCOMMU_RUNTIME_LANE);
|
|
970
|
-
} catch {
|
|
971
|
-
return next();
|
|
972
|
-
}
|
|
973
|
-
if (lane !== "portable") return next();
|
|
974
971
|
try {
|
|
975
972
|
const origin = await establishRequestPublicOrigin(c.env, c.req.raw);
|
|
976
973
|
c.env = { ...c.env, APP_URL: origin };
|
|
@@ -8,15 +8,20 @@
|
|
|
8
8
|
* are all `${APP_URL}/…`, and a wrong one is not a broken page — it is a
|
|
9
9
|
* permanent, federated wrong answer that remote servers have already cached.
|
|
10
10
|
*
|
|
11
|
-
* `APP_URL` is a plain variable, and on a
|
|
12
|
-
* A Takoform `WorkerEndpoint` allocates the Worker's public
|
|
13
|
-
* `WorkerVersion` that would have carried the variable is
|
|
14
|
-
* the deployer does not know the value at apply time and
|
|
15
|
-
* apply that could inject it. The origin exists, but only
|
|
16
|
-
* and the only place it is ever spoken is on the requests
|
|
11
|
+
* `APP_URL` is a plain variable, and on a Host-assigned endpoint it cannot
|
|
12
|
+
* always be one. A Takoform `WorkerEndpoint` allocates the Worker's public
|
|
13
|
+
* origin AFTER the `WorkerVersion` that would have carried the variable is
|
|
14
|
+
* already immutable, so the deployer does not know the value at apply time and
|
|
15
|
+
* there is no second apply that could inject it. The origin exists, but only
|
|
16
|
+
* the Host knows it, and the only place it is ever spoken is on the requests
|
|
17
|
+
* the Host routes here.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* This has nothing to do with the runtime lane. The lane names the SHAPE OF THE
|
|
20
|
+
* BINDINGS; a Takoform-hosted Worker on the production Takoserver runs on raw
|
|
21
|
+
* Cloudflare bindings — the `cloudflare` lane — and is in exactly the same
|
|
22
|
+
* position, because the Takoform module passes no `APP_URL` there either. So on
|
|
23
|
+
* EVERY lane an unset `APP_URL` is answered by OBSERVING one request and
|
|
24
|
+
* PINNING what it observed:
|
|
20
25
|
*
|
|
21
26
|
* 1. `APP_URL` is authoritative whenever it is set. It is used exactly as the
|
|
22
27
|
* operator wrote it and is never validated, cached, or persisted here —
|
|
@@ -32,27 +37,38 @@
|
|
|
32
37
|
*
|
|
33
38
|
* WHAT IS TRUSTED. The request URL as the runtime delivers it, and only that.
|
|
34
39
|
* Not `X-Forwarded-Host`, not `X-Forwarded-Proto`, not `Host` read out of the
|
|
35
|
-
* headers — nothing a client can write.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* the
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* headers — nothing a client can write. That URL is the endpoint the request
|
|
41
|
+
* genuinely arrived on, under every host this bundle runs on. Cloudflare
|
|
42
|
+
* Workers build `request.url` from the connection the edge terminated. Both
|
|
43
|
+
* wrapper hosts route by hostname and hand over the request they received on
|
|
44
|
+
* the Worker's own public endpoint: Takoserver's managed Workers-for-Platforms
|
|
45
|
+
* gateway looks up a host route for `new URL(request.url).hostname` and
|
|
46
|
+
* dispatches the SAME `Request` object, and the self-host workerd router picks
|
|
47
|
+
* a service from a table keyed by hostname and forwards unchanged. A hostname
|
|
48
|
+
* nobody published for this Worker is a 404 before any of this code runs, so
|
|
49
|
+
* the origin on the request is one the Host assigned — which is exactly the
|
|
50
|
+
* value that could not be delivered as a var.
|
|
43
51
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* means
|
|
47
|
-
*
|
|
48
|
-
* is
|
|
52
|
+
* WHAT THIS DOES NOT DECIDE. A Worker published straight to Cloudflare by an
|
|
53
|
+
* operator who holds several hostnames answers on all of them, and first writer
|
|
54
|
+
* wins means the first one to arrive names the instance. That operator knows
|
|
55
|
+
* their hostnames and sets `APP_URL`, which always wins and is never pinned.
|
|
56
|
+
* Inference is the answer for the deployment that CANNOT be told its origin,
|
|
57
|
+
* not a preference over being told.
|
|
49
58
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* an
|
|
54
|
-
*
|
|
55
|
-
*
|
|
59
|
+
* WHY HTTPS. A public fediverse origin is https; Cloudflare terminates TLS in
|
|
60
|
+
* front of a Worker on a public hostname, and Takoserver's own `WorkerEndpoint`
|
|
61
|
+
* can only ever assign an https origin. Requiring it here means an http request
|
|
62
|
+
* cannot pin an origin that would then sign deliveries and mint actor ids.
|
|
63
|
+
* Loopback http is the one exception, because `localhost` is not routable and
|
|
64
|
+
* is the origin a developer actually serves on — `wrangler dev` included.
|
|
65
|
+
*
|
|
66
|
+
* A host that terminates TLS in FRONT of the runtime and speaks plain http to
|
|
67
|
+
* it therefore establishes nothing: `request.url` is `http://…` on a routable
|
|
68
|
+
* name and the derivation refuses. That deployment must set `APP_URL`, which it
|
|
69
|
+
* can, because an operator who terminates TLS chose the hostname themselves.
|
|
70
|
+
* Refusing is the point — the alternative is trusting a forwarded-proto header
|
|
71
|
+
* that the same proxy may or may not be the only writer of.
|
|
56
72
|
*/
|
|
57
73
|
|
|
58
74
|
import type { Env, EnvVars } from "../types.ts";
|