rovloom 0.5.0 → 0.6.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.
Files changed (34) hide show
  1. package/README.md +8 -0
  2. package/dist/src/admin/index.js +1 -1
  3. package/dist/src/{chunk-smpevv7n.js → chunk-0dqx2mmz.js} +9 -16
  4. package/dist/src/{chunk-rwpynx2j.js → chunk-0qgk7mhz.js} +12 -11
  5. package/dist/src/{chunk-erdq0rn8.js → chunk-3dvn33c4.js} +57 -58
  6. package/dist/src/chunk-5b8g62kw.js +438 -0
  7. package/dist/src/{chunk-64ftwe9b.js → chunk-8ykrqhxh.js} +8 -2
  8. package/dist/src/{chunk-9y36gntb.js → chunk-9zkq0kc8.js} +10 -5
  9. package/dist/src/{chunk-5n8csngz.js → chunk-d2kz25f2.js} +156 -11
  10. package/dist/src/{chunk-ympzv86c.js → chunk-ez7d5dac.js} +13 -4
  11. package/dist/src/{chunk-emcefrc1.js → chunk-g27b2gmx.js} +3 -4
  12. package/dist/src/{chunk-abd4envz.js → chunk-gyvqqnjb.js} +30 -57
  13. package/dist/src/{chunk-e7x51y0t.js → chunk-jf4r0r44.js} +2 -2
  14. package/dist/src/{chunk-4etdq0cp.js → chunk-jka7v3wb.js} +4 -7
  15. package/dist/src/{chunk-xhq21g24.js → chunk-m9c1pnv9.js} +3 -3
  16. package/dist/src/{chunk-7k9g0x5e.js → chunk-mg0fd6ph.js} +1 -1
  17. package/dist/src/{chunk-0ake7e4r.js → chunk-n6wtjyfb.js} +6 -14
  18. package/dist/src/{chunk-nyn75b8v.js → chunk-qjh9x872.js} +30 -1
  19. package/dist/src/{chunk-r0nfthsf.js → chunk-s3ydr65k.js} +2 -2
  20. package/dist/src/{chunk-ybte82d3.js → chunk-srfbjwtk.js} +4 -3
  21. package/dist/src/{chunk-sj24fpz3.js → chunk-ssp57p43.js} +24 -28
  22. package/dist/src/{chunk-ebm3kvnq.js → chunk-wxqhscsw.js} +26 -3
  23. package/dist/src/{chunk-7q96e161.js → chunk-x0td5wn4.js} +6 -12
  24. package/dist/src/{chunk-9yg6x3gt.js → chunk-ytpfmcp1.js} +4 -3
  25. package/dist/src/{chunk-fnakrk0a.js → chunk-yv9px0f5.js} +22 -25
  26. package/dist/src/{chunk-n073xnr1.js → chunk-zjkjjm81.js} +43 -46
  27. package/dist/src/cli/index.js +23 -15
  28. package/dist/src/cli/main.js +14 -9
  29. package/dist/src/mcp/index.js +6 -5
  30. package/dist/src/runtime/index.js +2 -2
  31. package/dist/src/service/index.js +3 -4
  32. package/dist/src/store.js +1 -1
  33. package/dist/src/webui/index.js +1095 -156
  34. package/package.json +1 -1
@@ -931,7 +931,7 @@ function createManagementHandler2(options) {
931
931
  return failure2("invalid_arguments", 400);
932
932
  }
933
933
  const context = { ...identity, wait_signal: controller.signal };
934
- const reply = await options.service.execute(operation, args, context);
934
+ const reply = operation.startsWith("resources/") ? await options.resources.execute(operation.slice("resources/".length), args, identity, controller.signal) : await options.service.execute(operation, args, context);
935
935
  if (controller.signal.aborted) {
936
936
  return failure2("outcome_unconfirmed", 503);
937
937
  }
@@ -952,7 +952,7 @@ function createManagementHandler2(options) {
952
952
  } catch {
953
953
  return failure2("forbidden", 403);
954
954
  }
955
- if (!url.pathname.startsWith("/admin/v1/actions/")) {
955
+ if (!url.pathname.startsWith("/admin/v1/actions/") && !url.pathname.startsWith("/admin/v1/resources/")) {
956
956
  return reads.fetch(request);
957
957
  }
958
958
  let size = 0;
@@ -967,7 +967,16 @@ function createManagementHandler2(options) {
967
967
  if (request.method !== "POST") {
968
968
  return failure2("method_not_allowed", 405);
969
969
  }
970
- const operation = routes.get(url.pathname);
970
+ const resource = url.pathname.startsWith("/admin/v1/resources/") ? url.pathname.slice("/admin/v1/resources/".length) : null;
971
+ const operation = resource !== null && options.resources && [
972
+ "tokens_list",
973
+ "tokens_create",
974
+ "tokens_delete",
975
+ "tokens_rotate",
976
+ "pairings_list",
977
+ "pairings_delete",
978
+ "devices_delete"
979
+ ].includes(resource) ? `resources/${resource}` : routes.get(url.pathname);
971
980
  if (!operation) {
972
981
  return failure2("not_found", 404);
973
982
  }
@@ -1184,4 +1193,4 @@ function createManagementSessionAdapter2(options) {
1184
1193
  }
1185
1194
  export { createManagementReadHandler2, startManagementReadListener2, startManagementListener2, loadManagementAssets2, ManagementServiceError2, StoreManagementWriteService2, createManagementHandler2, createManagementSessionAdapter2 };
1186
1195
 
1187
- //# debugId=5F343A955701396E64756E2164756E21
1196
+ //# debugId=4BCF3E6652F2586E64756E2164756E21
@@ -1,13 +1,12 @@
1
1
  // @bun
2
2
  import {
3
- SERVICE_HELP2,
4
3
  parseServiceCommand2,
5
4
  handleServiceCommand2
6
- } from "./chunk-7q96e161.js";
5
+ } from "./chunk-x0td5wn4.js";
6
+ import"./chunk-5b8g62kw.js";
7
7
  export {
8
- SERVICE_HELP2 as SERVICE_HELP,
9
8
  handleServiceCommand2 as handleServiceCommand,
10
9
  parseServiceCommand2 as parseServiceCommand
11
10
  };
12
11
 
13
- //# debugId=C3691EFE843F735764756E2164756E21
12
+ //# debugId=2172CFBA81B35CDA64756E2164756E21
@@ -1,10 +1,14 @@
1
1
  // @bun
2
+ import {
3
+ cliMessages2,
4
+ formatMessage2
5
+ } from "./chunk-5b8g62kw.js";
2
6
  import {
3
7
  readRuntimeConfig2
4
8
  } from "./chunk-bspzg8er.js";
5
9
  import {
6
10
  readOrCreateRoleConfig
7
- } from "./chunk-64ftwe9b.js";
11
+ } from "./chunk-8ykrqhxh.js";
8
12
  import {
9
13
  resolveRoleConfigPath2
10
14
  } from "./chunk-1bf0wmgk.js";
@@ -18,7 +22,7 @@ import {
18
22
  } from "./chunk-hpzr94hm.js";
19
23
  import {
20
24
  PRODUCT_VERSION2
21
- } from "./chunk-r0nfthsf.js";
25
+ } from "./chunk-s3ydr65k.js";
22
26
  import {
23
27
  isWildcardHostname
24
28
  } from "./chunk-6n9s7nfe.js";
@@ -62,44 +66,9 @@ function serviceDiagnostic(text) {
62
66
  }
63
67
 
64
68
  // src/cli/run.ts
65
- var WILDCARD_LISTEN_WARNING = `wildcard_listener
66
- MCP/management listen on all interfaces over plain HTTP; protect them with a firewall or a TLS reverse proxy.
67
- MCP/\u7BA1\u7406\u9875\u76D1\u542C\u6240\u6709\u7F51\u5361\u4E14\u4E3A\u660E\u6587 HTTP\uFF1B\u8BF7\u7528\u9632\u706B\u5899\u6216 TLS \u53CD\u5411\u4EE3\u7406\u6536\u53E3\u3002
68
- `;
69
- var HELP2 = `Rovloom ${PRODUCT_VERSION2}
70
-
71
- \u7528\u6CD5\uFF1A
72
- rovloom --help
73
- rovloom --version
74
- rovloom config template gateway|connector
75
- rovloom config init connector [--provider luvus|herdr|mixed] [--config /absolute/path/config.json]
76
- rovloom config init gateway [--container] [--config /absolute/path/config.json]
77
- rovloom config check [--role gateway|connector] [--config /absolute/path/config.json]
78
- rovloom config check-runtime [--role gateway|connector] [--config /absolute/path/config.json]
79
- rovloom gateway [--add-device | --repair-device] [--config /absolute/path/config.json] [--non-interactive]
80
- rovloom connector [--repair | --claim] [--config /absolute/path/config.json] [--non-interactive]
81
- rovloom service --help
82
- rovloom token --help
83
- rovloom doctor --help
84
- rovloom storage --help
85
- rovloom admin --help
86
-
87
- gateway / connector \u542F\u52A8\u5BF9\u5E94\u89D2\u8272\u3002\u9996\u6B21\u8FD0\u884C\u65F6\u5728\u771F\u5B9E\u672C\u5730\u7EC8\u7AEF\u5B8C\u6210\u4E00\u6B21\u6027\u914D\u5BF9\u4E0E\u539F\u751F\u5B89\u88C5\u6279\u51C6\uFF1B
88
- \u5728\u7EC8\u7AEF\u62D2\u7EDD\u914D\u5BF9\u63D0\u793A\u65F6\uFF0CGateway \u4FDD\u6301\u672A\u914D\u5BF9\u8FD0\u884C\uFF0C\u53EF\u5148\u8FD0\u884C rovloom admin create \u518D\u4ECE\u7BA1\u7406\u9875\u5B8C\u6210\u9996\u53F0\u914D\u5BF9\uFF1B
89
- --add-device \u5728\u5DF2\u5B8C\u6210\u7684\u5F15\u5BFC\u4E4B\u4E0A\u518D\u914D\u5BF9\u4E00\u53F0 Connector\uFF08\u6CBF\u7528\u540C\u4E00 MCP \u51ED\u636E\uFF0C\u6388\u6743\u968F\u4E4B\u6269\u5927\u5230\u65B0\u8BBE\u5907\uFF09\uFF1B
90
- --repair-device / --repair \u91CD\u65B0\u914D\u5BF9\u5DF2\u914D\u5BF9\u7684\u540C\u4E00\u8BBE\u5907\uFF08\u51ED\u636E\u4E22\u5931\u6216\u6CC4\u6F0F\uFF09\uFF0C\u4FDD\u7559\u539F\u751F\u8BBE\u7F6E\u4E0E MCP \u6388\u6743\u3002
91
- --claim \u8BA9\u672A\u914D\u5BF9\u7684 Connector \u5411\u8FD0\u884C\u4E2D\u7684 Gateway \u5728\u7EBF\u8BA4\u9886\u7BA1\u7406\u5458\u521B\u5EFA\u7684\u914D\u5BF9\u7533\u8BF7\uFF08\u7BA1\u7406\u9875\u6838\u5BF9\u7801\u6279\u51C6\uFF0CGateway \u4E0D\u505C\u673A\uFF09\u3002
92
- \u8FD9\u56DB\u4E2A\u9009\u9879\u9700\u8981\u771F\u5B9E\u672C\u5730\u7EC8\u7AEF\uFF0C\u4E0D\u53EF\u4E0E --non-interactive \u5408\u7528\u3002--non-interactive \u5173\u95ED\u672C\u5730\u4EA4\u4E92\u5F15\u5BFC\uFF08\u670D\u52A1\u4EE5\u6B64\u8FD0\u884C\uFF09\u3002
93
- token \u7BA1\u7406 MCP Bearer \u4EE4\u724C\uFF0Cadmin \u7BA1\u7406\u7BA1\u7406\u9875\u7BA1\u7406\u5458\uFF0Cservice \u7BA1\u7406\u5F00\u673A\u670D\u52A1\uFF1B\u8BE6\u89C1\u5404\u81EA\u7684 --help\u3002
94
- config check \u53EA\u8BFB\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\uFF1Bcheck-runtime \u53E6\u6838\u5BF9\u7A0B\u5E8F\u7BA1\u7406\u7684\u72B6\u6001\uFF0C\u4E0D\u8BFB\u53D6\u51ED\u636E\u3002
95
-
96
- \u7701\u7565 --config \u65F6\u8BFB\u53D6 ~/.config/rovloom/gateway.json \u6216 connector.json\uFF08Windows \u540C\u6837\u4F7F\u7528\u7528\u6237 home\uFF09\u3002
97
- \u6587\u4EF6\u7F3A\u5931\u65F6\u9996\u6B21\u8FD0\u884C\u4F1A\u751F\u6210\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u5DF2\u6709\u6587\u4EF6\u4E0D\u4F1A\u88AB\u8986\u76D6\u6216\u91CD\u7F6E\u3002
98
- Gateway \u652F\u6301 Linux/macOS/Windows\uFF1BConnector \u652F\u6301 Linux x64\u3001Windows x64 \u4E0E macOS\uFF08x64 / arm64\uFF0C\u4EC5\u9644\u7740\u5DF2\u8FD0\u884C\u7684 Herdr / Luvus\uFF09\u3002
99
- \u9996\u6B21\u5F15\u5BFC\u6309 Connector \u7684 native.provider \u9009\u62E9 luvus\uFF08\u9ED8\u8BA4\uFF09\u3001herdr \u6216 mixed\u3002
100
- Agent \u4E0E\u6A21\u578B\u767B\u5F55\u9700\u72EC\u7ACB\u51C6\u5907\uFF1B\u539F\u751F ready \u4E0D\u4EE3\u8868\u6A21\u578B\u5DF2\u56DE\u590D\u3002
101
- \u9000\u51FA\u7801\uFF1A0 \u6210\u529F/\u6B63\u5E38\u5173\u95ED\uFF0C2 \u53C2\u6570\u6216\u914D\u7F6E\u9519\u8BEF\uFF0C3 \u540E\u7AEF\u4E0D\u53EF\u7528\uFF0C1 \u8FD0\u884C\u6216\u5173\u95ED\u5931\u8D25\u3002
102
- `;
69
+ function cliHelp2(language = "en") {
70
+ return formatMessage2(cliMessages2(language)["help.main"], { version: PRODUCT_VERSION2 });
71
+ }
103
72
  function parseCommand2(args, environment) {
104
73
  if (args.length === 0 || args.length === 1 && ["--help", "-h", "help"].includes(args[0])) {
105
74
  return { action: "help" };
@@ -183,9 +152,9 @@ async function untilStopped(running, signal) {
183
152
  async function runCli2(args, io, runtime = {}, environment) {
184
153
  try {
185
154
  if (args[0] === "service") {
186
- const { SERVICE_HELP, handleServiceCommand } = await import("./chunk-emcefrc1.js");
155
+ const { handleServiceCommand } = await import("./chunk-g27b2gmx.js");
187
156
  if (args.length === 2 && args[1] === "--help") {
188
- io.stderr.write(SERVICE_HELP);
157
+ io.stderr.write(cliMessages2(io.language)["help.service"]);
189
158
  return 0;
190
159
  }
191
160
  if (!runtime.service) {
@@ -194,6 +163,7 @@ async function runCli2(args, io, runtime = {}, environment) {
194
163
  const host = runtime.service;
195
164
  const code = await handleServiceCommand(args, {
196
165
  ...host,
166
+ language: io.language ?? "en",
197
167
  resolveDefaultConfig: host.resolveDefaultConfig ? (role, account) => {
198
168
  try {
199
169
  return host.resolveDefaultConfig(role, account);
@@ -212,19 +182,19 @@ async function runCli2(args, io, runtime = {}, environment) {
212
182
  throw new CliError2("invalid_arguments");
213
183
  }
214
184
  if (args[0] === "admin") {
215
- const { handleAdminCommand } = await import("./chunk-9yg6x3gt.js");
185
+ const { handleAdminCommand } = await import("./chunk-ytpfmcp1.js");
216
186
  return await handleAdminCommand(args, io, environment);
217
187
  }
218
188
  if (args[0] === "doctor" || args[0] === "storage") {
219
- const { handleStorageCommand } = await import("./chunk-0ake7e4r.js");
189
+ const { handleStorageCommand } = await import("./chunk-n6wtjyfb.js");
220
190
  return await handleStorageCommand(args, io, environment);
221
191
  }
222
192
  if (args[0] === "token") {
223
- const { handleTokenCommand } = await import("./chunk-sj24fpz3.js");
193
+ const { handleTokenCommand } = await import("./chunk-ssp57p43.js");
224
194
  return await handleTokenCommand(args, io, environment);
225
195
  }
226
196
  if (args[0] === "config" && args[1] === "init") {
227
- const { initializeRoleConfig } = await import("./chunk-xhq21g24.js");
197
+ const { initializeRoleConfig } = await import("./chunk-m9c1pnv9.js");
228
198
  initializeRoleConfig(args, environment);
229
199
  io.stderr.write(`config_ready
230
200
  `);
@@ -232,7 +202,7 @@ async function runCli2(args, io, runtime = {}, environment) {
232
202
  }
233
203
  const command = parseCommand2(args, environment);
234
204
  if (command.action === "help") {
235
- io.stderr.write(HELP2);
205
+ io.stderr.write(cliHelp2(io.language));
236
206
  return 0;
237
207
  }
238
208
  if (command.action === "version") {
@@ -306,15 +276,16 @@ async function runCli2(args, io, runtime = {}, environment) {
306
276
  }
307
277
  let reload = false;
308
278
  let warnedWildcard = false;
279
+ let shownDashboard = false;
309
280
  do {
310
281
  reload = false;
311
282
  const gateway = await runtime.gateway(config);
312
283
  if (!warnedWildcard && (isWildcardHostname(config.mcp_hostname) || config.management_enabled && isWildcardHostname(config.management_hostname))) {
313
284
  warnedWildcard = true;
314
- io.stderr.write(WILDCARD_LISTEN_WARNING);
285
+ io.stderr.write(cliMessages2(io.language)["run.wildcardListenWarning"]);
315
286
  }
316
287
  try {
317
- const { startHttpFacade } = await import("./chunk-ybte82d3.js");
288
+ const { startHttpFacade } = await import("./chunk-srfbjwtk.js");
318
289
  const http = startHttpFacade({
319
290
  service: gateway.service,
320
291
  authentication: gateway.authentication,
@@ -322,17 +293,21 @@ async function runCli2(args, io, runtime = {}, environment) {
322
293
  port: config.mcp_port,
323
294
  ...config.mcp_public_url ? { publicUrl: config.mcp_public_url } : {},
324
295
  ...config.mcp_lan ? { lan: true } : {},
296
+ ...io.language ? { language: io.language } : {},
325
297
  diagnostic: (code) => io.stderr.write(code + `
326
298
  `)
327
299
  });
328
300
  try {
329
301
  await gateway.listening?.(http.url);
302
+ if (!shownDashboard && gateway.managementUrl) {
303
+ shownDashboard = true;
304
+ io.stderr.write("dashboard_listening " + new URL(gateway.managementUrl).href + `
305
+ `);
306
+ }
330
307
  if (gateway.setupRequired) {
331
308
  io.stderr.write("gateway_listening " + http.url + `
332
309
  pairing_required
333
- Gateway is running; complete local pairing and native setup before using an Agent.
334
- Gateway \u5DF2\u542F\u52A8\uFF1B\u4F7F\u7528 Agent \u524D\u4ECD\u9700\u5B8C\u6210\u672C\u5730\u914D\u5BF9\u548C\u539F\u751F\u521D\u59CB\u5316\u3002
335
- `);
310
+ ` + cliMessages2(io.language)["run.pairingRequiredHint"]);
336
311
  }
337
312
  await untilStopped({
338
313
  closed: Promise.race([
@@ -362,9 +337,7 @@ Gateway \u5DF2\u542F\u52A8\uFF1B\u4F7F\u7528 Agent \u524D\u4ECD\u9700\u5B8C\u621
362
337
  io.stderr.write(error.code + `
363
338
  `);
364
339
  if (error.code === "configuration_required") {
365
- io.stderr.write(`Setup requires a local terminal, a reachable Gateway, completed pairing and a compatible installed Luvus. Preserve uncertain setup state for owner review.
366
- \u521D\u59CB\u5316\u9700\u672C\u5730\u7EC8\u7AEF\u3001\u53EF\u8FBE Gateway\u3001\u5B8C\u6574\u914D\u5BF9\u53CA\u517C\u5BB9 Luvus \u5B89\u88C5\uFF1B\u7ED3\u679C\u4E0D\u786E\u5B9A\u65F6\u4FDD\u7559\u539F\u72B6\u6001\u5E76\u7531\u6240\u6709\u8005\u6838\u67E5\u3002
367
- `);
340
+ io.stderr.write(cliMessages2(io.language)["run.configurationRequiredHint"]);
368
341
  }
369
342
  return error.exitCode;
370
343
  }
@@ -374,6 +347,6 @@ Gateway \u5DF2\u542F\u52A8\uFF1B\u4F7F\u7528 Agent \u524D\u4ECD\u9700\u5B8C\u621
374
347
  }
375
348
  }
376
349
 
377
- export { HELP2, parseCommand2, runCli2 };
350
+ export { cliHelp2, parseCommand2, runCli2 };
378
351
 
379
- //# debugId=EDE27C0F1768E16864756E2164756E21
352
+ //# debugId=618C67B77D8D88C964756E2164756E21
@@ -38,7 +38,7 @@ import {
38
38
  closeSession
39
39
  } from "./chunk-zjzrcc59.js";
40
40
  import"./chunk-zj48jvfe.js";
41
- import"./chunk-nyn75b8v.js";
41
+ import"./chunk-qjh9x872.js";
42
42
  import"./chunk-0xgpxdgc.js";
43
43
  import"./chunk-d4ejrtjq.js";
44
44
  import {
@@ -52,7 +52,7 @@ import {
52
52
  composeConnectorSessions2,
53
53
  createLuvusConnectorSessions2,
54
54
  createLuvusProductionSources2
55
- } from "./chunk-4etdq0cp.js";
55
+ } from "./chunk-jka7v3wb.js";
56
56
  import"./chunk-5h82060k.js";
57
57
  import {
58
58
  herdrDeadline,
@@ -55,7 +55,7 @@ import {
55
55
  import {
56
56
  configuredSnapshotDirectory,
57
57
  Store2
58
- } from "./chunk-nyn75b8v.js";
58
+ } from "./chunk-qjh9x872.js";
59
59
  import {
60
60
  createProviderResultAccess2,
61
61
  LUVUS_ENDPOINT_TRANSPORT,
@@ -2030,10 +2030,7 @@ function createManagementSessionAuthority2(source, options = {}) {
2030
2030
  if (lease.revoked && !lease.expiry_only || at < lease.session.expires_at || input.issued_at !== lease.upstream.issued_at || input.expires_at !== lease.upstream.expires_at) {
2031
2031
  throw new GatewayError2("unauthenticated");
2032
2032
  }
2033
- const session = Object.freeze({
2034
- ...lease.upstream,
2035
- expires_at: Math.min(lease.upstream.expires_at, at + 300000)
2036
- });
2033
+ const session = lease.upstream;
2037
2034
  try {
2038
2035
  base(session, lease.policy);
2039
2036
  } catch {
@@ -2054,7 +2051,7 @@ function createManagementSessionAuthority2(source, options = {}) {
2054
2051
  caller,
2055
2052
  management_session_ref: sessionRef,
2056
2053
  issued_at: input.issued_at,
2057
- expires_at: Math.min(input.expires_at, at + 300000)
2054
+ expires_at: input.expires_at
2058
2055
  });
2059
2056
  const current = base(session);
2060
2057
  if (leases.has(name) || leases.size >= capacity) {
@@ -2872,4 +2869,4 @@ function createLuvusProductionSources2() {
2872
2869
  }
2873
2870
  export { createTrustedRequestScope2, composeGatewaySessions2, composeConnectorSessions2, createGatewayRuntime2, createProviderGatewayRuntime2, openGatewayState2, createLuvusConnectorSessions2, createConnectorRuntime2, ConnectorHostStartupError2, createProviderConnectorRuntime2, createManagementSessionAuthority2, createLuvusOperationsProvider2, attachExistingLuvus2, LuvusProductionStartupError2, createLuvusProductionSources2 };
2874
2871
 
2875
- //# debugId=785921E4C40CA8AB64756E2164756E21
2872
+ //# debugId=8FAF80F854C0B57664756E2164756E21
@@ -6,7 +6,7 @@ import"./chunk-9tt13dm0.js";
6
6
  import"./chunk-g7pnjzkk.js";
7
7
  import {
8
8
  readOrCreateRoleConfig
9
- } from "./chunk-64ftwe9b.js";
9
+ } from "./chunk-8ykrqhxh.js";
10
10
  import {
11
11
  resolveRoleConfigPath2
12
12
  } from "./chunk-1bf0wmgk.js";
@@ -50,7 +50,7 @@ function initializeRoleConfig(args, environment) {
50
50
  if (config.role === "connector" && provider && (config.native?.provider ?? "luvus") !== provider) {
51
51
  throw new CliError2("config_exists");
52
52
  }
53
- if (config.role === "gateway" && container && [config.mcp_hostname, config.device_hostname, config.management_hostname].some((host) => host !== "0.0.0.0")) {
53
+ if (config.role === "gateway" && container && (config.management_lan !== true || [config.mcp_hostname, config.device_hostname, config.management_hostname].some((host) => host !== "0.0.0.0"))) {
54
54
  throw new CliError2("config_exists");
55
55
  }
56
56
  return config;
@@ -59,4 +59,4 @@ export {
59
59
  initializeRoleConfig
60
60
  };
61
61
 
62
- //# debugId=130364AF0AAC3C8064756E2164756E21
62
+ //# debugId=5FE0BCD7E52AF87B64756E2164756E21
@@ -22,7 +22,7 @@ import {
22
22
  SERVICE_ERROR_CODES,
23
23
  FacadeServiceError2,
24
24
  NativeRequestNotDispatchedError
25
- } from "./chunk-smpevv7n.js";
25
+ } from "./chunk-0dqx2mmz.js";
26
26
  import {
27
27
  LuvusAdapterError2,
28
28
  terminalExecutionCatalog
@@ -14,8 +14,11 @@ import {
14
14
  assertUsage,
15
15
  GATEWAY_LOCK_FORMAT2,
16
16
  Store2
17
- } from "./chunk-nyn75b8v.js";
17
+ } from "./chunk-qjh9x872.js";
18
18
  import"./chunk-09f9q26d.js";
19
+ import {
20
+ cliMessages2
21
+ } from "./chunk-5b8g62kw.js";
19
22
  import {
20
23
  readRuntimeConfig2
21
24
  } from "./chunk-bspzg8er.js";
@@ -131,17 +134,6 @@ function inspectStorage(input) {
131
134
  }
132
135
 
133
136
  // src/cli/storage-command.ts
134
- var STORAGE_HELP = `\u7528\u6CD5\uFF1A
135
- rovloom doctor --role gateway|connector [--config /absolute/config.json] [--json]
136
- rovloom storage check --role gateway [--config /absolute/config.json] [--json]
137
- rovloom storage backup --role gateway --output /path/to/gateway.backups/snapshot.db [--config /absolute/config.json] [--json]
138
- rovloom storage resume --role gateway [--config /absolute/config.json] [--json]
139
-
140
- Gateway \u547D\u4EE4\u987B\u5148\u505C\u6B62\u670D\u52A1\uFF1B\u6CBF\u7528\u540C\u4E00\u5199\u9501\uFF0C\u62D2\u7EDD\u6D3B\u52A8\u6216\u65E0\u6CD5\u5224\u5B9A\u7684\u6301\u6709\u8005\u3002
141
- check \u53EA\u8BFB\uFF1Bbackup \u4EC5\u4F7F\u7528\u771F\u5B9E\u72B6\u6001\u76EE\u5F55\u540C\u7EA7\u7684 <state>.backups \u666E\u901A\u76EE\u5F55\uFF0C\u5BFC\u51FA\u8131\u654F\u5FEB\u7167\uFF08\u4E0D\u542B\u539F\u6587\u53CA\u6709\u6548\u51ED\u636E\uFF09\uFF0C\u5B8C\u6574\u72B6\u6001\u9700\u53E6\u884C\u79BB\u7EBF\u5907\u4EFD\u3002
142
- resume \u662F\u672C\u673A\u64CD\u4F5C\u5458\u663E\u5F0F\u6279\u51C6\u7684\u89E3\u9664\u964D\u7EA7\uFF0C\u5B8C\u6574\u6027\u3001\u65F6\u949F\u6216\u9884\u7B97\u4E0D\u6B63\u5E38\u65F6\u4ECD\u62D2\u7EDD\u3002
143
- Connector doctor \u53EA\u68C0\u67E5\u914D\u7F6E\u53CA managed \u72B6\u6001\uFF0C\u4E0D\u542F\u52A8 native\uFF0C\u4E5F\u4E0D\u58F0\u660E native \u5C31\u7EEA\u3002
144
- `;
145
137
  function parse(args) {
146
138
  const action = args[0] === "doctor" ? "doctor" : args[1];
147
139
  if (!["doctor", "check", "backup", "resume"].includes(action ?? "")) {
@@ -201,7 +193,7 @@ async function handleStorageCommand(args, io, environment) {
201
193
  let json = args.includes("--json");
202
194
  try {
203
195
  if (args.length === 2 && args[1] === "--help") {
204
- io.stderr.write(STORAGE_HELP);
196
+ io.stderr.write(cliMessages2(io.language)["help.storage"]);
205
197
  return 0;
206
198
  }
207
199
  const flags = parse(args);
@@ -318,4 +310,4 @@ export {
318
310
  handleStorageCommand
319
311
  };
320
312
 
321
- //# debugId=007190958BDB411E64756E2164756E21
313
+ //# debugId=2C436BD5D6042D5D64756E2164756E21
@@ -1636,6 +1636,35 @@ class Store2 {
1636
1636
  revoke(machine) {
1637
1637
  this.devices.revoke(machine);
1638
1638
  }
1639
+ deleteDevice(machine, actor) {
1640
+ this.transaction((now) => {
1641
+ this.devices.applyRevoke(machine, now);
1642
+ for (const table of ["pairing_claims", "enrollments", "admin_pairings", "providers", "calls", "machines"]) {
1643
+ this.db.prepare(`DELETE FROM ${table} WHERE machine_id=?`).run(machine);
1644
+ }
1645
+ this.audit("machine_deleted", actor, now, undefined, { machine_id: machine });
1646
+ }, false);
1647
+ }
1648
+ listPairings(offset = 0) {
1649
+ return this.db.prepare(`SELECT p.pairing_id,p.machine_id,m.name,
1650
+ CASE WHEN p.status='pending' AND p.expires<=? THEN 'expired' ELSE p.status END AS status,p.expires
1651
+ FROM admin_pairings p JOIN machines m ON m.machine_id=p.machine_id ORDER BY p.expires DESC,p.pairing_id LIMIT 51 OFFSET ?`).all(this.clock(), offset);
1652
+ }
1653
+ deletePairing(pairing, actor) {
1654
+ return this.transaction((now) => {
1655
+ const application = this.devices.pairingApplication(pairing);
1656
+ if (!application) {
1657
+ throw new GatewayError2("pairing_not_found");
1658
+ }
1659
+ const unfinished = this.db.prepare("SELECT claim_id FROM pairing_claims WHERE pairing_id=? AND status IN ('approved','delivered')").get(pairing);
1660
+ if (unfinished) {
1661
+ this.devices.applyRevoke(application.machine_id, now);
1662
+ }
1663
+ this.db.prepare("DELETE FROM admin_pairings WHERE pairing_id=?").run(pairing);
1664
+ this.audit("pairing_deleted", actor, now, undefined, { pairing_id: pairing, machine_id: application.machine_id });
1665
+ return unfinished ? application.machine_id : null;
1666
+ }, false);
1667
+ }
1639
1668
  defineProvider(binding) {
1640
1669
  validateProvider2(binding);
1641
1670
  return this.transaction((now) => {
@@ -2275,4 +2304,4 @@ class Store2 {
2275
2304
 
2276
2305
  export { DEFAULT_RETENTION2, configuredSnapshotDirectory, SCHEMA_VERSION, assertBudget, assertUsage, GATEWAY_LOCK_FORMAT2, Store2 };
2277
2306
 
2278
- //# debugId=14A43F12EAAA7BD364756E2164756E21
2307
+ //# debugId=B8B3ABA270E159D964756E2164756E21
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  // src/mcp/version.ts
3
3
  var MCP_REVISION2 = "2025-11-25";
4
- var PRODUCT_VERSION2 = "0.5.0";
4
+ var PRODUCT_VERSION2 = "0.6.0";
5
5
 
6
6
  export { MCP_REVISION2, PRODUCT_VERSION2 };
7
7
 
8
- //# debugId=1479A7639E360A6A64756E2164756E21
8
+ //# debugId=F89FEF5D3124887164756E2164756E21
@@ -3,8 +3,9 @@ import {
3
3
  HTTP_BODY_BYTES2,
4
4
  createHttpFacade2,
5
5
  startHttpFacade2
6
- } from "./chunk-9y36gntb.js";
7
- import"./chunk-smpevv7n.js";
6
+ } from "./chunk-9zkq0kc8.js";
7
+ import"./chunk-0dqx2mmz.js";
8
+ import"./chunk-5b8g62kw.js";
8
9
  import"./chunk-7crhmqn2.js";
9
10
  import"./chunk-d71r315c.js";
10
11
  export {
@@ -13,4 +14,4 @@ export {
13
14
  startHttpFacade2 as startHttpFacade
14
15
  };
15
16
 
16
- //# debugId=A0A48728336CC35C64756E2164756E21
17
+ //# debugId=7DE436763985B0CD64756E2164756E21
@@ -6,6 +6,10 @@ import {
6
6
  } from "./chunk-qt9m2kg2.js";
7
7
  import"./chunk-9tt13dm0.js";
8
8
  import"./chunk-g7pnjzkk.js";
9
+ import {
10
+ cliMessages2,
11
+ formatMessage2
12
+ } from "./chunk-5b8g62kw.js";
9
13
  import {
10
14
  setupFileStamp,
11
15
  writeSetupFile,
@@ -18,7 +22,7 @@ import {
18
22
  revokeCaller,
19
23
  summarize,
20
24
  isAdminPlaceholder
21
- } from "./chunk-ebm3kvnq.js";
25
+ } from "./chunk-wxqhscsw.js";
22
26
  import {
23
27
  resolveRoleConfigPath2
24
28
  } from "./chunk-1bf0wmgk.js";
@@ -35,21 +39,6 @@ import"./chunk-3nnahj0j.js";
35
39
  import"./chunk-0y5542k8.js";
36
40
 
37
41
  // src/cli/token-command.ts
38
- var TOKEN_HELP = `\u7528\u6CD5\uFF1A
39
- rovloom token list [--config /absolute/path/gateway.json]
40
- rovloom token create --principal ID --like EXISTING_ID [--ttl-days N]
41
- rovloom token renew --principal ID [--ttl-days N]
42
- rovloom token rotate --principal ID [--ttl-days N] [--grace-minutes M]
43
- rovloom token revoke --principal ID
44
- rovloom token permissions --principal ID --discard-response true|false
45
-
46
- \u4EE4\u724C\u6CE8\u518C\u8868\u4F4D\u4E8E Gateway \u72B6\u6001\u76EE\u5F55\uFF1BGateway \u6BCF\u6B21\u8BA4\u8BC1\u91CD\u8BFB\uFF0C\u4FEE\u6539\u7ACB\u5373\u751F\u6548\u3001\u65E0\u9700\u91CD\u542F\u3002
47
- create/rotate \u628A\u65B0\u4EE4\u724C\u539F\u503C\u53EA\u5199\u5230 stdout \u4E00\u6B21\uFF08\u6CE8\u518C\u8868\u53EA\u4FDD\u5B58 SHA-256 \u6458\u8981\uFF09\uFF1B\u5176\u4F59\u4FE1\u606F\u5199\u5230 stderr\u3002
48
- create \u7684\u65B0\u4E3B\u4F53\u6743\u9650\u514B\u9686\u81EA --like \u6307\u5B9A\u7684\u73B0\u6709\u4E3B\u4F53\uFF0C\u4E0D\u6269\u5927\u6743\u9650\u3002renew \u5EF6\u957F\u5230\u671F\u65F6\u95F4\u3001\u4EE4\u724C\u4E0D\u53D8\u3002
49
- rotate \u7B7E\u53D1\u65B0\u4EE4\u724C\uFF1B--grace-minutes \u5185\u65E7\u4EE4\u724C\u7EE7\u7EED\u6709\u6548\uFF08\u9ED8\u8BA4 0\uFF0C\u7ACB\u5373\u5931\u6548\uFF09\u3002revoke \u5220\u9664\u4E3B\u4F53\u3002
50
- permissions \u663E\u5F0F\u7BA1\u7406\u7ED3\u679C\u5220\u9664\u6743\u9650\uFF0C\u70ED\u751F\u6548\uFF1B\u9ED8\u8BA4\u5173\u95ED\u3002\u5220\u9664\u7ED3\u679C\u524D\u5E94\u5148\u8BFB\u53D6\u5E76\u4FDD\u5B58\u6240\u9700\u5185\u5BB9\u3002
51
- ttl \u9ED8\u8BA4 30 \u5929\uFF081-365\uFF09\u3002
52
- `;
53
42
  function parse(args) {
54
43
  const sub = args[1];
55
44
  if (!sub || !["list", "create", "renew", "rotate", "revoke", "permissions"].includes(sub)) {
@@ -129,7 +118,7 @@ function syncClientFile(stateDir, principal, token, issued, expires) {
129
118
  async function handleTokenCommand(args, io, environment, now = Date.now) {
130
119
  try {
131
120
  if (args.length === 2 && args[1] === "--help") {
132
- io.stderr.write(TOKEN_HELP);
121
+ io.stderr.write(cliMessages2(io.language)["help.token"]);
133
122
  return 0;
134
123
  }
135
124
  const flags = parse(args);
@@ -154,31 +143,38 @@ async function handleTokenCommand(args, io, environment, now = Date.now) {
154
143
  if (flags.sub === "create") {
155
144
  const made = createCaller(registry, flags.principal, flags.like, at, flags.days);
156
145
  next = made.registry;
157
- io.stderr.write("created " + flags.principal + " expires " + new Date(made.expires_at).toISOString() + `
158
- `);
146
+ io.stderr.write(formatMessage2(cliMessages2(io.language)["token.created"], {
147
+ principal: flags.principal,
148
+ expires: new Date(made.expires_at).toISOString()
149
+ }));
159
150
  io.stdout.write(made.token + `
160
151
  `);
161
152
  } else if (flags.sub === "renew") {
162
153
  const renewed = renewCaller(registry, flags.principal, at, flags.days);
163
154
  next = renewed.registry;
164
- io.stderr.write("renewed " + flags.principal + " expires " + new Date(renewed.expires_at).toISOString() + `
165
- `);
155
+ io.stderr.write(formatMessage2(cliMessages2(io.language)["token.renewed"], {
156
+ principal: flags.principal,
157
+ expires: new Date(renewed.expires_at).toISOString()
158
+ }));
166
159
  } else if (flags.sub === "rotate") {
167
160
  const rotated = rotateCaller(registry, flags.principal, at, { days: flags.days, graceMinutes: flags.grace });
168
161
  next = rotated.registry;
169
- io.stderr.write("rotated " + flags.principal + " expires " + new Date(rotated.expires_at).toISOString() + `
170
- `);
162
+ io.stderr.write(formatMessage2(cliMessages2(io.language)["token.rotated"], {
163
+ principal: flags.principal,
164
+ expires: new Date(rotated.expires_at).toISOString()
165
+ }));
171
166
  issued = rotated.token;
172
167
  io.stdout.write(rotated.token + `
173
168
  `);
174
169
  } else if (flags.sub === "permissions") {
175
170
  next = setDiscardPermission(registry, flags.principal, flags.discard);
176
- io.stderr.write("permissions " + flags.principal + " discard_response=" + String(flags.discard) + `
177
- `);
171
+ io.stderr.write(formatMessage2(cliMessages2(io.language)["token.permissions"], {
172
+ principal: flags.principal,
173
+ discard: String(flags.discard)
174
+ }));
178
175
  } else {
179
176
  next = revokeCaller(registry, flags.principal);
180
- io.stderr.write("revoked " + flags.principal + `
181
- `);
177
+ io.stderr.write(formatMessage2(cliMessages2(io.language)["token.revoked"], { principal: flags.principal }));
182
178
  }
183
179
  writeSetupFile(path, boundedJson2(next, REGISTRY_MAX_BYTES), true, stamp);
184
180
  if (flags.sub === "renew" || flags.sub === "rotate") {
@@ -201,4 +197,4 @@ export {
201
197
  handleTokenCommand
202
198
  };
203
199
 
204
- //# debugId=FA979FCCD381000964756E2164756E21
200
+ //# debugId=97EFCC7F7ABCF40164756E2164756E21
@@ -133,7 +133,10 @@ function parseRegistry(value, resource) {
133
133
  const digests = new Set;
134
134
  for (const input of source.callers) {
135
135
  const caller = object2(input);
136
- fields2(caller, ["principal", "token_sha256", "issued_at", "expires_at"], ["previous"]);
136
+ fields2(caller, ["principal", "token_sha256", "issued_at", "expires_at"], ["previous", "token", "scope"]);
137
+ if (caller.scope !== undefined && caller.scope !== "gateway" || caller.token !== undefined && (typeof caller.token !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(caller.token) || digestToken(caller.token) !== caller.token_sha256)) {
138
+ invalid();
139
+ }
137
140
  const principal = object2(caller.principal);
138
141
  fields2(principal, ["id", "policy"], ["permissions"]);
139
142
  if (principal.permissions !== undefined) {
@@ -190,7 +193,9 @@ function createCaller(registry, principal, like, now, days) {
190
193
  const expires_at = now + ttl(days);
191
194
  const entry = {
192
195
  principal: { ...structuredClone(template.principal), id: principal },
196
+ ...template.scope ? { scope: template.scope } : {},
193
197
  token_sha256: digestToken(token),
198
+ token,
194
199
  issued_at: now,
195
200
  expires_at
196
201
  };
@@ -223,7 +228,9 @@ function rotateCaller(registry, principal, now, options = {}) {
223
228
  const expires_at = now + ttl(options.days);
224
229
  const entry = {
225
230
  principal: old.principal,
231
+ ...old.scope ? { scope: old.scope } : {},
226
232
  token_sha256: digestToken(token),
233
+ token,
227
234
  issued_at: now,
228
235
  expires_at,
229
236
  ...grace > 0 ? { previous: { token_sha256: old.token_sha256, expires_at: Math.min(now + grace * 60000, old.expires_at) } } : {}
@@ -250,6 +257,22 @@ function summarize(registry, now) {
250
257
  rotating: entry.previous !== undefined && now < entry.previous.expires_at
251
258
  }));
252
259
  }
260
+ function createGatewayCaller(registry, principal, now, days = 365) {
261
+ if (!PRINCIPAL.test(principal) || registry.callers.some((entry) => entry.principal.id === principal) || registry.callers.length >= MAX_CALLERS) {
262
+ throw new CliError2("invalid_arguments");
263
+ }
264
+ const token = newToken();
265
+ const expires_at = now + ttl(days);
266
+ const entry = {
267
+ principal: { id: principal, policy: structuredClone(registry.local_policy) },
268
+ scope: "gateway",
269
+ token,
270
+ token_sha256: digestToken(token),
271
+ issued_at: now,
272
+ expires_at
273
+ };
274
+ return { registry: { ...registry, callers: [...registry.callers, entry] }, token, expires_at };
275
+ }
253
276
 
254
277
  // src/cli/admin-registry.ts
255
278
  var ADMIN_POLICY_REVISION = "rovloom_admin_v1";
@@ -351,6 +374,6 @@ function summarizeAdmins(management, now) {
351
374
  }));
352
375
  }
353
376
 
354
- export { setupFileStamp, writeSetupFile, readSetupJson, writeSetupJson, REGISTRY_MAX_BYTES, parseRegistry, createCaller, setDiscardPermission, renewCaller, rotateCaller, revokeCaller, summarize, DEFAULT_ADMIN_TTL_DAYS, emptyManagement, isAdminPlaceholder, issueAdmin, revokeAdmin, summarizeAdmins };
377
+ export { setupFileStamp, writeSetupFile, readSetupJson, writeSetupJson, REGISTRY_MAX_BYTES, digestToken, parseRegistry, createCaller, setDiscardPermission, renewCaller, rotateCaller, revokeCaller, summarize, createGatewayCaller, DEFAULT_ADMIN_TTL_DAYS, emptyManagement, isAdminPlaceholder, issueAdmin, revokeAdmin, summarizeAdmins };
355
378
 
356
- //# debugId=3023B85F5DE2326664756E2164756E21
379
+ //# debugId=69610EBBA61A8B4564756E2164756E21