buckyos 0.7.120 → 0.7.121

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 (43) hide show
  1. package/cli/README.md +24 -3
  2. package/cli/core/app.ts +28 -0
  3. package/cli/deno.json +2 -1
  4. package/cli/dist/cli.mjs +568 -77
  5. package/cli/dist/cli.mjs.map +1 -1
  6. package/cli/modules/provision.ts +690 -0
  7. package/cli/runtime/host.ts +19 -2
  8. package/cli/runtime/host_deno.ts +4 -0
  9. package/cli/runtime/host_node.ts +4 -0
  10. package/cli/version.ts +1 -1
  11. package/dist/browser.cjs +1 -1
  12. package/dist/browser.mjs +124 -124
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.mjs +124 -124
  15. package/dist/{ndm_proxy-c00bc561.mjs → ndm_proxy-8f547002.mjs} +113 -216
  16. package/dist/ndm_proxy-8f547002.mjs.map +1 -0
  17. package/dist/ndm_proxy-93a8869b.js +13 -0
  18. package/dist/ndm_proxy-93a8869b.js.map +1 -0
  19. package/dist/ndn_types-44c69036.js +2 -0
  20. package/dist/ndn_types-44c69036.js.map +1 -0
  21. package/dist/{ndn_types-f6c08d20.mjs → ndn_types-d768245f.mjs} +149 -39
  22. package/dist/ndn_types-d768245f.mjs.map +1 -0
  23. package/dist/node.cjs +1 -1
  24. package/dist/node.mjs +124 -124
  25. package/dist/provision.cjs +6 -6
  26. package/dist/provision.cjs.map +1 -1
  27. package/dist/provision.d.ts +2 -0
  28. package/dist/provision.d.ts.map +1 -1
  29. package/dist/provision.mjs +1084 -35
  30. package/dist/provision.mjs.map +1 -1
  31. package/dist/provision_activate.d.ts +146 -0
  32. package/dist/provision_activate.d.ts.map +1 -0
  33. package/dist/{tus_client-573066b3.mjs → tus_client-b1c35e8c.mjs} +2 -2
  34. package/dist/{tus_client-573066b3.mjs.map → tus_client-b1c35e8c.mjs.map} +1 -1
  35. package/dist/{tus_client-83ad0f4f.js → tus_client-d0798623.js} +2 -2
  36. package/dist/{tus_client-83ad0f4f.js.map → tus_client-d0798623.js.map} +1 -1
  37. package/package.json +1 -1
  38. package/dist/ndm_proxy-68354a89.js +0 -13
  39. package/dist/ndm_proxy-68354a89.js.map +0 -1
  40. package/dist/ndm_proxy-c00bc561.mjs.map +0 -1
  41. package/dist/ndn_types-859bbd48.js +0 -2
  42. package/dist/ndn_types-859bbd48.js.map +0 -1
  43. package/dist/ndn_types-f6c08d20.mjs.map +0 -1
package/cli/dist/cli.mjs CHANGED
@@ -3,6 +3,7 @@ import { fileURLToPath } from "node:url";
3
3
  import * as nodePath from "node:path";
4
4
  import { resolve as resolve$5, dirname as dirname$3 } from "node:path";
5
5
  import { BuckyOSSDK, RuntimeType, buckyos, namelib, VerifyHubClient, createAppInstanceId, parseSessionTokenClaims, ndn, ndm_proxy } from "buckyos/node";
6
+ import * as provisionSdk from "buckyos/provision";
6
7
  import { createHash } from "node:crypto";
7
8
  import { readFile, writeFile, readdir, stat, lstat, realpath, mkdtemp, rename, rm, mkdir, chmod, symlink, copyFile, open } from "node:fs/promises";
8
9
  import { createReadStream, createWriteStream } from "node:fs";
@@ -21,6 +22,7 @@ const EXIT_AUTH = 3;
21
22
  const EXIT_PERMISSION = 4;
22
23
  const EXIT_UNAVAILABLE = 5;
23
24
  const EXIT_OPERATION = 6;
25
+ const EXIT_PARTIAL = 7;
24
26
  const EXIT_TIMEOUT = 8;
25
27
  const EXIT_INTERNAL = 9;
26
28
  class ToolError extends Error {
@@ -511,13 +513,16 @@ function buildDistributionPolicy(options) {
511
513
  }
512
514
  for (const candidate of parsed.read)
513
515
  readPaths.add(resolveInputPath(candidate, cwd, path));
516
+ for (const candidate of parsed.readParents) {
517
+ readPaths.add(path.dirname(resolveInputPath(candidate, cwd, path)));
518
+ }
514
519
  for (const candidate of parsed.write)
515
520
  writePaths.add(resolveInputPath(candidate, cwd, path));
516
521
  for (const candidate of parsed.writeParents) {
517
522
  writePaths.add(path.dirname(resolveInputPath(candidate, cwd, path)));
518
523
  }
519
524
  const subprocesses = parsed.module === "pikg" && ["init", "build"].includes(parsed.verb ?? "") ? ["docker"] : [];
520
- const network = parsed.module !== void 0 && !["pikg", "command", "completion", "config"].includes(parsed.module);
525
+ const network = parsed.module !== void 0 && !["pikg", "command", "completion", "config", "provision"].includes(parsed.module);
521
526
  const allowedEnvironment = options.distribution === "developer" ? TOOL_ENVIRONMENT_NAMES.filter((name) => name !== "BUCKYOS_ROOT") : TOOL_ENVIRONMENT_NAMES;
522
527
  return Object.freeze({
523
528
  name: options.distribution === "system" ? "system-default" : "developer-default",
@@ -542,6 +547,7 @@ function resolveInputPath(value, cwd, path) {
542
547
  }
543
548
  function collectArgumentPaths(argv) {
544
549
  const read = [];
550
+ const readParents = [];
545
551
  const write = [];
546
552
  const writeParents = [];
547
553
  let module;
@@ -617,6 +623,14 @@ function collectArgumentPaths(argv) {
617
623
  write.push(value);
618
624
  else if (name === "file" && module === "system-config" && verb === "set-file") {
619
625
  read.push(value);
626
+ } else if (name === "root" && module === "provision") {
627
+ read.push(value);
628
+ if (verb === "activate")
629
+ write.push(value);
630
+ } else if (name === "owner-key-backup" && module === "provision") {
631
+ readParents.push(value);
632
+ if (verb === "activate")
633
+ writeParents.push(value);
620
634
  } else if (!valueOptions.has(name))
621
635
  continue;
622
636
  continue;
@@ -632,7 +646,7 @@ function collectArgumentPaths(argv) {
632
646
  writeParents.push(token);
633
647
  }
634
648
  }
635
- return { read, write, writeParents, module, verb };
649
+ return { read, readParents, write, writeParents, module, verb };
636
650
  }
637
651
  function policyView(host2) {
638
652
  return {
@@ -2480,7 +2494,7 @@ function replPrompt(config) {
2480
2494
  return `buckyos[${profile}|${zone}|${identity}]> `;
2481
2495
  }
2482
2496
  const EMPTY_INPUT$1 = { type: "object", properties: {}, additionalProperties: false };
2483
- const OBJECT_OUTPUT$7 = { type: "object", additionalProperties: true };
2497
+ const OBJECT_OUTPUT$8 = { type: "object", additionalProperties: true };
2484
2498
  function createAuthModule() {
2485
2499
  return {
2486
2500
  name: "auth",
@@ -2490,7 +2504,7 @@ function createAuthModule() {
2490
2504
  verb: "whoami",
2491
2505
  summary: "Show the effective principal and application identity",
2492
2506
  inputSchema: EMPTY_INPUT$1,
2493
- outputSchema: OBJECT_OUTPUT$7,
2507
+ outputSchema: OBJECT_OUTPUT$8,
2494
2508
  resultSchemaVersion: 1,
2495
2509
  access: { mode: "fixed", level: "read" },
2496
2510
  asyncMode: "sync",
@@ -2508,7 +2522,7 @@ function createAuthModule() {
2508
2522
  verb: "session-status",
2509
2523
  summary: "Show the in-memory session state without exposing credentials",
2510
2524
  inputSchema: EMPTY_INPUT$1,
2511
- outputSchema: OBJECT_OUTPUT$7,
2525
+ outputSchema: OBJECT_OUTPUT$8,
2512
2526
  resultSchemaVersion: 1,
2513
2527
  access: { mode: "fixed", level: "read" },
2514
2528
  asyncMode: "sync",
@@ -2529,7 +2543,7 @@ const EMPTY_INPUT = {
2529
2543
  properties: {},
2530
2544
  additionalProperties: false
2531
2545
  };
2532
- const OBJECT_OUTPUT$6 = { type: "object", additionalProperties: true };
2546
+ const OBJECT_OUTPUT$7 = { type: "object", additionalProperties: true };
2533
2547
  function createCoreModules(registry) {
2534
2548
  return [createCommandModule(registry), createConfigModule(), createCompletionModule(registry)];
2535
2549
  }
@@ -2542,7 +2556,7 @@ function createCommandModule(registry) {
2542
2556
  verb: "list",
2543
2557
  summary: "List registered modules and commands",
2544
2558
  inputSchema: EMPTY_INPUT,
2545
- outputSchema: OBJECT_OUTPUT$6,
2559
+ outputSchema: OBJECT_OUTPUT$7,
2546
2560
  resultSchemaVersion: 1,
2547
2561
  access: { mode: "fixed", level: "read" },
2548
2562
  asyncMode: "sync",
@@ -2575,7 +2589,7 @@ function createCommandModule(registry) {
2575
2589
  required: ["target_module", "target_verb"],
2576
2590
  additionalProperties: false
2577
2591
  },
2578
- outputSchema: OBJECT_OUTPUT$6,
2592
+ outputSchema: OBJECT_OUTPUT$7,
2579
2593
  resultSchemaVersion: 1,
2580
2594
  access: { mode: "fixed", level: "read" },
2581
2595
  asyncMode: "sync",
@@ -2597,7 +2611,7 @@ function createConfigModule() {
2597
2611
  verb: "list",
2598
2612
  summary: "List the global configuration and available profiles",
2599
2613
  inputSchema: EMPTY_INPUT,
2600
- outputSchema: OBJECT_OUTPUT$6,
2614
+ outputSchema: OBJECT_OUTPUT$7,
2601
2615
  resultSchemaVersion: 1,
2602
2616
  access: { mode: "fixed", level: "read" },
2603
2617
  asyncMode: "sync",
@@ -2628,7 +2642,7 @@ function createConfigModule() {
2628
2642
  },
2629
2643
  additionalProperties: false
2630
2644
  },
2631
- outputSchema: OBJECT_OUTPUT$6,
2645
+ outputSchema: OBJECT_OUTPUT$7,
2632
2646
  resultSchemaVersion: 1,
2633
2647
  access: { mode: "fixed", level: "read" },
2634
2648
  asyncMode: "sync",
@@ -2638,11 +2652,11 @@ function createConfigModule() {
2638
2652
  "buckyos config get zone --profile-name production"
2639
2653
  ],
2640
2654
  handler: async (ctx, input) => {
2641
- const profileName = optionalString$3(input.profile_name);
2655
+ const profileName = optionalString$4(input.profile_name);
2642
2656
  const value = profileName ? await ctx.configStore.readProfile(profileName) : await ctx.configStore.readConfig();
2643
2657
  if (!value)
2644
2658
  throw new UsageError("PROFILE_NOT_FOUND", `profile not found: ${profileName}`);
2645
- const key = optionalString$3(input.key);
2659
+ const key = optionalString$4(input.key);
2646
2660
  if (!key)
2647
2661
  return { value };
2648
2662
  if (!Object.hasOwn(value, key)) {
@@ -2674,7 +2688,7 @@ function createConfigModule() {
2674
2688
  required: ["key", "value"],
2675
2689
  additionalProperties: false
2676
2690
  },
2677
- outputSchema: OBJECT_OUTPUT$6,
2691
+ outputSchema: OBJECT_OUTPUT$7,
2678
2692
  resultSchemaVersion: 1,
2679
2693
  access: { mode: "fixed", level: "write" },
2680
2694
  asyncMode: "sync",
@@ -2686,7 +2700,7 @@ function createConfigModule() {
2686
2700
  handler: async (ctx, input) => {
2687
2701
  const key = String(input.key);
2688
2702
  const rawValue = String(input.value);
2689
- const profileName = optionalString$3(input.profile_name);
2703
+ const profileName = optionalString$4(input.profile_name);
2690
2704
  if (profileName) {
2691
2705
  validateProfileName(profileName);
2692
2706
  const profile = await ctx.configStore.readProfile(profileName) ?? { schema_version: 1 };
@@ -2714,7 +2728,7 @@ function createConfigModule() {
2714
2728
  required: ["profile_name"],
2715
2729
  additionalProperties: false
2716
2730
  },
2717
- outputSchema: OBJECT_OUTPUT$6,
2731
+ outputSchema: OBJECT_OUTPUT$7,
2718
2732
  resultSchemaVersion: 1,
2719
2733
  access: { mode: "fixed", level: "write" },
2720
2734
  asyncMode: "sync",
@@ -2746,7 +2760,7 @@ function createConfigModule() {
2746
2760
  properties: { effective: { type: "boolean" } },
2747
2761
  additionalProperties: false
2748
2762
  },
2749
- outputSchema: OBJECT_OUTPUT$6,
2763
+ outputSchema: OBJECT_OUTPUT$7,
2750
2764
  resultSchemaVersion: 1,
2751
2765
  access: { mode: "fixed", level: "read" },
2752
2766
  asyncMode: "sync",
@@ -2832,7 +2846,7 @@ function outputValue(value) {
2832
2846
  }
2833
2847
  return value;
2834
2848
  }
2835
- function optionalString$3(value) {
2849
+ function optionalString$4(value) {
2836
2850
  return typeof value === "string" && value ? value : void 0;
2837
2851
  }
2838
2852
  function completionScript(registry, shell) {
@@ -2891,7 +2905,7 @@ function createSystemModule() {
2891
2905
  };
2892
2906
  }
2893
2907
  const SERVICE_NAME = "system_config";
2894
- const OBJECT_OUTPUT$5 = { type: "object", additionalProperties: false };
2908
+ const OBJECT_OUTPUT$6 = { type: "object", additionalProperties: false };
2895
2909
  const KEY_INPUT = {
2896
2910
  type: "object",
2897
2911
  properties: { key: { type: "string", minLength: 1 } },
@@ -2909,7 +2923,7 @@ function createSystemConfigModule() {
2909
2923
  positionals: [{ name: "key", description: "System-config key" }],
2910
2924
  inputSchema: KEY_INPUT,
2911
2925
  outputSchema: {
2912
- ...OBJECT_OUTPUT$5,
2926
+ ...OBJECT_OUTPUT$6,
2913
2927
  properties: {
2914
2928
  key: { type: "string" },
2915
2929
  value: { type: "string" },
@@ -2952,7 +2966,7 @@ function createSystemConfigModule() {
2952
2966
  additionalProperties: false
2953
2967
  },
2954
2968
  outputSchema: {
2955
- ...OBJECT_OUTPUT$5,
2969
+ ...OBJECT_OUTPUT$6,
2956
2970
  properties: {
2957
2971
  key: { type: "string" },
2958
2972
  items: { type: "array", items: { type: "string" } }
@@ -3006,7 +3020,7 @@ function setCommand() {
3006
3020
  additionalProperties: false
3007
3021
  },
3008
3022
  outputSchema: {
3009
- ...OBJECT_OUTPUT$5,
3023
+ ...OBJECT_OUTPUT$6,
3010
3024
  properties: { key: { type: "string" }, updated: { type: "boolean" } },
3011
3025
  required: ["key", "updated"]
3012
3026
  },
@@ -3045,7 +3059,7 @@ function setFileCommand() {
3045
3059
  additionalProperties: false
3046
3060
  },
3047
3061
  outputSchema: {
3048
- ...OBJECT_OUTPUT$5,
3062
+ ...OBJECT_OUTPUT$6,
3049
3063
  properties: { key: { type: "string" }, updated: { type: "boolean" } },
3050
3064
  required: ["key", "updated"]
3051
3065
  },
@@ -3082,7 +3096,7 @@ function mutationCommand(options) {
3082
3096
  additionalProperties: false
3083
3097
  },
3084
3098
  outputSchema: {
3085
- ...OBJECT_OUTPUT$5,
3099
+ ...OBJECT_OUTPUT$6,
3086
3100
  properties: {
3087
3101
  key: { type: "string" },
3088
3102
  [options.resultProperty]: { type: "boolean" }
@@ -4130,7 +4144,7 @@ function validateServiceConfigTips(value, label) {
4130
4144
  } else {
4131
4145
  throw invalid("schema", `${label}.service_endpoints.${name}.expose.route.type is invalid`);
4132
4146
  }
4133
- optionalString$2(expose.scope, `${label}.service_endpoints.${name}.expose.scope`);
4147
+ optionalString$3(expose.scope, `${label}.service_endpoints.${name}.expose.scope`);
4134
4148
  optionalBoolean(
4135
4149
  expose.allow_guest,
4136
4150
  `${label}.service_endpoints.${name}.expose.allow_guest`
@@ -4184,7 +4198,7 @@ function validateServiceConfigTips(value, label) {
4184
4198
  throw invalid("schema", `${label}.rdb_instances.${name}.schema.${backend} is invalid`);
4185
4199
  }
4186
4200
  }
4187
- optionalString$2(database.connection, `${label}.rdb_instances.${name}.connection`);
4201
+ optionalString$3(database.connection, `${label}.rdb_instances.${name}.connection`);
4188
4202
  }
4189
4203
  if (config.instance_volume !== void 0) {
4190
4204
  const volume = expectObject$3(config.instance_volume, `${label}.instance_volume`);
@@ -4212,8 +4226,8 @@ function validateServiceConfigTips(value, label) {
4212
4226
  validateStringMap(environment2.description ?? {}, `${label}.bash_envs.${name}.description`);
4213
4227
  }
4214
4228
  validateStringMap(config.runtime_caps ?? {}, `${label}.runtime_caps`);
4215
- optionalString$2(config.container_param, `${label}.container_param`);
4216
- optionalString$2(config.start_param, `${label}.start_param`);
4229
+ optionalString$3(config.container_param, `${label}.container_param`);
4230
+ optionalString$3(config.start_param, `${label}.start_param`);
4217
4231
  return config;
4218
4232
  }
4219
4233
  function appDocObjectId(value) {
@@ -4607,7 +4621,7 @@ function validateAppDocShape(appDoc) {
4607
4621
  }
4608
4622
  if (appDoc.name !== void 0)
4609
4623
  expectNonEmptyString(appDoc.name, "APPDOC.name");
4610
- optionalString$2(appDoc.copyright, "APPDOC.copyright");
4624
+ optionalString$3(appDoc.copyright, "APPDOC.copyright");
4611
4625
  for (const field of ["tags", "categories"]) {
4612
4626
  const values = appDoc[field];
4613
4627
  if (values !== void 0 && (!Array.isArray(values) || values.length === 0 || values.some((value) => typeof value !== "string"))) {
@@ -4817,7 +4831,7 @@ function optionalBoolean(value, label) {
4817
4831
  throw invalid("schema", `${label} must be boolean`);
4818
4832
  }
4819
4833
  }
4820
- function optionalString$2(value, label) {
4834
+ function optionalString$3(value, label) {
4821
4835
  if (value !== void 0 && typeof value !== "string") {
4822
4836
  throw invalid("schema", `${label} must be a string`);
4823
4837
  }
@@ -4851,7 +4865,7 @@ function invalid(stage, message, entry) {
4851
4865
  function stableJsonDigest(value) {
4852
4866
  return sha256Bytes(new TextEncoder().encode(ndn.toCanonicalJsonString(value)));
4853
4867
  }
4854
- const PACKAGE_VERSION = "0.7.120";
4868
+ const PACKAGE_VERSION = "0.7.121";
4855
4869
  const TOOL_VERSION = PACKAGE_VERSION;
4856
4870
  const SDK_VERSION = PACKAGE_VERSION;
4857
4871
  const PROTOCOL_VERSION = "1";
@@ -4868,7 +4882,7 @@ const VERSION$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
4868
4882
  const SHA256_ID = /^sha256:[0-9a-f]{64}$/;
4869
4883
  const OBJECT_ID = /^(?:appdoc|pkg):[0-9a-f]{64}$/;
4870
4884
  const SAFE_GENERATED_FILE = /^[A-Za-z0-9._-]+$/;
4871
- const OBJECT_OUTPUT$4 = { type: "object", additionalProperties: true };
4885
+ const OBJECT_OUTPUT$5 = { type: "object", additionalProperties: true };
4872
4886
  function packageEnvironmentQualifier(key, selector) {
4873
4887
  const effective = selector ?? derivedSelector(key);
4874
4888
  const os = effective?.os;
@@ -4905,7 +4919,7 @@ function createPikgModule(dependencies = {}) {
4905
4919
  properties: { meta_dir: { type: "string", minLength: 1 } },
4906
4920
  additionalProperties: false
4907
4921
  },
4908
- outputSchema: OBJECT_OUTPUT$4,
4922
+ outputSchema: OBJECT_OUTPUT$5,
4909
4923
  resultSchemaVersion: 1,
4910
4924
  access: { mode: "fixed", level: "read" },
4911
4925
  asyncMode: "sync",
@@ -4952,7 +4966,7 @@ function createPikgModule(dependencies = {}) {
4952
4966
  },
4953
4967
  additionalProperties: false
4954
4968
  },
4955
- outputSchema: OBJECT_OUTPUT$4,
4969
+ outputSchema: OBJECT_OUTPUT$5,
4956
4970
  resultSchemaVersion: 1,
4957
4971
  access: { mode: "fixed", level: "write" },
4958
4972
  asyncMode: "sync",
@@ -4976,7 +4990,7 @@ function createPikgModule(dependencies = {}) {
4976
4990
  properties: { meta_dir: { type: "string", minLength: 1 } },
4977
4991
  additionalProperties: false
4978
4992
  },
4979
- outputSchema: OBJECT_OUTPUT$4,
4993
+ outputSchema: OBJECT_OUTPUT$5,
4980
4994
  resultSchemaVersion: 1,
4981
4995
  access: { mode: "fixed", level: "write" },
4982
4996
  asyncMode: "sync",
@@ -4997,7 +5011,7 @@ function createPikgModule(dependencies = {}) {
4997
5011
  properties: { dist_dir: { type: "string", minLength: 1 } },
4998
5012
  additionalProperties: false
4999
5013
  },
5000
- outputSchema: OBJECT_OUTPUT$4,
5014
+ outputSchema: OBJECT_OUTPUT$5,
5001
5015
  resultSchemaVersion: 1,
5002
5016
  access: { mode: "fixed", level: "write" },
5003
5017
  asyncMode: "sync",
@@ -5017,7 +5031,7 @@ function createPikgModule(dependencies = {}) {
5017
5031
  required: ["pikg_path"],
5018
5032
  additionalProperties: false
5019
5033
  },
5020
- outputSchema: OBJECT_OUTPUT$4,
5034
+ outputSchema: OBJECT_OUTPUT$5,
5021
5035
  resultSchemaVersion: 1,
5022
5036
  access: { mode: "fixed", level: "read" },
5023
5037
  asyncMode: "sync",
@@ -5038,7 +5052,7 @@ function createPikgModule(dependencies = {}) {
5038
5052
  properties: { meta_dir: { type: "string", minLength: 1 } },
5039
5053
  additionalProperties: false
5040
5054
  },
5041
- outputSchema: OBJECT_OUTPUT$4,
5055
+ outputSchema: OBJECT_OUTPUT$5,
5042
5056
  resultSchemaVersion: 1,
5043
5057
  access: { mode: "fixed", level: "destructive" },
5044
5058
  asyncMode: "sync",
@@ -6229,16 +6243,16 @@ async function observeTask(ctx, taskId) {
6229
6243
  const envelope = expectObject$2(response, "TaskManager get_task response");
6230
6244
  const task = expectObject$2(envelope.task ?? envelope, "TaskManager task");
6231
6245
  const phase = expectString$2(task.phase, "task.phase");
6232
- const outcome = optionalString$1(task.outcome);
6246
+ const outcome = optionalString$2(task.outcome);
6233
6247
  const taskError = isObject$1(task.error) ? task.error : void 0;
6234
6248
  return {
6235
6249
  revision: typeof task.revision === "number" ? task.revision : void 0,
6236
6250
  phase,
6237
6251
  outcome,
6238
- message: optionalString$1(task.message),
6252
+ message: optionalString$2(task.message),
6239
6253
  error: taskError ? {
6240
- code: optionalString$1(taskError.code),
6241
- message: optionalString$1(taskError.message),
6254
+ code: optionalString$2(taskError.code),
6255
+ message: optionalString$2(taskError.message),
6242
6256
  retryable: typeof taskError.retryable === "boolean" ? taskError.retryable : void 0,
6243
6257
  details: isObject$1(taskError.detail) ? taskError.detail : void 0
6244
6258
  } : void 0,
@@ -6258,7 +6272,7 @@ function normalizeTaskErrorCode(code, outcome) {
6258
6272
  return code.trim().replaceAll(/[^A-Za-z0-9]+/g, "_").toUpperCase();
6259
6273
  return outcome === "Canceled" ? "CANCELED" : "TASK_FAILED";
6260
6274
  }
6261
- function optionalString$1(value) {
6275
+ function optionalString$2(value) {
6262
6276
  return typeof value === "string" ? value : void 0;
6263
6277
  }
6264
6278
  function expectString$2(value, label) {
@@ -6298,7 +6312,7 @@ const CONTROL_PANEL_SERVICE = "control-panel";
6298
6312
  const PLAN_SCHEMA_VERSION = 4;
6299
6313
  const STAGING_RELEASE_TIMEOUT_MS = 5e3;
6300
6314
  const ZIP_LOCAL_MAGIC = [80, 75, 3, 4];
6301
- const OBJECT_OUTPUT$3 = { type: "object", additionalProperties: true };
6315
+ const OBJECT_OUTPUT$4 = { type: "object", additionalProperties: true };
6302
6316
  const INSTALL_POLICIES = [
6303
6317
  "strict-public",
6304
6318
  "normal",
@@ -6317,7 +6331,7 @@ function createAppModule(dependencies = {}) {
6317
6331
  lifecycleCommand("start", "Start an installed App"),
6318
6332
  lifecycleCommand("stop", "Stop an installed App"),
6319
6333
  restartCommand(),
6320
- statusCommand()
6334
+ statusCommand$1()
6321
6335
  ];
6322
6336
  return {
6323
6337
  name: "app",
@@ -6354,7 +6368,7 @@ function fetchCommand(dependencies) {
6354
6368
  target: { type: "object", additionalProperties: true },
6355
6369
  install_params: { type: "object", additionalProperties: true }
6356
6370
  }),
6357
- outputSchema: OBJECT_OUTPUT$3,
6371
+ outputSchema: OBJECT_OUTPUT$4,
6358
6372
  resultSchemaVersion: 1,
6359
6373
  access: { mode: "fixed", level: "read" },
6360
6374
  asyncMode: "sync",
@@ -6371,7 +6385,7 @@ function listCommand$1() {
6371
6385
  verb: "list",
6372
6386
  summary: "List visible installed Apps",
6373
6387
  inputSchema: emptyInputSchema(),
6374
- outputSchema: OBJECT_OUTPUT$3,
6388
+ outputSchema: OBJECT_OUTPUT$4,
6375
6389
  resultSchemaVersion: 1,
6376
6390
  access: { mode: "fixed", level: "read" },
6377
6391
  asyncMode: "sync",
@@ -6429,7 +6443,7 @@ function installCommand(dependencies) {
6429
6443
  no_wait: { type: "boolean" },
6430
6444
  policy: { type: "string", enum: [...INSTALL_POLICIES] }
6431
6445
  }),
6432
- outputSchema: OBJECT_OUTPUT$3,
6446
+ outputSchema: OBJECT_OUTPUT$4,
6433
6447
  resultSchemaVersion: 1,
6434
6448
  access: { mode: "fixed", level: "write" },
6435
6449
  asyncMode: "either",
@@ -6473,7 +6487,7 @@ function upgradeCommand(dependencies) {
6473
6487
  },
6474
6488
  additionalProperties: false
6475
6489
  },
6476
- outputSchema: OBJECT_OUTPUT$3,
6490
+ outputSchema: OBJECT_OUTPUT$4,
6477
6491
  resultSchemaVersion: 1,
6478
6492
  access: { mode: "fixed", level: "write" },
6479
6493
  asyncMode: "either",
@@ -6590,7 +6604,7 @@ function restartCommand() {
6590
6604
  examples: ["buckyos app restart app1"]
6591
6605
  };
6592
6606
  }
6593
- function statusCommand() {
6607
+ function statusCommand$1() {
6594
6608
  return {
6595
6609
  verb: "status",
6596
6610
  summary: "Show desired, task, scheduled, runtime, version, and readiness state",
@@ -6602,7 +6616,7 @@ function statusCommand() {
6602
6616
  properties: { app_name: { type: "string", minLength: 1 } },
6603
6617
  additionalProperties: false
6604
6618
  },
6605
- outputSchema: OBJECT_OUTPUT$3,
6619
+ outputSchema: OBJECT_OUTPUT$4,
6606
6620
  resultSchemaVersion: 1,
6607
6621
  access: { mode: "fixed", level: "read" },
6608
6622
  asyncMode: "sync",
@@ -6643,7 +6657,7 @@ async function fetchApp(ctx, input, dependencies) {
6643
6657
  const source = await prepareSource(ctx, input, "inspect", dependencies);
6644
6658
  try {
6645
6659
  let inspection = await inspectSource(ctx, source, input);
6646
- const planPathInput = optionalString(input.plan);
6660
+ const planPathInput = optionalString$1(input.plan);
6647
6661
  let planPath;
6648
6662
  if (planPathInput) {
6649
6663
  inspection = await finalizePlanChoices(ctx, source, input, inspection);
@@ -6667,7 +6681,7 @@ async function fetchApp(ctx, input, dependencies) {
6667
6681
  }
6668
6682
  async function installApp(ctx, input, dependencies) {
6669
6683
  rejectDryRunNoWait(input);
6670
- const submittedPlan = optionalString(input.plan) ? await readPlanFile(resolveFromCwd(ctx, String(input.plan))) : void 0;
6684
+ const submittedPlan = optionalString$1(input.plan) ? await readPlanFile(resolveFromCwd(ctx, String(input.plan))) : void 0;
6671
6685
  const source = await prepareSource(ctx, input, "install", dependencies);
6672
6686
  let keepStaging = false;
6673
6687
  try {
@@ -6931,15 +6945,15 @@ async function prepareSource(ctx, input, purpose, dependencies) {
6931
6945
  }
6932
6946
  }
6933
6947
  async function classifySource(ctx, input) {
6934
- const positional = optionalString(input.source);
6935
- const pikg = optionalString(input.pikg);
6948
+ const positional = optionalString$1(input.source);
6949
+ const pikg = optionalString$1(input.pikg);
6936
6950
  if (positional && pikg) {
6937
6951
  throw new UsageError("ARGUMENT_CONFLICT", "<source> and --pikg are mutually exclusive");
6938
6952
  }
6939
6953
  const raw = pikg ?? positional;
6940
6954
  if (!raw)
6941
6955
  throw new UsageError("MISSING_ARGUMENT", "source or --pikg is required");
6942
- const forced = pikg ? "pikg" : optionalString(input.from);
6956
+ const forced = pikg ? "pikg" : optionalString$1(input.from);
6943
6957
  if (pikg && forced && forced !== "pikg") {
6944
6958
  throw new UsageError("ARGUMENT_CONFLICT", "--pikg conflicts with --from");
6945
6959
  }
@@ -7260,11 +7274,11 @@ async function observeInstallTask(ctx, taskId) {
7260
7274
  const sanitizedDetails = error && isObject(error.details) ? sanitizeAppOutput(error.details) : void 0;
7261
7275
  return {
7262
7276
  phase: expectString$1(status, "task_phase"),
7263
- outcome: optionalString(status.task_outcome),
7277
+ outcome: optionalString$1(status.task_outcome),
7264
7278
  message: installProgressMessage(status),
7265
7279
  error: error ? {
7266
- code: optionalString(error.code),
7267
- message: optionalString(error.message),
7280
+ code: optionalString$1(error.code),
7281
+ message: optionalString$1(error.message),
7268
7282
  retryable: typeof error.retryable === "boolean" ? error.retryable : void 0,
7269
7283
  details: isObject(sanitizedDetails) ? sanitizedDetails : void 0
7270
7284
  } : void 0,
@@ -7362,7 +7376,7 @@ function installedScope(details) {
7362
7376
  };
7363
7377
  }
7364
7378
  function installOptions(input) {
7365
- const policy2 = optionalString(input.policy) ?? "normal";
7379
+ const policy2 = optionalString$1(input.policy) ?? "normal";
7366
7380
  return { policy: policy2.replaceAll("-", "_").toUpperCase() };
7367
7381
  }
7368
7382
  function sourceSummary(source) {
@@ -7686,13 +7700,13 @@ function parseEmbeddedJson(message) {
7686
7700
  }
7687
7701
  function readinessValue(inspection, field) {
7688
7702
  const readiness = isObject(inspection.status.readiness) ? inspection.status.readiness : void 0;
7689
- return readiness ? optionalString(readiness[field]) : void 0;
7703
+ return readiness ? optionalString$1(readiness[field]) : void 0;
7690
7704
  }
7691
7705
  function planUse(plan) {
7692
- return optionalString(plan.plan_use);
7706
+ return optionalString$1(plan.plan_use);
7693
7707
  }
7694
7708
  function installProgressMessage(status) {
7695
- const stage = optionalString(status.stage);
7709
+ const stage = optionalString$1(status.stage);
7696
7710
  const progress = isObject(status.progress) ? status.progress : void 0;
7697
7711
  const percent = progress && typeof progress.percent === "number" ? `${progress.percent}%` : void 0;
7698
7712
  return [stage, percent].filter(Boolean).join(" ") || void 0;
@@ -7716,7 +7730,7 @@ function selectorCommand(options) {
7716
7730
  required: ["app_name"],
7717
7731
  additionalProperties: false
7718
7732
  },
7719
- outputSchema: OBJECT_OUTPUT$3,
7733
+ outputSchema: OBJECT_OUTPUT$4,
7720
7734
  resultSchemaVersion: 1,
7721
7735
  access: { mode: "fixed", level: options.access },
7722
7736
  asyncMode: options.asyncMode,
@@ -7798,7 +7812,7 @@ function expectNumber(object, property) {
7798
7812
  }
7799
7813
  return value;
7800
7814
  }
7801
- function optionalString(value) {
7815
+ function optionalString$1(value) {
7802
7816
  return typeof value === "string" && value.trim() ? value : void 0;
7803
7817
  }
7804
7818
  function optionalNumber(value) {
@@ -7943,7 +7957,7 @@ function splitServices(value) {
7943
7957
  return [...new Set(items.map((item) => String(item).trim()).filter(Boolean))];
7944
7958
  }
7945
7959
  const CONTROL_PANEL$2 = "control-panel";
7946
- const OBJECT_OUTPUT$2 = { type: "object", additionalProperties: true };
7960
+ const OBJECT_OUTPUT$3 = { type: "object", additionalProperties: true };
7947
7961
  function createDiagnosticModule(dependencies = {}) {
7948
7962
  return {
7949
7963
  name: "diagnostic",
@@ -7982,7 +7996,7 @@ function collectCommand() {
7982
7996
  required: ["services"],
7983
7997
  additionalProperties: false
7984
7998
  },
7985
- outputSchema: OBJECT_OUTPUT$2,
7999
+ outputSchema: OBJECT_OUTPUT$3,
7986
8000
  resultSchemaVersion: 1,
7987
8001
  access: { mode: "fixed", level: "privileged" },
7988
8002
  asyncMode: "task",
@@ -8036,7 +8050,7 @@ function exportCommand$1(dependencies) {
8036
8050
  required: ["bundle_id", "path"],
8037
8051
  additionalProperties: false
8038
8052
  },
8039
- outputSchema: OBJECT_OUTPUT$2,
8053
+ outputSchema: OBJECT_OUTPUT$3,
8040
8054
  resultSchemaVersion: 1,
8041
8055
  access: { mode: "fixed", level: "privileged" },
8042
8056
  asyncMode: "sync",
@@ -8078,7 +8092,7 @@ function compact$2(value) {
8078
8092
  return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
8079
8093
  }
8080
8094
  const CONTROL_PANEL$1 = "control-panel";
8081
- const OBJECT_OUTPUT$1 = { type: "object", additionalProperties: true };
8095
+ const OBJECT_OUTPUT$2 = { type: "object", additionalProperties: true };
8082
8096
  function createLogModule(dependencies = {}) {
8083
8097
  return {
8084
8098
  name: "log",
@@ -8139,7 +8153,7 @@ function tailCommand(dependencies) {
8139
8153
  }
8140
8154
  ],
8141
8155
  inputSchema: filterSchema({ from: { type: "string", enum: ["start", "end"] } }),
8142
- outputSchema: OBJECT_OUTPUT$1,
8156
+ outputSchema: OBJECT_OUTPUT$2,
8143
8157
  resultSchemaVersion: 1,
8144
8158
  access: { mode: "fixed", level: "read" },
8145
8159
  asyncMode: "stream",
@@ -8195,7 +8209,7 @@ function exportCommand(dependencies) {
8195
8209
  ...filterSchema({ path: { type: "string", minLength: 1 } }),
8196
8210
  required: ["path"]
8197
8211
  },
8198
- outputSchema: OBJECT_OUTPUT$1,
8212
+ outputSchema: OBJECT_OUTPUT$2,
8199
8213
  resultSchemaVersion: 1,
8200
8214
  access: { mode: "fixed", level: "read" },
8201
8215
  asyncMode: "sync",
@@ -8331,7 +8345,7 @@ function abortableSleep(milliseconds, signal) {
8331
8345
  }
8332
8346
  const TASK_MANAGER = "task-manager";
8333
8347
  const CONTROL_PANEL = "control-panel";
8334
- const OBJECT_OUTPUT = { type: "object", additionalProperties: true };
8348
+ const OBJECT_OUTPUT$1 = { type: "object", additionalProperties: true };
8335
8349
  function createTaskModule() {
8336
8350
  return {
8337
8351
  name: "task",
@@ -8434,7 +8448,7 @@ function getCommand() {
8434
8448
  required: ["task_id"],
8435
8449
  additionalProperties: false
8436
8450
  },
8437
- outputSchema: OBJECT_OUTPUT,
8451
+ outputSchema: OBJECT_OUTPUT$1,
8438
8452
  resultSchemaVersion: 1,
8439
8453
  access: { mode: "fixed", level: "read" },
8440
8454
  asyncMode: "sync",
@@ -8475,7 +8489,7 @@ function waitCommand() {
8475
8489
  summary: "Stream changes until a Task becomes terminal",
8476
8490
  positionals: [{ name: "task_id", description: "Opaque Task ID", required: true }],
8477
8491
  inputSchema: taskIdSchema(),
8478
- outputSchema: OBJECT_OUTPUT,
8492
+ outputSchema: OBJECT_OUTPUT$1,
8479
8493
  resultSchemaVersion: 1,
8480
8494
  access: { mode: "fixed", level: "read" },
8481
8495
  asyncMode: "stream",
@@ -8526,7 +8540,7 @@ function cancelCommand() {
8526
8540
  required: ["task_id"],
8527
8541
  additionalProperties: false
8528
8542
  },
8529
- outputSchema: OBJECT_OUTPUT,
8543
+ outputSchema: OBJECT_OUTPUT$1,
8530
8544
  resultSchemaVersion: 1,
8531
8545
  access: { mode: "fixed", level: "write" },
8532
8546
  asyncMode: "sync",
@@ -8569,7 +8583,7 @@ function retryCommand() {
8569
8583
  required: ["task_id"],
8570
8584
  additionalProperties: false
8571
8585
  },
8572
- outputSchema: OBJECT_OUTPUT,
8586
+ outputSchema: OBJECT_OUTPUT$1,
8573
8587
  resultSchemaVersion: 1,
8574
8588
  access: { mode: "fixed", level: "write" },
8575
8589
  asyncMode: "either",
@@ -8642,6 +8656,459 @@ function compact(value) {
8642
8656
  function invalidResponse(label) {
8643
8657
  throw new ToolError("INVALID_SERVICE_RESPONSE", `${label} is invalid`, EXIT_INTERNAL);
8644
8658
  }
8659
+ const sdk = provisionSdk;
8660
+ const OBJECT_OUTPUT = { type: "object", additionalProperties: true };
8661
+ const ROOT_OPTION = {
8662
+ name: "root",
8663
+ description: "Installed BuckyOS root on this machine (BUCKYOS_ROOT); read by status/check, written by activate",
8664
+ type: "string",
8665
+ required: true
8666
+ };
8667
+ const TARGET_OPTIONS = [
8668
+ ROOT_OPTION,
8669
+ {
8670
+ name: "domain",
8671
+ description: "Fixed public host name; Owner DID and Zone DID become did:web:<domain>",
8672
+ type: "string",
8673
+ required: true
8674
+ },
8675
+ {
8676
+ name: "owner-name",
8677
+ property: "owner_name",
8678
+ description: "Local administrator / OwnerDocument name (lowercase DNS label)",
8679
+ type: "string",
8680
+ required: true
8681
+ },
8682
+ {
8683
+ name: "owner-key-backup",
8684
+ property: "owner_key_backup",
8685
+ description: "New file for the Owner private-key recovery copy; its directory must exist and the file must not",
8686
+ type: "string",
8687
+ required: true
8688
+ },
8689
+ {
8690
+ name: "public-ip",
8691
+ property: "public_ip",
8692
+ description: "Fixed public IP used only for the A/AAAA record instructions",
8693
+ type: "string"
8694
+ },
8695
+ {
8696
+ name: "rtcp-port",
8697
+ property: "rtcp_port",
8698
+ description: "RTCP port, default 2980",
8699
+ type: "integer"
8700
+ },
8701
+ {
8702
+ name: "guest-access",
8703
+ property: "guest_access",
8704
+ description: "Enable guest access in the first-boot configuration",
8705
+ type: "boolean"
8706
+ }
8707
+ ];
8708
+ const TARGET_INPUT_PROPERTIES = {
8709
+ root: { type: "string", minLength: 1 },
8710
+ domain: { type: "string", minLength: 1 },
8711
+ owner_name: { type: "string", minLength: 1 },
8712
+ owner_key_backup: { type: "string", minLength: 1 },
8713
+ public_ip: { type: "string" },
8714
+ rtcp_port: { type: "integer", minimum: 1 },
8715
+ guest_access: { type: "boolean" }
8716
+ };
8717
+ const TARGET_REQUIRED = ["root", "domain", "owner_name", "owner_key_backup"];
8718
+ const POLICY_NOTE = "Paths are read from argv by the launcher to grant the minimal filesystem permissions; root and owner_key_backup given only inside --input are limited to the policy roots (cwd, and the paired BUCKYOS_ROOT of the system distribution).";
8719
+ function createProvisionModule(dependencies = {}) {
8720
+ const deps = {
8721
+ inspect: dependencies.inspect ?? sdk.inspectActivationRoot,
8722
+ check: dependencies.check ?? sdk.checkOfflineActivation,
8723
+ activate: dependencies.activate ?? sdk.activateOfflineZone
8724
+ };
8725
+ return {
8726
+ name: "provision",
8727
+ summary: "Activate an installed BuckyOS root on this machine (first Zone, Owner, and OOD)",
8728
+ commands: [statusCommand(deps), checkCommand(deps), activateCommand(deps)]
8729
+ };
8730
+ }
8731
+ function statusCommand(deps) {
8732
+ return {
8733
+ verb: "status",
8734
+ summary: "Inspect the local activation material of an installed BuckyOS root",
8735
+ description: "Read-only. Reports not_installed, unactivated, partial, configured, or invalid from the files under the root; configured only means the first-boot material is complete and internally consistent (startup_required=true). Service health, DNS, TLS, and public DID discovery are not checked. " + POLICY_NOTE,
8736
+ options: [ROOT_OPTION],
8737
+ inputSchema: {
8738
+ type: "object",
8739
+ properties: { root: { type: "string", minLength: 1 } },
8740
+ required: ["root"],
8741
+ additionalProperties: false
8742
+ },
8743
+ outputSchema: {
8744
+ ...OBJECT_OUTPUT,
8745
+ properties: {
8746
+ root: { type: "string" },
8747
+ state: {
8748
+ type: "string",
8749
+ enum: ["not_installed", "unactivated", "partial", "configured", "invalid"]
8750
+ },
8751
+ startup_required: { type: "boolean" }
8752
+ },
8753
+ required: ["root", "state", "startup_required"]
8754
+ },
8755
+ resultSchemaVersion: 1,
8756
+ access: { mode: "fixed", level: "read" },
8757
+ asyncMode: "sync",
8758
+ requiresSession: false,
8759
+ execution: "local",
8760
+ networkAccess: false,
8761
+ examples: ["buckyos provision status --root /opt/buckyos"],
8762
+ handler: async (ctx, input) => {
8763
+ const root = resolvePath(ctx, requiredString(input, "root"));
8764
+ await assertHostAccess(root, "read");
8765
+ return statusView(await runSdk(() => deps.inspect(root)));
8766
+ }
8767
+ };
8768
+ }
8769
+ function checkCommand(deps) {
8770
+ return {
8771
+ verb: "check",
8772
+ summary: "Validate activation parameters and the target root without writing anything",
8773
+ description: "Read-only precheck shared with activate: parameters, target state, and the owner key backup location. No keys are generated, no backup is written, and no operation is produced; activate re-validates the target itself. Fails with the first problem code when the target is not ready. " + POLICY_NOTE,
8774
+ options: TARGET_OPTIONS,
8775
+ inputSchema: {
8776
+ type: "object",
8777
+ properties: TARGET_INPUT_PROPERTIES,
8778
+ required: TARGET_REQUIRED,
8779
+ additionalProperties: false
8780
+ },
8781
+ outputSchema: {
8782
+ ...OBJECT_OUTPUT,
8783
+ properties: {
8784
+ ready: { type: "boolean" },
8785
+ root: { type: "string" },
8786
+ state: { type: "string" }
8787
+ },
8788
+ required: ["ready", "root", "state"]
8789
+ },
8790
+ resultSchemaVersion: 1,
8791
+ access: { mode: "fixed", level: "read" },
8792
+ asyncMode: "sync",
8793
+ requiresSession: false,
8794
+ execution: "local",
8795
+ networkAccess: false,
8796
+ examples: [
8797
+ "buckyos provision check --root /opt/buckyos --domain corp.example.com --owner-name admin --owner-key-backup /secure-backup/corp-owner.pem"
8798
+ ],
8799
+ handler: async (ctx, input) => {
8800
+ const options = activationOptions(ctx, input);
8801
+ await assertHostAccess(options.rootDir, "read");
8802
+ await assertHostAccess(getHost().path.dirname(options.ownerKeyBackupPath), "read");
8803
+ const precheck = await runSdk(() => deps.check(options));
8804
+ if (!precheck.ready)
8805
+ throw precheckError(precheck);
8806
+ return precheckView(precheck);
8807
+ }
8808
+ };
8809
+ }
8810
+ function activateCommand(deps) {
8811
+ return {
8812
+ verb: "activate",
8813
+ summary: "Activate the root: create the first Zone, Owner, and OOD identity and the first-boot configuration",
8814
+ description: "Privileged local write. Generates random Ed25519 Owner/device keys and current-time documents, saves the Owner private-key backup, then commits the identity, Zone, and start_config files; etc/node_identity.json is written last because node-daemon treats it as the activation switch. The administrator password is read from the secret admin_password field of --input JSON or from a hidden terminal prompt; there is no --admin-password option. Non-interactive runs require --yes. Repeated, partial, and invalid targets are rejected; there is no --force. After success restart BuckyOS through the installer or node control entry; this command never reports the Zone as online. " + POLICY_NOTE,
8815
+ options: TARGET_OPTIONS,
8816
+ inputSchema: {
8817
+ type: "object",
8818
+ properties: {
8819
+ ...TARGET_INPUT_PROPERTIES,
8820
+ admin_password: {
8821
+ type: "string",
8822
+ secret: true,
8823
+ description: "Administrator password (secret; --input JSON or hidden prompt only)"
8824
+ }
8825
+ },
8826
+ required: TARGET_REQUIRED,
8827
+ additionalProperties: false
8828
+ },
8829
+ outputSchema: {
8830
+ ...OBJECT_OUTPUT,
8831
+ properties: {
8832
+ root: { type: "string" },
8833
+ state: { type: "string", enum: ["configured"] },
8834
+ startup_required: { type: "boolean" }
8835
+ },
8836
+ required: ["root", "state", "startup_required"]
8837
+ },
8838
+ resultSchemaVersion: 1,
8839
+ access: { mode: "fixed", level: "privileged" },
8840
+ asyncMode: "sync",
8841
+ requiresSession: false,
8842
+ execution: "local",
8843
+ networkAccess: false,
8844
+ examples: [
8845
+ "buckyos provision activate --root /opt/buckyos --domain corp.example.com --owner-name admin --owner-key-backup /secure-backup/corp-owner.pem",
8846
+ "buckyos --non-interactive --yes --input activation.json provision activate --root /opt/buckyos --owner-key-backup /secure-backup/corp-owner.pem"
8847
+ ],
8848
+ handler: async (ctx, input) => {
8849
+ const options = activationOptions(ctx, input);
8850
+ const backupDirectory = getHost().path.dirname(options.ownerKeyBackupPath);
8851
+ await assertHostAccess(options.rootDir, "read");
8852
+ await assertHostAccess(options.rootDir, "write");
8853
+ await assertHostAccess(backupDirectory, "read");
8854
+ await assertHostAccess(backupDirectory, "write");
8855
+ const precheck = await runSdk(() => deps.check(options));
8856
+ if (!precheck.ready)
8857
+ throw precheckError(precheck);
8858
+ const adminPassword = await obtainAdminPassword(ctx, input);
8859
+ await confirmActivation(ctx, precheck);
8860
+ const result = await runSdk(
8861
+ () => deps.activate({ ...options, adminPassword, traceId: ctx.traceId })
8862
+ );
8863
+ return resultView(ctx, input, result);
8864
+ }
8865
+ };
8866
+ }
8867
+ function activationOptions(ctx, input) {
8868
+ return {
8869
+ rootDir: resolvePath(ctx, requiredString(input, "root")),
8870
+ domain: requiredString(input, "domain"),
8871
+ ownerName: requiredString(input, "owner_name"),
8872
+ ownerKeyBackupPath: resolvePath(ctx, requiredString(input, "owner_key_backup")),
8873
+ publicIp: optionalString(input, "public_ip"),
8874
+ rtcpPort: typeof input.rtcp_port === "number" ? input.rtcp_port : void 0,
8875
+ guestAccess: input.guest_access === true
8876
+ };
8877
+ }
8878
+ function requiredString(input, key) {
8879
+ const value = optionalString(input, key);
8880
+ if (!value)
8881
+ throw new UsageError("INVALID_ARGUMENT", `${key} is required`);
8882
+ return value;
8883
+ }
8884
+ function optionalString(input, key) {
8885
+ const value = input[key];
8886
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
8887
+ }
8888
+ function resolvePath(ctx, value) {
8889
+ const path = getHost().path;
8890
+ return path.isAbsolute(value) ? path.resolve(value) : path.resolve(ctx.cwd, value);
8891
+ }
8892
+ async function assertHostAccess(path, operation) {
8893
+ try {
8894
+ await getHost().assertAccess(path, operation);
8895
+ } catch (error) {
8896
+ if (isHostError(error, "PermissionDenied")) {
8897
+ throw new ToolError(
8898
+ "HOST_ACCESS_DENIED",
8899
+ `${error.message}; pass the path on the command line (--root / --owner-key-backup) so the launcher can grant it`,
8900
+ EXIT_PERMISSION,
8901
+ false,
8902
+ { path, operation }
8903
+ );
8904
+ }
8905
+ throw error;
8906
+ }
8907
+ }
8908
+ async function obtainAdminPassword(ctx, input) {
8909
+ if (typeof input.admin_password === "string")
8910
+ return input.admin_password;
8911
+ if (ctx.config.nonInteractive) {
8912
+ throw new UsageError(
8913
+ "SECRET_REQUIRED",
8914
+ "admin_password must be provided through --input JSON in non-interactive mode"
8915
+ );
8916
+ }
8917
+ if (!ctx.io.inputIsTerminal) {
8918
+ throw new UsageError(
8919
+ "SECRET_INPUT_UNAVAILABLE",
8920
+ "the administrator password requires an interactive terminal or --input JSON"
8921
+ );
8922
+ }
8923
+ const host2 = getHost();
8924
+ let password;
8925
+ let confirmation;
8926
+ try {
8927
+ password = await host2.readSecret("Administrator password: ");
8928
+ confirmation = await host2.readSecret("Confirm administrator password: ");
8929
+ } catch (error) {
8930
+ if (isHostError(error, "PermissionDenied")) {
8931
+ throw new UsageError("SECRET_INPUT_UNAVAILABLE", error.message);
8932
+ }
8933
+ throw error;
8934
+ }
8935
+ if (password !== confirmation) {
8936
+ throw new UsageError("PASSWORD_MISMATCH", "the administrator passwords do not match");
8937
+ }
8938
+ return password;
8939
+ }
8940
+ async function confirmActivation(ctx, precheck) {
8941
+ if (ctx.confirmed)
8942
+ return;
8943
+ if (ctx.config.nonInteractive) {
8944
+ throw new ToolError(
8945
+ "CONFIRMATION_REQUIRED",
8946
+ "provision activate requires --yes in non-interactive mode",
8947
+ EXIT_PERMISSION
8948
+ );
8949
+ }
8950
+ if (!ctx.io.inputIsTerminal) {
8951
+ throw new ToolError(
8952
+ "CONFIRMATION_REQUIRED",
8953
+ "provision activate requires an interactive terminal or --yes",
8954
+ EXIT_PERMISSION
8955
+ );
8956
+ }
8957
+ await ctx.io.stderr(
8958
+ [
8959
+ "Activation summary",
8960
+ ` BUCKYOS_ROOT : ${precheck.rootDir}`,
8961
+ ` Owner/Zone : ${precheck.zoneDid}`,
8962
+ ` Device : ${precheck.deviceDid}`,
8963
+ ` Admin : ${precheck.ownerName}`,
8964
+ ` Network : ${"wan"} (no SN, no BNS)`,
8965
+ ` RTCP port : ${precheck.rtcpPort}`,
8966
+ ` Guest access : ${precheck.guestAccess}`,
8967
+ ` Owner backup : ${precheck.ownerKeyBackup.path}`,
8968
+ ""
8969
+ ].join("\n")
8970
+ );
8971
+ const answer = (await ctx.io.prompt("Write this activation to disk? [y/N] "))?.trim().toLowerCase();
8972
+ if (answer !== "y" && answer !== "yes") {
8973
+ throw new ToolError("CONFIRMATION_DECLINED", "activation was declined", EXIT_PERMISSION);
8974
+ }
8975
+ }
8976
+ function isSdkError(error) {
8977
+ return error instanceof Error && error.name === "ActivationError" && typeof error.code === "string";
8978
+ }
8979
+ async function runSdk(run) {
8980
+ try {
8981
+ return await run();
8982
+ } catch (error) {
8983
+ if (isSdkError(error)) {
8984
+ const exitCode = error.code === "INVALID_ARGUMENT" ? EXIT_USAGE : error.code === "ACTIVATION_COMMIT_FAILED" ? EXIT_PARTIAL : EXIT_OPERATION;
8985
+ throw new ToolError(error.code, error.message, exitCode, false, error.details ?? {});
8986
+ }
8987
+ throw error;
8988
+ }
8989
+ }
8990
+ function precheckError(precheck) {
8991
+ const [first] = precheck.problems;
8992
+ const single = precheck.problems.length === 1;
8993
+ return new ToolError(
8994
+ single ? first.code : "ACTIVATION_PRECHECK_FAILED",
8995
+ single ? first.message : `activation precheck failed: ${precheck.problems.map((p) => p.message).join("; ")}`,
8996
+ EXIT_OPERATION,
8997
+ false,
8998
+ precheckView(precheck)
8999
+ );
9000
+ }
9001
+ function statusView(status) {
9002
+ return {
9003
+ root: status.rootDir,
9004
+ state: status.state,
9005
+ startup_required: status.startupRequired,
9006
+ observed_at: status.observedAt,
9007
+ zone_did: status.zoneDid,
9008
+ owner_did: status.ownerDid,
9009
+ device_did: status.deviceDid,
9010
+ device_name: status.deviceName,
9011
+ access_hostname: status.accessHostname,
9012
+ files: status.files.map((file) => ({
9013
+ path: file.path,
9014
+ role: file.role,
9015
+ required: file.required,
9016
+ secret: file.secret,
9017
+ present: file.present
9018
+ })),
9019
+ problems: status.problems,
9020
+ warnings: status.warnings,
9021
+ lock: status.lock ? {
9022
+ path: status.lock.path,
9023
+ stage: status.lock.stage,
9024
+ trace_id: status.lock.traceId,
9025
+ started_at: status.lock.startedAt,
9026
+ domain: status.lock.domain,
9027
+ committed_files: status.lock.committedFiles,
9028
+ owner_key_backup: status.lock.ownerKeyBackupPath,
9029
+ corrupt: status.lock.corrupt
9030
+ } : null
9031
+ };
9032
+ }
9033
+ function precheckView(precheck) {
9034
+ return {
9035
+ ready: precheck.ready,
9036
+ root: precheck.rootDir,
9037
+ state: precheck.state,
9038
+ domain: precheck.domain,
9039
+ owner_name: precheck.ownerName,
9040
+ owner_did: precheck.ownerDid,
9041
+ zone_did: precheck.zoneDid,
9042
+ device_did: precheck.deviceDid,
9043
+ device_name: precheck.deviceName,
9044
+ access_hostname: precheck.accessHostname,
9045
+ rtcp_port: precheck.rtcpPort,
9046
+ guest_access: precheck.guestAccess,
9047
+ public_ip: precheck.publicIp,
9048
+ dns_records: precheck.dnsRecords,
9049
+ owner_key_backup: {
9050
+ path: precheck.ownerKeyBackup.path,
9051
+ directory_exists: precheck.ownerKeyBackup.directoryExists,
9052
+ exists: precheck.ownerKeyBackup.exists
9053
+ },
9054
+ planned_files: precheck.plannedFiles,
9055
+ problems: precheck.problems,
9056
+ target: statusView(precheck.status)
9057
+ };
9058
+ }
9059
+ function resultView(ctx, input, result) {
9060
+ const dnsNotes = [
9061
+ ...result.dnsRecords.map((record) => `${record.type} ${record.name} ${record.value}`),
9062
+ ...result.publicIp ? [] : [`A/AAAA ${result.domain} <this node's fixed public IP>`],
9063
+ `The address record is also saved in etc/zone_dns_records.json under ${result.rootDir}.`,
9064
+ `Local boot uses etc/${result.domain}.zone.json; no DNS BOOT/PKX/DEV records are required.`,
9065
+ "TLS/ACME is not provided by SN in this mode; configure it on the public gateway."
9066
+ ];
9067
+ return {
9068
+ root: result.rootDir,
9069
+ state: result.state,
9070
+ startup_required: result.startupRequired,
9071
+ domain: result.domain,
9072
+ owner_name: result.ownerName,
9073
+ owner_did: result.ownerDid,
9074
+ zone_did: result.zoneDid,
9075
+ device_did: result.deviceDid,
9076
+ device_name: result.deviceName,
9077
+ access_hostname: result.accessHostname,
9078
+ rtcp_port: result.rtcpPort,
9079
+ guest_access: result.guestAccess,
9080
+ public_ip: result.publicIp,
9081
+ document_iat: result.documentIat,
9082
+ document_exp: result.documentExp,
9083
+ owner_key_backup: result.ownerKeyBackup,
9084
+ dns_records: result.dnsRecords,
9085
+ dns_notes: dnsNotes,
9086
+ committed_files: result.committedFiles,
9087
+ warnings: result.warnings,
9088
+ next_steps: [
9089
+ "Restart BuckyOS through the installer or the node control entry to leave activation mode and boot the new Zone.",
9090
+ "Check the running Zone afterwards with system status; activation does not verify service health, DNS, or TLS.",
9091
+ `Keep the Owner private-key backup ${result.ownerKeyBackup.path} offline; it is the only recovery copy.`
9092
+ ],
9093
+ audit: {
9094
+ module: ctx.command.module,
9095
+ verb: ctx.command.verb,
9096
+ trace_id: ctx.traceId,
9097
+ tool_version: TOOL_VERSION,
9098
+ input_fingerprint: inputFingerprint(input)
9099
+ }
9100
+ };
9101
+ }
9102
+ function inputFingerprint(input) {
9103
+ const material = {};
9104
+ for (const key of Object.keys(TARGET_INPUT_PROPERTIES).sort()) {
9105
+ if (input[key] !== void 0)
9106
+ material[key] = input[key];
9107
+ }
9108
+ const hash = getHost().createHash("sha256");
9109
+ hash.update(new TextEncoder().encode(JSON.stringify(material)));
9110
+ return hash.digestHex();
9111
+ }
8645
9112
  const VERSION = TOOL_VERSION;
8646
9113
  class BuckyOSToolApplication {
8647
9114
  #environment;
@@ -8658,7 +9125,8 @@ class BuckyOSToolApplication {
8658
9125
  dependencies.pikg,
8659
9126
  dependencies.app,
8660
9127
  dependencies.log,
8661
- dependencies.diagnostic
9128
+ dependencies.diagnostic,
9129
+ dependencies.provision
8662
9130
  );
8663
9131
  this.#environment = dependencies.environment ?? readEnvironment();
8664
9132
  this.#cwd = dependencies.cwd ?? getHost().cwd();
@@ -8744,6 +9212,8 @@ class BuckyOSToolApplication {
8744
9212
  `);
8745
9213
  return EXIT_SUCCESS;
8746
9214
  }
9215
+ if (command.execution === "local")
9216
+ assertNoSessionOptions(invocation.global, command);
8747
9217
  const setup = await this.#resolveForCommand(command, invocation.global);
8748
9218
  const inputObject = invocation.global.input ? await this.#readInputObject(invocation.global.input) : void 0;
8749
9219
  const parsed = parseCommandArgs(command, invocation.actionArgv, inputObject);
@@ -8989,7 +9459,7 @@ class BuckyOSToolApplication {
8989
9459
  return parsed;
8990
9460
  }
8991
9461
  }
8992
- function createRegistry(pikgDependencies, appDependencies, logDependencies, diagnosticDependencies) {
9462
+ function createRegistry(pikgDependencies, appDependencies, logDependencies, diagnosticDependencies, provisionDependencies) {
8993
9463
  const registry = new CommandRegistry();
8994
9464
  for (const module of createCoreModules(registry))
8995
9465
  registry.register(module);
@@ -9001,8 +9471,26 @@ function createRegistry(pikgDependencies, appDependencies, logDependencies, diag
9001
9471
  registry.register(createTaskModule());
9002
9472
  registry.register(createLogModule(logDependencies));
9003
9473
  registry.register(createDiagnosticModule(diagnosticDependencies));
9474
+ registry.register(createProvisionModule(provisionDependencies));
9004
9475
  return registry;
9005
9476
  }
9477
+ function assertNoSessionOptions(global, command) {
9478
+ for (const [name, value] of [
9479
+ ["profile", global.profile],
9480
+ ["zone", global.zone],
9481
+ ["endpoint", global.endpoint],
9482
+ ["identity", global.identity],
9483
+ ["session-token", global.sessionToken],
9484
+ ["session-token-file", global.sessionTokenFile]
9485
+ ]) {
9486
+ if (value !== void 0) {
9487
+ throw new UsageError(
9488
+ "ARGUMENT_CONFLICT",
9489
+ `--${name} cannot be combined with the local command ${command.module} ${command.verb}`
9490
+ );
9491
+ }
9492
+ }
9493
+ }
9006
9494
  const unavailableClients = {
9007
9495
  call: () => Promise.reject(new ToolError("INTERNAL_ERROR", "service clients are unavailable", 9))
9008
9496
  };
@@ -9270,6 +9758,9 @@ class NodeHost {
9270
9758
  throw translateNodeError(error, path);
9271
9759
  }
9272
9760
  }
9761
+ async assertAccess(path, operation) {
9762
+ await this.assertPath(path, operation);
9763
+ }
9273
9764
  createHash(_algorithm) {
9274
9765
  const hash = createHash("sha256");
9275
9766
  return {