rovloom 0.4.0 → 0.5.0
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/README.md +13 -41
- package/dist/src/admin/index.js +1 -1
- package/dist/src/{chunk-1fyfrgte.js → chunk-0ake7e4r.js} +4 -4
- package/dist/src/{chunk-qfyefed3.js → chunk-1bf0wmgk.js} +1 -1
- package/dist/src/chunk-5j0gj6w2.js +7 -0
- package/dist/src/{chunk-dtj9y82v.js → chunk-5n8csngz.js} +119 -34
- package/dist/src/{chunk-v1httsp6.js → chunk-64ftwe9b.js} +2 -2
- package/dist/src/{chunk-76wgt2g5.js → chunk-9y36gntb.js} +6 -5
- package/dist/src/{chunk-ydmabg5t.js → chunk-9yg6x3gt.js} +5 -5
- package/dist/src/{chunk-keg92d31.js → chunk-abd4envz.js} +13 -11
- package/dist/src/{chunk-6hxy1fcg.js → chunk-bspzg8er.js} +2 -2
- package/dist/src/{chunk-t3pn1435.js → chunk-e7x51y0t.js} +2 -2
- package/dist/src/{chunk-qab3m6nh.js → chunk-ebm3kvnq.js} +18 -5
- package/dist/src/{chunk-ymsx7hhd.js → chunk-erdq0rn8.js} +8 -8
- package/dist/src/{chunk-wdr3sdsm.js → chunk-fnakrk0a.js} +42 -11
- package/dist/src/{chunk-bjdqj43d.js → chunk-hpzr94hm.js} +23 -6
- package/dist/src/{chunk-fd9n51mc.js → chunk-n073xnr1.js} +51 -22
- package/dist/src/{chunk-xmkgq3nh.js → chunk-r0nfthsf.js} +2 -2
- package/dist/src/{chunk-z1vhdr3c.js → chunk-rwpynx2j.js} +10 -10
- package/dist/src/{chunk-8x6ygvhh.js → chunk-sj24fpz3.js} +4 -4
- package/dist/src/{chunk-5vx1b9z8.js → chunk-xhq21g24.js} +3 -3
- package/dist/src/{chunk-4af38z2b.js → chunk-ybte82d3.js} +1 -1
- package/dist/src/{chunk-khmgp03q.js → chunk-ympzv86c.js} +65 -13
- package/dist/src/{chunk-se5daacy.js → chunk-z7kkfrgz.js} +1 -1
- package/dist/src/cli/index.js +12 -12
- package/dist/src/cli/main.js +9 -9
- package/dist/src/mcp/index.js +2 -2
- package/dist/src/webui/index.js +13 -3
- package/package.json +1 -1
|
@@ -6,13 +6,13 @@ import"./chunk-9tt13dm0.js";
|
|
|
6
6
|
import"./chunk-g7pnjzkk.js";
|
|
7
7
|
import {
|
|
8
8
|
readOrCreateRoleConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-64ftwe9b.js";
|
|
10
10
|
import {
|
|
11
11
|
resolveRoleConfigPath2
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-1bf0wmgk.js";
|
|
13
13
|
import {
|
|
14
14
|
CliError2
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-hpzr94hm.js";
|
|
16
16
|
import"./chunk-3nnahj0j.js";
|
|
17
17
|
import"./chunk-0y5542k8.js";
|
|
18
18
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
parseManagementReadPath
|
|
15
15
|
} from "./chunk-gav2y5y9.js";
|
|
16
16
|
import {
|
|
17
|
+
isWildcardHostname,
|
|
17
18
|
canonicalLoopbackHost
|
|
18
19
|
} from "./chunk-6n9s7nfe.js";
|
|
19
20
|
|
|
@@ -37,6 +38,30 @@ var statuses = {
|
|
|
37
38
|
invalid_response: 502,
|
|
38
39
|
timeout: 504
|
|
39
40
|
};
|
|
41
|
+
function lanAwareOrigin(request, loopback, lan) {
|
|
42
|
+
const raw = request.headers.get("host");
|
|
43
|
+
if (!raw || Buffer.byteLength(raw) > 2048) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const expected = new URL(loopback);
|
|
47
|
+
const host = raw.toLowerCase();
|
|
48
|
+
if (host === expected.host.toLowerCase()) {
|
|
49
|
+
return expected.origin;
|
|
50
|
+
}
|
|
51
|
+
if (!lan) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const url = new URL(request.url);
|
|
56
|
+
const candidate = "http://" + host;
|
|
57
|
+
if (new URL(candidate).origin !== candidate) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return url.host.toLowerCase() === host && url.protocol === "http:" ? candidate : null;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
40
65
|
function failure(code, status) {
|
|
41
66
|
return new Response(JSON.stringify({ error: code }), {
|
|
42
67
|
status,
|
|
@@ -77,6 +102,9 @@ function assets(input) {
|
|
|
77
102
|
return result;
|
|
78
103
|
}
|
|
79
104
|
function allowed(request, expected) {
|
|
105
|
+
if (expected === null) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
80
108
|
if (new TextEncoder().encode(request.url).byteLength > MANAGEMENT_URL_BYTES) {
|
|
81
109
|
return null;
|
|
82
110
|
}
|
|
@@ -118,7 +146,7 @@ function context(identity, signal) {
|
|
|
118
146
|
async function initialize(implementation, request, body, signal) {
|
|
119
147
|
return implementation(request, new Response(body.slice().buffer, { headers: { ...headers, "content-type": managementAssetType("/") } }), signal);
|
|
120
148
|
}
|
|
121
|
-
function prepare(options, origin) {
|
|
149
|
+
function prepare(options, origin, lan = () => false) {
|
|
122
150
|
if (!options || typeof options.authenticate !== "function") {
|
|
123
151
|
throw new Error("management_authentication_required");
|
|
124
152
|
}
|
|
@@ -174,7 +202,7 @@ function prepare(options, origin) {
|
|
|
174
202
|
}
|
|
175
203
|
let url;
|
|
176
204
|
try {
|
|
177
|
-
url = allowed(request, origin());
|
|
205
|
+
url = allowed(request, lanAwareOrigin(request, origin(), lan()));
|
|
178
206
|
} catch {
|
|
179
207
|
url = null;
|
|
180
208
|
}
|
|
@@ -264,24 +292,27 @@ function prepare(options, origin) {
|
|
|
264
292
|
}
|
|
265
293
|
function createManagementReadHandler2(options) {
|
|
266
294
|
const url = new URL(options.origin);
|
|
267
|
-
if (url.origin !== options.origin || url.protocol !== "http:" ||
|
|
295
|
+
if (url.origin !== options.origin || url.protocol !== "http:" || !["127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password) {
|
|
268
296
|
throw new Error("management_listener_invalid");
|
|
269
297
|
}
|
|
270
|
-
return prepare(options, () => options.origin);
|
|
298
|
+
return prepare(options, () => options.origin, () => options.lan === true);
|
|
271
299
|
}
|
|
272
300
|
function startManagementReadListener2(options) {
|
|
273
301
|
if (!options) {
|
|
274
302
|
throw new Error("management_listener_invalid");
|
|
275
303
|
}
|
|
276
304
|
let origin = "";
|
|
277
|
-
|
|
305
|
+
let lan = false;
|
|
306
|
+
const handler = prepare(options, () => origin, () => lan);
|
|
278
307
|
try {
|
|
279
308
|
return startManagementListener2({
|
|
280
309
|
port: options.port,
|
|
281
310
|
hostname: options.hostname,
|
|
311
|
+
lan: options.lan === true,
|
|
282
312
|
maxRequestBodySize: 1,
|
|
283
|
-
handler: (actualOrigin) => {
|
|
313
|
+
handler: (actualOrigin, actualLan) => {
|
|
284
314
|
origin = actualOrigin;
|
|
315
|
+
lan = actualLan;
|
|
285
316
|
return handler;
|
|
286
317
|
}
|
|
287
318
|
});
|
|
@@ -307,7 +338,7 @@ function startManagementListener2(options) {
|
|
|
307
338
|
});
|
|
308
339
|
const url = new URL(`http://${canonicalLoopbackHost(options.hostname)}:${server.port}`).origin;
|
|
309
340
|
try {
|
|
310
|
-
handler = options.handler(url);
|
|
341
|
+
handler = options.handler(url, options.lan === true && isWildcardHostname(options.hostname));
|
|
311
342
|
if (typeof handler?.fetch !== "function" || typeof handler.stop !== "function") {
|
|
312
343
|
throw new Error("management_listener_invalid");
|
|
313
344
|
}
|
|
@@ -844,7 +875,7 @@ function createManagementHandler2(options) {
|
|
|
844
875
|
throw new Error("management_csrf_required");
|
|
845
876
|
}
|
|
846
877
|
const reads = createManagementReadHandler2(options);
|
|
847
|
-
const
|
|
878
|
+
const expected = (request) => lanAwareOrigin(request, options.origin, options.lan === true);
|
|
848
879
|
const pending = new Set;
|
|
849
880
|
let stopped = false;
|
|
850
881
|
let tokens = 16;
|
|
@@ -930,7 +961,7 @@ function createManagementHandler2(options) {
|
|
|
930
961
|
size += Buffer.byteLength(name + value);
|
|
931
962
|
count++;
|
|
932
963
|
}
|
|
933
|
-
if (request.url.length > 2048 || size > 16384 || count > 48 || url.origin !==
|
|
964
|
+
if (request.url.length > 2048 || size > 16384 || count > 48 || url.origin !== expected(request) || request.headers.get("origin") !== url.origin || url.username || url.password || url.search || url.hash || request.headers.has("sec-fetch-site") && request.headers.get("sec-fetch-site") !== "same-origin") {
|
|
934
965
|
return failure2("forbidden", 403);
|
|
935
966
|
}
|
|
936
967
|
if (request.method !== "POST") {
|
|
@@ -1025,16 +1056,37 @@ function createManagementSessionAdapter2(options) {
|
|
|
1025
1056
|
throw new Error("management_cookie_name_invalid");
|
|
1026
1057
|
}
|
|
1027
1058
|
const origin = new URL(options.origin);
|
|
1028
|
-
if (origin.origin !== options.origin || origin.protocol !== "http:" ||
|
|
1059
|
+
if (origin.origin !== options.origin || origin.protocol !== "http:" || !["127.0.0.1", "[::1]"].includes(origin.hostname) || origin.username || origin.password) {
|
|
1029
1060
|
throw new Error("management_listener_invalid");
|
|
1030
1061
|
}
|
|
1031
1062
|
const identities = options.identities;
|
|
1032
1063
|
const sessions = options.sessions;
|
|
1033
1064
|
const now = options.now ?? Date.now;
|
|
1034
1065
|
let observed = 0;
|
|
1066
|
+
function expected(request) {
|
|
1067
|
+
const raw = request.headers.get("host");
|
|
1068
|
+
if (!raw || Buffer.byteLength(raw) > 2048) {
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
const host = raw.toLowerCase();
|
|
1072
|
+
if (host === origin.host.toLowerCase()) {
|
|
1073
|
+
return origin.origin;
|
|
1074
|
+
}
|
|
1075
|
+
if (!options.lan) {
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
try {
|
|
1079
|
+
const url = new URL(request.url);
|
|
1080
|
+
const candidate = "http://" + host;
|
|
1081
|
+
return new URL(candidate).origin === candidate && url.host.toLowerCase() === host && url.protocol === "http:" ? candidate : null;
|
|
1082
|
+
} catch {
|
|
1083
|
+
return null;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1035
1086
|
function cookie(request) {
|
|
1036
1087
|
const url = new URL(request.url);
|
|
1037
|
-
|
|
1088
|
+
const trusted = expected(request);
|
|
1089
|
+
if (trusted === null || url.origin !== trusted || request.headers.has("origin") && request.headers.get("origin") !== trusted) {
|
|
1038
1090
|
return null;
|
|
1039
1091
|
}
|
|
1040
1092
|
const site = request.headers.get("sec-fetch-site");
|
|
@@ -1115,7 +1167,7 @@ function createManagementSessionAdapter2(options) {
|
|
|
1115
1167
|
if (request.method !== "POST") {
|
|
1116
1168
|
return false;
|
|
1117
1169
|
}
|
|
1118
|
-
if (request.headers.get("origin") !==
|
|
1170
|
+
if (request.headers.get("origin") !== expected(request) || request.headers.has("sec-fetch-site") && request.headers.get("sec-fetch-site") !== "same-origin") {
|
|
1119
1171
|
return false;
|
|
1120
1172
|
}
|
|
1121
1173
|
const candidate = request.headers.get("x-rovloom-csrf");
|
|
@@ -1132,4 +1184,4 @@ function createManagementSessionAdapter2(options) {
|
|
|
1132
1184
|
}
|
|
1133
1185
|
export { createManagementReadHandler2, startManagementReadListener2, startManagementListener2, loadManagementAssets2, ManagementServiceError2, StoreManagementWriteService2, createManagementHandler2, createManagementSessionAdapter2 };
|
|
1134
1186
|
|
|
1135
|
-
//# debugId=
|
|
1187
|
+
//# debugId=5F343A955701396E64756E2164756E21
|
package/dist/src/cli/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
HELP2,
|
|
9
9
|
parseCommand2,
|
|
10
10
|
runCli2
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-abd4envz.js";
|
|
12
12
|
import {
|
|
13
13
|
Store2
|
|
14
14
|
} from "../chunk-nyn75b8v.js";
|
|
@@ -16,7 +16,7 @@ import"../chunk-09f9q26d.js";
|
|
|
16
16
|
import {
|
|
17
17
|
FacadeServiceError2
|
|
18
18
|
} from "../chunk-smpevv7n.js";
|
|
19
|
-
import"../chunk-
|
|
19
|
+
import"../chunk-9y36gntb.js";
|
|
20
20
|
import {
|
|
21
21
|
Router2
|
|
22
22
|
} from "../chunk-y4hksha9.js";
|
|
@@ -39,38 +39,38 @@ import {
|
|
|
39
39
|
import"../chunk-d4ejrtjq.js";
|
|
40
40
|
import"../chunk-5s2emvww.js";
|
|
41
41
|
import"../chunk-4etdq0cp.js";
|
|
42
|
-
import"../chunk-
|
|
42
|
+
import"../chunk-ympzv86c.js";
|
|
43
43
|
import"../chunk-5h82060k.js";
|
|
44
44
|
import"../chunk-863tk45b.js";
|
|
45
45
|
import"../chunk-zb641qa3.js";
|
|
46
46
|
import"../chunk-ttsrctxg.js";
|
|
47
47
|
import"../chunk-5svt6rwr.js";
|
|
48
48
|
import"../chunk-2tn0r64b.js";
|
|
49
|
-
import"../chunk-
|
|
50
|
-
import"../chunk-
|
|
49
|
+
import"../chunk-fnakrk0a.js";
|
|
50
|
+
import"../chunk-n073xnr1.js";
|
|
51
51
|
import {
|
|
52
52
|
createRuntimeCliRuntime2,
|
|
53
53
|
MANAGEMENT_COOKIE_NAME2,
|
|
54
54
|
MANAGEMENT_BOOTSTRAP_META2,
|
|
55
55
|
createManagementPageInitializer2,
|
|
56
56
|
createProductionCliRuntime2
|
|
57
|
-
} from "../chunk-
|
|
58
|
-
import"../chunk-
|
|
57
|
+
} from "../chunk-5n8csngz.js";
|
|
58
|
+
import"../chunk-ebm3kvnq.js";
|
|
59
59
|
import {
|
|
60
60
|
readRuntimeConfig2
|
|
61
|
-
} from "../chunk-
|
|
62
|
-
import"../chunk-
|
|
61
|
+
} from "../chunk-bspzg8er.js";
|
|
62
|
+
import"../chunk-64ftwe9b.js";
|
|
63
63
|
import {
|
|
64
64
|
resolveRoleConfigPath2
|
|
65
|
-
} from "../chunk-
|
|
66
|
-
import"../chunk-
|
|
65
|
+
} from "../chunk-1bf0wmgk.js";
|
|
66
|
+
import"../chunk-z7kkfrgz.js";
|
|
67
67
|
import {
|
|
68
68
|
CliError2,
|
|
69
69
|
parseConfig2,
|
|
70
70
|
configDocument2,
|
|
71
71
|
configTemplate2,
|
|
72
72
|
readConfig2
|
|
73
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-hpzr94hm.js";
|
|
74
74
|
import"../chunk-vwcntax3.js";
|
|
75
75
|
import"../chunk-gbsbwssz.js";
|
|
76
76
|
import"../chunk-3nnahj0j.js";
|
package/dist/src/cli/main.js
CHANGED
|
@@ -10,20 +10,20 @@ import"../chunk-g7pnjzkk.js";
|
|
|
10
10
|
import {
|
|
11
11
|
parseCommand2,
|
|
12
12
|
runCli2
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-abd4envz.js";
|
|
14
14
|
import {
|
|
15
15
|
createNativeServiceBackend2,
|
|
16
16
|
ServiceManager2
|
|
17
17
|
} from "../chunk-ttm3c0jh.js";
|
|
18
|
-
import"../chunk-
|
|
19
|
-
import"../chunk-
|
|
18
|
+
import"../chunk-bspzg8er.js";
|
|
19
|
+
import"../chunk-64ftwe9b.js";
|
|
20
20
|
import {
|
|
21
21
|
resolveRoleConfigPath2
|
|
22
|
-
} from "../chunk-
|
|
23
|
-
import"../chunk-
|
|
22
|
+
} from "../chunk-1bf0wmgk.js";
|
|
23
|
+
import"../chunk-z7kkfrgz.js";
|
|
24
24
|
import {
|
|
25
25
|
parseConfig2
|
|
26
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-hpzr94hm.js";
|
|
27
27
|
import {
|
|
28
28
|
manifest,
|
|
29
29
|
serviceControlId
|
|
@@ -300,10 +300,10 @@ async function control(role) {
|
|
|
300
300
|
}
|
|
301
301
|
async function product() {
|
|
302
302
|
if (!runtime) {
|
|
303
|
-
const { createProductSources } = await import("../chunk-
|
|
304
|
-
const { CliSetup } = await import("../chunk-
|
|
303
|
+
const { createProductSources } = await import("../chunk-e7x51y0t.js");
|
|
304
|
+
const { CliSetup } = await import("../chunk-erdq0rn8.js");
|
|
305
305
|
setup = new CliSetup;
|
|
306
|
-
runtime = (await import("../chunk-
|
|
306
|
+
runtime = (await import("../chunk-rwpynx2j.js")).createProductionCliRuntime(createProductSources(), setup);
|
|
307
307
|
}
|
|
308
308
|
return runtime;
|
|
309
309
|
}
|
package/dist/src/mcp/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
HTTP_BODY_BYTES2,
|
|
6
6
|
createHttpFacade2,
|
|
7
7
|
startHttpFacade2
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-9y36gntb.js";
|
|
9
9
|
import {
|
|
10
10
|
StoreGatewayService2,
|
|
11
11
|
RuntimeGatewayService2
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
MCP_REVISION2,
|
|
24
24
|
PRODUCT_VERSION2
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-r0nfthsf.js";
|
|
26
26
|
import"../chunk-zj48jvfe.js";
|
|
27
27
|
import"../chunk-0xgpxdgc.js";
|
|
28
28
|
import"../chunk-gbsbwssz.js";
|
package/dist/src/webui/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_PAIRING_POLICY_REF
|
|
4
|
+
} from "../chunk-5j0gj6w2.js";
|
|
2
5
|
import {
|
|
3
6
|
ReadError2,
|
|
4
7
|
createSnapshotReader2,
|
|
@@ -1192,6 +1195,12 @@ function createPreferenceControl(kind, choices, onChoose) {
|
|
|
1192
1195
|
return { root, update, close, dispose };
|
|
1193
1196
|
}
|
|
1194
1197
|
|
|
1198
|
+
// src/webui/request-id.ts
|
|
1199
|
+
function managementRequestId() {
|
|
1200
|
+
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
1201
|
+
return "request_" + Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1195
1204
|
// src/webui/write-contract.ts
|
|
1196
1205
|
class ManagementClientError extends Error {
|
|
1197
1206
|
problem;
|
|
@@ -1695,7 +1704,7 @@ function createDeviceManagementFlow(options) {
|
|
|
1695
1704
|
let active;
|
|
1696
1705
|
let generation = 0;
|
|
1697
1706
|
let disposed = false;
|
|
1698
|
-
const requestId = options.requestId ??
|
|
1707
|
+
const requestId = options.requestId ?? managementRequestId;
|
|
1699
1708
|
async function execute(operation, args, signal) {
|
|
1700
1709
|
if (signal.aborted) {
|
|
1701
1710
|
throw new ManagementClientError("aborted");
|
|
@@ -2320,7 +2329,7 @@ function createPairingManagementFlow(options) {
|
|
|
2320
2329
|
let active;
|
|
2321
2330
|
let generation = 0;
|
|
2322
2331
|
let disposed = false;
|
|
2323
|
-
const requestId = options.requestId ??
|
|
2332
|
+
const requestId = options.requestId ?? managementRequestId;
|
|
2324
2333
|
async function execute(operation, args, signal) {
|
|
2325
2334
|
if (signal.aborted) {
|
|
2326
2335
|
throw new ManagementClientError("aborted");
|
|
@@ -2569,6 +2578,7 @@ function createPairingActions(options) {
|
|
|
2569
2578
|
policyInput.required = true;
|
|
2570
2579
|
policyInput.maxLength = 128;
|
|
2571
2580
|
policyInput.autocomplete = "off";
|
|
2581
|
+
policyInput.value = DEFAULT_PAIRING_POLICY_REF;
|
|
2572
2582
|
policyLabel.append(policyCaption, policyInput);
|
|
2573
2583
|
const create = node3("button", "pairing-confirm");
|
|
2574
2584
|
create.type = "submit";
|
|
@@ -3507,4 +3517,4 @@ export {
|
|
|
3507
3517
|
unavailableRead
|
|
3508
3518
|
};
|
|
3509
3519
|
|
|
3510
|
-
//# debugId=
|
|
3520
|
+
//# debugId=D52975500C6ECA9664756E2164756E21
|