@volter/world-core 3.0.20 → 3.0.22
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/dist/generated/pack-facts.json +66 -1
- package/dist/inject.cjs +77 -1
- package/dist/src/derived.d.ts +9 -3
- package/generated/pack-facts.json +66 -1
- package/inject.cjs +77 -1
- package/package.json +1 -1
- package/src/derived.ts +9 -3
|
@@ -1398,6 +1398,71 @@
|
|
|
1398
1398
|
},
|
|
1399
1399
|
"serveExport": "createLinearTwinServer"
|
|
1400
1400
|
},
|
|
1401
|
+
"linkedin": {
|
|
1402
|
+
"adoption": {
|
|
1403
|
+
"sdks": [
|
|
1404
|
+
"linkedin-api-client"
|
|
1405
|
+
],
|
|
1406
|
+
"pypi": [
|
|
1407
|
+
"linkedin-api-client"
|
|
1408
|
+
],
|
|
1409
|
+
"envStems": [
|
|
1410
|
+
"LINKEDIN"
|
|
1411
|
+
]
|
|
1412
|
+
},
|
|
1413
|
+
"hosts": [
|
|
1414
|
+
{
|
|
1415
|
+
"host": "api.linkedin.com",
|
|
1416
|
+
"pathPattern": "^/(rest|v2)/|^/_twin/"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"host": "www.linkedin.com",
|
|
1420
|
+
"pathPattern": "^/$|^/(dms-uploads|dms-mpf-uploads|feed|company|login|uas/login|m/logout|signup/cold-join|signup/api/cors/createAccount|checkpoint/lg/login-submit)(/|$)|^/_twin/"
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
"host": "linkedin.com",
|
|
1424
|
+
"pathPattern": "^/$|^/(dms-uploads|dms-mpf-uploads|feed|company|login|uas/login|m/logout|signup/cold-join|signup/api/cors/createAccount|checkpoint/lg/login-submit)(/|$)|^/_twin/"
|
|
1425
|
+
},
|
|
1426
|
+
{
|
|
1427
|
+
"host": "media.licdn.com",
|
|
1428
|
+
"pathPattern": "^/dms/image/"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"host": "dms.licdn.com",
|
|
1432
|
+
"pathPattern": "^/playlist/"
|
|
1433
|
+
}
|
|
1434
|
+
],
|
|
1435
|
+
"archetype": "crud",
|
|
1436
|
+
"protocol": {
|
|
1437
|
+
"declared": "3",
|
|
1438
|
+
"major": 3,
|
|
1439
|
+
"standing": "current"
|
|
1440
|
+
},
|
|
1441
|
+
"transport": "rest",
|
|
1442
|
+
"resources": [
|
|
1443
|
+
"post",
|
|
1444
|
+
"image",
|
|
1445
|
+
"video",
|
|
1446
|
+
"organization",
|
|
1447
|
+
"member",
|
|
1448
|
+
"organization_acl",
|
|
1449
|
+
"developer_app",
|
|
1450
|
+
"_access_token",
|
|
1451
|
+
"_usage",
|
|
1452
|
+
"_upload",
|
|
1453
|
+
"_person",
|
|
1454
|
+
"_web_session"
|
|
1455
|
+
],
|
|
1456
|
+
"endpointEnvNone": "LinkedIn's clients (linkedin-api-client, plain fetch) read no base-URL variable; the World claims api.linkedin.com and www.linkedin.com",
|
|
1457
|
+
"credentialDoor": {
|
|
1458
|
+
"path": "/_twin/app-credentials",
|
|
1459
|
+
"body": {},
|
|
1460
|
+
"fill": {
|
|
1461
|
+
"LINKEDIN_ACCESS_TOKEN": "access_token"
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
"serveExport": "createLinkedinTwinServer"
|
|
1465
|
+
},
|
|
1401
1466
|
"livekit": {
|
|
1402
1467
|
"serverBacking": {
|
|
1403
1468
|
"command": "livekit-server"
|
|
@@ -1960,7 +2025,7 @@
|
|
|
1960
2025
|
"credentialDoor": {
|
|
1961
2026
|
"path": "/_twin/app-credentials",
|
|
1962
2027
|
"body": {
|
|
1963
|
-
"username": "
|
|
2028
|
+
"username": "FamouslyDefault"
|
|
1964
2029
|
},
|
|
1965
2030
|
"fill": {
|
|
1966
2031
|
"REDDIT_ACCESS_TOKEN": "access_token"
|
package/dist/inject.cjs
CHANGED
|
@@ -21,7 +21,13 @@
|
|
|
21
21
|
// (stripe-node → https; @octokit → fetch; @slack/web-api & jira.js → axios →
|
|
22
22
|
// http/https; @linear/sdk → fetch), so no per-SDK shim is needed.
|
|
23
23
|
//
|
|
24
|
-
//
|
|
24
|
+
// Attached to a World (VOLTER_WORLD), a request a bundled undici (wrangler's) sends to the
|
|
25
|
+
// World's own paths through undici's shared global dispatcher carries the World's key too:
|
|
26
|
+
// Object.defineProperty is watched for that global, and the dispatcher set there is stood
|
|
27
|
+
// in for by a view whose dispatch keys a hop whose origin and path are the World's
|
|
28
|
+
// (keyedView, below), sent with maxRedirections 0 so no follower below it takes the key on.
|
|
29
|
+
//
|
|
30
|
+
// A client can still open its own sockets (npm `undici`'s own Agent, which
|
|
25
31
|
// @turbopuffer/turbopuffer uses under Node, honours neither patch nor HTTPS_PROXY).
|
|
26
32
|
// `net.connect`/`tls.connect` are the seam every Node client ends at, so they carry
|
|
27
33
|
// the backstop: a connect to a twinned vendor host went around the rewrite and is
|
|
@@ -435,6 +441,74 @@ function withWorldKey(args) {
|
|
|
435
441
|
return out;
|
|
436
442
|
}
|
|
437
443
|
|
|
444
|
+
// A client that bundles its own undici (wrangler) calls neither the global `fetch` nor http(s), so its requests to the
|
|
445
|
+
// World's own paths would arrive without the key. Every undici copy, Node's own included, keeps its dispatcher on one
|
|
446
|
+
// shared global (`Symbol.for('undici.globalDispatcher.<n>')`), set with Object.defineProperty when that copy loads. A
|
|
447
|
+
// dispatcher defined there is stood in for by a view of it whose `dispatch` adds the key to one hop, only when that
|
|
448
|
+
// hop's origin is the World's and its path one of the World's own, compared as strings (a path is never resolved as a
|
|
449
|
+
// URL, so `//other-host/…` names no other origin); the dispatcher itself is never changed, and restore() puts it back.
|
|
450
|
+
const UNDICI_DISPATCHERS = [Symbol.for('undici.globalDispatcher.1'), Symbol.for('undici.globalDispatcher.2')];
|
|
451
|
+
const KEYED_VIEWS = new WeakMap(); // view -> the dispatcher it stands in for
|
|
452
|
+
function keyedUndiciHeaders(headers, key) {
|
|
453
|
+
if (headers == null) return { 'x-twins-key': key };
|
|
454
|
+
if (Array.isArray(headers)) {
|
|
455
|
+
const flat = headers.length === 0 || !Array.isArray(headers[0]);
|
|
456
|
+
const names = flat ? headers.filter((_, i) => i % 2 === 0) : headers.map((h) => h[0]);
|
|
457
|
+
if (names.some((n) => String(n).toLowerCase() === 'x-twins-key')) return headers;
|
|
458
|
+
return flat ? [...headers, 'x-twins-key', key] : [...headers, ['x-twins-key', key]];
|
|
459
|
+
}
|
|
460
|
+
const entries = typeof headers[Symbol.iterator] === 'function' ? [...headers] : Object.entries(headers);
|
|
461
|
+
if (entries.some(([n]) => String(n).toLowerCase() === 'x-twins-key')) return headers;
|
|
462
|
+
return Object.assign(Object.fromEntries(entries), { 'x-twins-key': key });
|
|
463
|
+
}
|
|
464
|
+
/** A dispatch hop is the World's: its origin is the World's own and its path, as written, under the World's paths. */
|
|
465
|
+
function hopToWorld(opts) {
|
|
466
|
+
const base = worldBase();
|
|
467
|
+
if (!base || !base.path || !opts || opts.origin == null) return false;
|
|
468
|
+
let origin;
|
|
469
|
+
try { origin = new URL(String(opts.origin)).origin; } catch { return false; }
|
|
470
|
+
const at = String(opts.path == null ? '/' : opts.path);
|
|
471
|
+
return origin === base.origin && (at.startsWith(`${base.path}/`) || at.startsWith(`/-${base.path}/`));
|
|
472
|
+
}
|
|
473
|
+
function keyedView(dispatcher) {
|
|
474
|
+
if (!dispatcher || typeof dispatcher.dispatch !== 'function' || KEYED_VIEWS.has(dispatcher)) return dispatcher;
|
|
475
|
+
const view = new Proxy(dispatcher, {
|
|
476
|
+
get(target, name) {
|
|
477
|
+
if (name === 'dispatch') {
|
|
478
|
+
return function keyedDispatch(opts, handler) {
|
|
479
|
+
const key = ORIGINAL_DEFINE_PROPERTY ? twinsKey() : null;
|
|
480
|
+
// a hop the caller asked undici to follow is not keyed; a keyed hop is sent with maxRedirections 0, so no
|
|
481
|
+
// redirect follower below this view (a composed interceptor, a RetryAgent or proxy agent around one, undici
|
|
482
|
+
// 6's option or interceptors) carries its headers to the next origin: the redirect comes back to the caller
|
|
483
|
+
const keyed = key && !(opts && Number(opts.maxRedirections) > 0) && hopToWorld(opts);
|
|
484
|
+
return target.dispatch(keyed ? Object.assign({}, opts, { headers: keyedUndiciHeaders(opts.headers, key), maxRedirections: 0 }) : opts, handler);
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
const value = Reflect.get(target, name, target);
|
|
488
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
KEYED_VIEWS.set(view, dispatcher);
|
|
492
|
+
return view;
|
|
493
|
+
}
|
|
494
|
+
let ORIGINAL_DEFINE_PROPERTY = null;
|
|
495
|
+
function keyUndiciDispatches() {
|
|
496
|
+
if (ORIGINAL_DEFINE_PROPERTY || !worldBase() || Object.defineProperty.name === 'keyingDefineProperty') return;
|
|
497
|
+
const define = ORIGINAL_DEFINE_PROPERTY = Object.defineProperty;
|
|
498
|
+
Object.defineProperty = function keyingDefineProperty(target, name, descriptor) {
|
|
499
|
+
if (ORIGINAL_DEFINE_PROPERTY && target === globalThis && UNDICI_DISPATCHERS.includes(name) && descriptor && 'value' in descriptor) descriptor = Object.assign({}, descriptor, { value: keyedView(descriptor.value) });
|
|
500
|
+
return define(target, name, descriptor);
|
|
501
|
+
};
|
|
502
|
+
for (const name of UNDICI_DISPATCHERS) if (globalThis[name]) globalThis[name] = keyedView(globalThis[name]);
|
|
503
|
+
}
|
|
504
|
+
function unkeyUndiciDispatches() {
|
|
505
|
+
if (!ORIGINAL_DEFINE_PROPERTY) return;
|
|
506
|
+
// only what this put in place is put back: a wrapper installed over it since stays
|
|
507
|
+
if (Object.defineProperty.name === 'keyingDefineProperty') Object.defineProperty = ORIGINAL_DEFINE_PROPERTY;
|
|
508
|
+
ORIGINAL_DEFINE_PROPERTY = null;
|
|
509
|
+
for (const name of UNDICI_DISPATCHERS) if (KEYED_VIEWS.has(globalThis[name])) globalThis[name] = KEYED_VIEWS.get(globalThis[name]);
|
|
510
|
+
}
|
|
511
|
+
|
|
438
512
|
// S4 review F3: undici's default redirect-follow forwards CUSTOM headers across origins — a
|
|
439
513
|
// twin (or the World) answering 30x to an external URL would carry x-twins-key to a REAL host. A
|
|
440
514
|
// keyed fetch follows redirects itself: a hop that is a twin or the World re-enters the patched
|
|
@@ -979,6 +1053,7 @@ function install(mapOverride) {
|
|
|
979
1053
|
tls.connect = patchedConnect(ORIGINALS.tlsConnect, true);
|
|
980
1054
|
dns.lookup = patchedLookup(ORIGINALS.dnsLookup);
|
|
981
1055
|
dns.promises.lookup = patchedPromisesLookup(ORIGINALS.dnsPromisesLookup);
|
|
1056
|
+
keyUndiciDispatches();
|
|
982
1057
|
// gRPC (architecture, "Other wires": gRPC): an HTTP/2 session to a host a twin serves (grpc-js on google-gax: TLS to
|
|
983
1058
|
// webrisk.googleapis.com) connects to that twin's origin in plain text, where the kernel's HTTP/2 server answers it;
|
|
984
1059
|
// the client carries on unchanged. Any other authority is the real one's.
|
|
@@ -1139,6 +1214,7 @@ function restore() {
|
|
|
1139
1214
|
dns.lookup = ORIGINALS.dnsLookup;
|
|
1140
1215
|
dns.promises.lookup = ORIGINALS.dnsPromisesLookup;
|
|
1141
1216
|
http2.connect = ORIGINALS.http2Connect;
|
|
1217
|
+
unkeyUndiciDispatches();
|
|
1142
1218
|
installed = false;
|
|
1143
1219
|
MAP = {};
|
|
1144
1220
|
}
|
package/dist/src/derived.d.ts
CHANGED
|
@@ -126,9 +126,10 @@ export type Workspace = {
|
|
|
126
126
|
id: string;
|
|
127
127
|
path: string;
|
|
128
128
|
};
|
|
129
|
-
/** A
|
|
130
|
-
*
|
|
131
|
-
*
|
|
129
|
+
/** A page of the World's board (architecture, "The board"): a page there is to see at the vendor, a record's own (an
|
|
130
|
+
* account's profile, each of its posts, a site and each page it serves), as the vendor's pack lists them from its state
|
|
131
|
+
* (`semantics/board.ts`). Every field is a fact of the World's state: which of them a person looks at is the board's
|
|
132
|
+
* choice, never the pack's. `GET /twin/board` lists them. */
|
|
132
133
|
export type BoardFrame = {
|
|
133
134
|
/** stable within the vendor, whatever the World's ids: what a saved board names the frame by */
|
|
134
135
|
id: string;
|
|
@@ -149,6 +150,11 @@ export type BoardFrame = {
|
|
|
149
150
|
type: string;
|
|
150
151
|
id: string;
|
|
151
152
|
}>;
|
|
153
|
+
/** the id of the page it sits under at the vendor (a post under its author's profile, a site's page under its site):
|
|
154
|
+
* a board showing everything shows a page with no parent and opens the pages under it from there */
|
|
155
|
+
parent?: string;
|
|
156
|
+
/** the World's own: an account the World's applications or people act as, a page of one, a site the World serves */
|
|
157
|
+
ours?: boolean;
|
|
152
158
|
/** set by the kernel, never the pack: whether a built screen of the vendor's (any of its lanes') draws the url */
|
|
153
159
|
drawn?: boolean;
|
|
154
160
|
};
|
|
@@ -1398,6 +1398,71 @@
|
|
|
1398
1398
|
},
|
|
1399
1399
|
"serveExport": "createLinearTwinServer"
|
|
1400
1400
|
},
|
|
1401
|
+
"linkedin": {
|
|
1402
|
+
"adoption": {
|
|
1403
|
+
"sdks": [
|
|
1404
|
+
"linkedin-api-client"
|
|
1405
|
+
],
|
|
1406
|
+
"pypi": [
|
|
1407
|
+
"linkedin-api-client"
|
|
1408
|
+
],
|
|
1409
|
+
"envStems": [
|
|
1410
|
+
"LINKEDIN"
|
|
1411
|
+
]
|
|
1412
|
+
},
|
|
1413
|
+
"hosts": [
|
|
1414
|
+
{
|
|
1415
|
+
"host": "api.linkedin.com",
|
|
1416
|
+
"pathPattern": "^/(rest|v2)/|^/_twin/"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"host": "www.linkedin.com",
|
|
1420
|
+
"pathPattern": "^/$|^/(dms-uploads|dms-mpf-uploads|feed|company|login|uas/login|m/logout|signup/cold-join|signup/api/cors/createAccount|checkpoint/lg/login-submit)(/|$)|^/_twin/"
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
"host": "linkedin.com",
|
|
1424
|
+
"pathPattern": "^/$|^/(dms-uploads|dms-mpf-uploads|feed|company|login|uas/login|m/logout|signup/cold-join|signup/api/cors/createAccount|checkpoint/lg/login-submit)(/|$)|^/_twin/"
|
|
1425
|
+
},
|
|
1426
|
+
{
|
|
1427
|
+
"host": "media.licdn.com",
|
|
1428
|
+
"pathPattern": "^/dms/image/"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"host": "dms.licdn.com",
|
|
1432
|
+
"pathPattern": "^/playlist/"
|
|
1433
|
+
}
|
|
1434
|
+
],
|
|
1435
|
+
"archetype": "crud",
|
|
1436
|
+
"protocol": {
|
|
1437
|
+
"declared": "3",
|
|
1438
|
+
"major": 3,
|
|
1439
|
+
"standing": "current"
|
|
1440
|
+
},
|
|
1441
|
+
"transport": "rest",
|
|
1442
|
+
"resources": [
|
|
1443
|
+
"post",
|
|
1444
|
+
"image",
|
|
1445
|
+
"video",
|
|
1446
|
+
"organization",
|
|
1447
|
+
"member",
|
|
1448
|
+
"organization_acl",
|
|
1449
|
+
"developer_app",
|
|
1450
|
+
"_access_token",
|
|
1451
|
+
"_usage",
|
|
1452
|
+
"_upload",
|
|
1453
|
+
"_person",
|
|
1454
|
+
"_web_session"
|
|
1455
|
+
],
|
|
1456
|
+
"endpointEnvNone": "LinkedIn's clients (linkedin-api-client, plain fetch) read no base-URL variable; the World claims api.linkedin.com and www.linkedin.com",
|
|
1457
|
+
"credentialDoor": {
|
|
1458
|
+
"path": "/_twin/app-credentials",
|
|
1459
|
+
"body": {},
|
|
1460
|
+
"fill": {
|
|
1461
|
+
"LINKEDIN_ACCESS_TOKEN": "access_token"
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
"serveExport": "createLinkedinTwinServer"
|
|
1465
|
+
},
|
|
1401
1466
|
"livekit": {
|
|
1402
1467
|
"serverBacking": {
|
|
1403
1468
|
"command": "livekit-server"
|
|
@@ -1960,7 +2025,7 @@
|
|
|
1960
2025
|
"credentialDoor": {
|
|
1961
2026
|
"path": "/_twin/app-credentials",
|
|
1962
2027
|
"body": {
|
|
1963
|
-
"username": "
|
|
2028
|
+
"username": "FamouslyDefault"
|
|
1964
2029
|
},
|
|
1965
2030
|
"fill": {
|
|
1966
2031
|
"REDDIT_ACCESS_TOKEN": "access_token"
|
package/inject.cjs
CHANGED
|
@@ -21,7 +21,13 @@
|
|
|
21
21
|
// (stripe-node → https; @octokit → fetch; @slack/web-api & jira.js → axios →
|
|
22
22
|
// http/https; @linear/sdk → fetch), so no per-SDK shim is needed.
|
|
23
23
|
//
|
|
24
|
-
//
|
|
24
|
+
// Attached to a World (VOLTER_WORLD), a request a bundled undici (wrangler's) sends to the
|
|
25
|
+
// World's own paths through undici's shared global dispatcher carries the World's key too:
|
|
26
|
+
// Object.defineProperty is watched for that global, and the dispatcher set there is stood
|
|
27
|
+
// in for by a view whose dispatch keys a hop whose origin and path are the World's
|
|
28
|
+
// (keyedView, below), sent with maxRedirections 0 so no follower below it takes the key on.
|
|
29
|
+
//
|
|
30
|
+
// A client can still open its own sockets (npm `undici`'s own Agent, which
|
|
25
31
|
// @turbopuffer/turbopuffer uses under Node, honours neither patch nor HTTPS_PROXY).
|
|
26
32
|
// `net.connect`/`tls.connect` are the seam every Node client ends at, so they carry
|
|
27
33
|
// the backstop: a connect to a twinned vendor host went around the rewrite and is
|
|
@@ -435,6 +441,74 @@ function withWorldKey(args) {
|
|
|
435
441
|
return out;
|
|
436
442
|
}
|
|
437
443
|
|
|
444
|
+
// A client that bundles its own undici (wrangler) calls neither the global `fetch` nor http(s), so its requests to the
|
|
445
|
+
// World's own paths would arrive without the key. Every undici copy, Node's own included, keeps its dispatcher on one
|
|
446
|
+
// shared global (`Symbol.for('undici.globalDispatcher.<n>')`), set with Object.defineProperty when that copy loads. A
|
|
447
|
+
// dispatcher defined there is stood in for by a view of it whose `dispatch` adds the key to one hop, only when that
|
|
448
|
+
// hop's origin is the World's and its path one of the World's own, compared as strings (a path is never resolved as a
|
|
449
|
+
// URL, so `//other-host/…` names no other origin); the dispatcher itself is never changed, and restore() puts it back.
|
|
450
|
+
const UNDICI_DISPATCHERS = [Symbol.for('undici.globalDispatcher.1'), Symbol.for('undici.globalDispatcher.2')];
|
|
451
|
+
const KEYED_VIEWS = new WeakMap(); // view -> the dispatcher it stands in for
|
|
452
|
+
function keyedUndiciHeaders(headers, key) {
|
|
453
|
+
if (headers == null) return { 'x-twins-key': key };
|
|
454
|
+
if (Array.isArray(headers)) {
|
|
455
|
+
const flat = headers.length === 0 || !Array.isArray(headers[0]);
|
|
456
|
+
const names = flat ? headers.filter((_, i) => i % 2 === 0) : headers.map((h) => h[0]);
|
|
457
|
+
if (names.some((n) => String(n).toLowerCase() === 'x-twins-key')) return headers;
|
|
458
|
+
return flat ? [...headers, 'x-twins-key', key] : [...headers, ['x-twins-key', key]];
|
|
459
|
+
}
|
|
460
|
+
const entries = typeof headers[Symbol.iterator] === 'function' ? [...headers] : Object.entries(headers);
|
|
461
|
+
if (entries.some(([n]) => String(n).toLowerCase() === 'x-twins-key')) return headers;
|
|
462
|
+
return Object.assign(Object.fromEntries(entries), { 'x-twins-key': key });
|
|
463
|
+
}
|
|
464
|
+
/** A dispatch hop is the World's: its origin is the World's own and its path, as written, under the World's paths. */
|
|
465
|
+
function hopToWorld(opts) {
|
|
466
|
+
const base = worldBase();
|
|
467
|
+
if (!base || !base.path || !opts || opts.origin == null) return false;
|
|
468
|
+
let origin;
|
|
469
|
+
try { origin = new URL(String(opts.origin)).origin; } catch { return false; }
|
|
470
|
+
const at = String(opts.path == null ? '/' : opts.path);
|
|
471
|
+
return origin === base.origin && (at.startsWith(`${base.path}/`) || at.startsWith(`/-${base.path}/`));
|
|
472
|
+
}
|
|
473
|
+
function keyedView(dispatcher) {
|
|
474
|
+
if (!dispatcher || typeof dispatcher.dispatch !== 'function' || KEYED_VIEWS.has(dispatcher)) return dispatcher;
|
|
475
|
+
const view = new Proxy(dispatcher, {
|
|
476
|
+
get(target, name) {
|
|
477
|
+
if (name === 'dispatch') {
|
|
478
|
+
return function keyedDispatch(opts, handler) {
|
|
479
|
+
const key = ORIGINAL_DEFINE_PROPERTY ? twinsKey() : null;
|
|
480
|
+
// a hop the caller asked undici to follow is not keyed; a keyed hop is sent with maxRedirections 0, so no
|
|
481
|
+
// redirect follower below this view (a composed interceptor, a RetryAgent or proxy agent around one, undici
|
|
482
|
+
// 6's option or interceptors) carries its headers to the next origin: the redirect comes back to the caller
|
|
483
|
+
const keyed = key && !(opts && Number(opts.maxRedirections) > 0) && hopToWorld(opts);
|
|
484
|
+
return target.dispatch(keyed ? Object.assign({}, opts, { headers: keyedUndiciHeaders(opts.headers, key), maxRedirections: 0 }) : opts, handler);
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
const value = Reflect.get(target, name, target);
|
|
488
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
KEYED_VIEWS.set(view, dispatcher);
|
|
492
|
+
return view;
|
|
493
|
+
}
|
|
494
|
+
let ORIGINAL_DEFINE_PROPERTY = null;
|
|
495
|
+
function keyUndiciDispatches() {
|
|
496
|
+
if (ORIGINAL_DEFINE_PROPERTY || !worldBase() || Object.defineProperty.name === 'keyingDefineProperty') return;
|
|
497
|
+
const define = ORIGINAL_DEFINE_PROPERTY = Object.defineProperty;
|
|
498
|
+
Object.defineProperty = function keyingDefineProperty(target, name, descriptor) {
|
|
499
|
+
if (ORIGINAL_DEFINE_PROPERTY && target === globalThis && UNDICI_DISPATCHERS.includes(name) && descriptor && 'value' in descriptor) descriptor = Object.assign({}, descriptor, { value: keyedView(descriptor.value) });
|
|
500
|
+
return define(target, name, descriptor);
|
|
501
|
+
};
|
|
502
|
+
for (const name of UNDICI_DISPATCHERS) if (globalThis[name]) globalThis[name] = keyedView(globalThis[name]);
|
|
503
|
+
}
|
|
504
|
+
function unkeyUndiciDispatches() {
|
|
505
|
+
if (!ORIGINAL_DEFINE_PROPERTY) return;
|
|
506
|
+
// only what this put in place is put back: a wrapper installed over it since stays
|
|
507
|
+
if (Object.defineProperty.name === 'keyingDefineProperty') Object.defineProperty = ORIGINAL_DEFINE_PROPERTY;
|
|
508
|
+
ORIGINAL_DEFINE_PROPERTY = null;
|
|
509
|
+
for (const name of UNDICI_DISPATCHERS) if (KEYED_VIEWS.has(globalThis[name])) globalThis[name] = KEYED_VIEWS.get(globalThis[name]);
|
|
510
|
+
}
|
|
511
|
+
|
|
438
512
|
// S4 review F3: undici's default redirect-follow forwards CUSTOM headers across origins — a
|
|
439
513
|
// twin (or the World) answering 30x to an external URL would carry x-twins-key to a REAL host. A
|
|
440
514
|
// keyed fetch follows redirects itself: a hop that is a twin or the World re-enters the patched
|
|
@@ -979,6 +1053,7 @@ function install(mapOverride) {
|
|
|
979
1053
|
tls.connect = patchedConnect(ORIGINALS.tlsConnect, true);
|
|
980
1054
|
dns.lookup = patchedLookup(ORIGINALS.dnsLookup);
|
|
981
1055
|
dns.promises.lookup = patchedPromisesLookup(ORIGINALS.dnsPromisesLookup);
|
|
1056
|
+
keyUndiciDispatches();
|
|
982
1057
|
// gRPC (architecture, "Other wires": gRPC): an HTTP/2 session to a host a twin serves (grpc-js on google-gax: TLS to
|
|
983
1058
|
// webrisk.googleapis.com) connects to that twin's origin in plain text, where the kernel's HTTP/2 server answers it;
|
|
984
1059
|
// the client carries on unchanged. Any other authority is the real one's.
|
|
@@ -1139,6 +1214,7 @@ function restore() {
|
|
|
1139
1214
|
dns.lookup = ORIGINALS.dnsLookup;
|
|
1140
1215
|
dns.promises.lookup = ORIGINALS.dnsPromisesLookup;
|
|
1141
1216
|
http2.connect = ORIGINALS.http2Connect;
|
|
1217
|
+
unkeyUndiciDispatches();
|
|
1142
1218
|
installed = false;
|
|
1143
1219
|
MAP = {};
|
|
1144
1220
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/world-core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.22",
|
|
4
4
|
"description": "The kernel of Volter World: one log per twin, branches as pointers, checkpoints, the fold that keeps a twin current, the head that performs a write against the vendor, references, and the git plane. A twin package builds on it; the runtime serves it.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
package/src/derived.ts
CHANGED
|
@@ -210,9 +210,10 @@ export type DerivedFetch = ((request: Request) => Promise<Response>) & {
|
|
|
210
210
|
/** A workspace screen a pack draws, as `GET /twin` lists it: its id and path (Viewing a World). */
|
|
211
211
|
export type Workspace = { id: string; path: string };
|
|
212
212
|
|
|
213
|
-
/** A
|
|
214
|
-
*
|
|
215
|
-
*
|
|
213
|
+
/** A page of the World's board (architecture, "The board"): a page there is to see at the vendor, a record's own (an
|
|
214
|
+
* account's profile, each of its posts, a site and each page it serves), as the vendor's pack lists them from its state
|
|
215
|
+
* (`semantics/board.ts`). Every field is a fact of the World's state: which of them a person looks at is the board's
|
|
216
|
+
* choice, never the pack's. `GET /twin/board` lists them. */
|
|
216
217
|
export type BoardFrame = {
|
|
217
218
|
/** stable within the vendor, whatever the World's ids: what a saved board names the frame by */
|
|
218
219
|
id: string;
|
|
@@ -226,6 +227,11 @@ export type BoardFrame = {
|
|
|
226
227
|
url: string;
|
|
227
228
|
/** the records whose changes are this frame's changes */
|
|
228
229
|
covers: Array<{ type: string; id: string }>;
|
|
230
|
+
/** the id of the page it sits under at the vendor (a post under its author's profile, a site's page under its site):
|
|
231
|
+
* a board showing everything shows a page with no parent and opens the pages under it from there */
|
|
232
|
+
parent?: string;
|
|
233
|
+
/** the World's own: an account the World's applications or people act as, a page of one, a site the World serves */
|
|
234
|
+
ours?: boolean;
|
|
229
235
|
/** set by the kernel, never the pack: whether a built screen of the vendor's (any of its lanes') draws the url */
|
|
230
236
|
drawn?: boolean;
|
|
231
237
|
};
|