@forgezero/agent 0.1.91 → 0.1.92

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.
@@ -917,7 +917,7 @@ async function postSignedNode(options, path, body) {
917
917
  }
918
918
 
919
919
  // src/version.ts
920
- var VERSION3 = "0.1.91";
920
+ var VERSION3 = "0.1.92";
921
921
 
922
922
  // src/agent-heartbeat.ts
923
923
  function readAgentHostMetrics() {
package/dist/bootstrap.js CHANGED
@@ -1420,7 +1420,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1420
1420
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1421
1421
 
1422
1422
  // src/version.ts
1423
- var VERSION = "0.1.91";
1423
+ var VERSION = "0.1.92";
1424
1424
 
1425
1425
  // src/software.ts
1426
1426
  var PINNED_BUN_VERSION = "1.3.14";
@@ -3088,6 +3088,7 @@ var httpsOrigin = (name, raw) => {
3088
3088
  }
3089
3089
  return value.origin;
3090
3090
  };
3091
+ var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
3091
3092
  function validatePlatformInitialInventory(value) {
3092
3093
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
3093
3094
  throw new Error("initial platform inventory coordinates are invalid");
@@ -3193,7 +3194,7 @@ function validatePlatformSharedEnvironment(input) {
3193
3194
  if (input.otlpEndpoint !== "http://127.0.0.1:4318")
3194
3195
  throw new Error("OTLP must use the exact local collector endpoint.");
3195
3196
  validateCollectorUnit(input.otlpCollectorUnit);
3196
- httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint);
3197
+ agentTelemetryOrigin(input.agentOtlpEndpoint);
3197
3198
  for (const [name, value] of Object.entries({
3198
3199
  nodeHostname: input.nodeHostname,
3199
3200
  nodeRegion: input.nodeRegion,
@@ -3238,7 +3239,7 @@ function validatePlatformSharedEnvironment(input) {
3238
3239
  databaseReadPreferredCoordinators: readPreferred,
3239
3240
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
3240
3241
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
3241
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
3242
+ agentOtlpEndpoint: agentTelemetryOrigin(input.agentOtlpEndpoint),
3242
3243
  ...initialInventory ? { initialInventory } : {}
3243
3244
  };
3244
3245
  }
@@ -3514,6 +3515,7 @@ function planLocalOtlpProof(endpoint2, collectorUnit) {
3514
3515
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
3515
3516
  var FORGEZERO_OTEL_COLLECTOR_VERSION = "0.157.0";
3516
3517
  var FORGEZERO_OTEL_COLLECTOR_SHA256 = "2937cf24892af55b143c072fddece17862239cf78280620029276493eb81beae";
3518
+ var LOCAL_DEBUG_OTEL_EXPORT = "local-debug";
3517
3519
  var ARCHIVE = "/run/forgezero-otelcol.tar.gz";
3518
3520
  var EXTRACT = "/run/forgezero-otelcol-release";
3519
3521
  var BINARY = "/usr/local/lib/forgezero/otelcol/otelcol";
@@ -3539,7 +3541,9 @@ var destination = (value) => {
3539
3541
  return url.toString().replace(/\/$/, "");
3540
3542
  };
3541
3543
  function renderForgeZeroOtelCollector(exportEndpoint) {
3542
- const endpoint2 = destination(exportEndpoint);
3544
+ const exporter = exportEndpoint === LOCAL_DEBUG_OTEL_EXPORT ? { definition: ` debug:
3545
+ verbosity: basic`, name: "debug" } : { definition: ` otlp_http:
3546
+ endpoint: ${JSON.stringify(destination(exportEndpoint))}`, name: "otlp_http" };
3543
3547
  return {
3544
3548
  config: `receivers:
3545
3549
  otlp:
@@ -3547,19 +3551,18 @@ function renderForgeZeroOtelCollector(exportEndpoint) {
3547
3551
  http:
3548
3552
  endpoint: 127.0.0.1:4318
3549
3553
  exporters:
3550
- otlp_http:
3551
- endpoint: ${JSON.stringify(endpoint2)}
3554
+ ${exporter.definition}
3552
3555
  service:
3553
3556
  pipelines:
3554
3557
  traces:
3555
3558
  receivers: [otlp]
3556
- exporters: [otlp_http]
3559
+ exporters: [${exporter.name}]
3557
3560
  metrics:
3558
3561
  receivers: [otlp]
3559
- exporters: [otlp_http]
3562
+ exporters: [${exporter.name}]
3560
3563
  logs:
3561
3564
  receivers: [otlp]
3562
- exporters: [otlp_http]
3565
+ exporters: [${exporter.name}]
3563
3566
  `,
3564
3567
  unit: `[Unit]
3565
3568
  Description=ForgeZero independently supervised OpenTelemetry Collector
@@ -3816,14 +3819,20 @@ function validateBootstrapConfig(value) {
3816
3819
  if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?){2,}$/.test(value.nodeHostname)) {
3817
3820
  throw new Error("node hostname must be a lowercase public FQDN");
3818
3821
  }
3819
- let telemetry;
3820
- try {
3821
- telemetry = new URL(value.telemetryEndpoint);
3822
- } catch {
3823
- throw new Error("telemetry endpoint is malformed");
3824
- }
3825
- if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
3826
- throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
3822
+ if (value.telemetryEndpoint === LOCAL_DEBUG_OTEL_EXPORT) {
3823
+ if (value.kind !== "platform" || value.environment !== "development") {
3824
+ throw new Error("local debug telemetry is allowed only for the development platform profile");
3825
+ }
3826
+ } else {
3827
+ let telemetry;
3828
+ try {
3829
+ telemetry = new URL(value.telemetryEndpoint);
3830
+ } catch {
3831
+ throw new Error("telemetry endpoint is malformed");
3832
+ }
3833
+ if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
3834
+ throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
3835
+ }
3827
3836
  }
3828
3837
  const deploymentCredentials = value.deploymentCredentials ?? {};
3829
3838
  if (!deploymentCredentials || typeof deploymentCredentials !== "object" || Array.isArray(deploymentCredentials) || Object.keys(deploymentCredentials).length > 64) {
package/dist/fz-agent.js CHANGED
@@ -9496,7 +9496,7 @@ async function writeAndCloseProcessInput(input, value) {
9496
9496
  }
9497
9497
 
9498
9498
  // src/version.ts
9499
- var VERSION2 = "0.1.91";
9499
+ var VERSION2 = "0.1.92";
9500
9500
 
9501
9501
  // src/ssh-bootstrap.ts
9502
9502
  class SshBootstrapError extends Error {
package/dist/fz.js CHANGED
@@ -4840,7 +4840,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
4840
4840
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
4841
4841
 
4842
4842
  // src/version.ts
4843
- var VERSION2 = "0.1.91";
4843
+ var VERSION2 = "0.1.92";
4844
4844
 
4845
4845
  // src/software.ts
4846
4846
  var PINNED_BUN_VERSION = "1.3.14";
@@ -12236,6 +12236,7 @@ var httpsOrigin = (name, raw) => {
12236
12236
  }
12237
12237
  return value.origin;
12238
12238
  };
12239
+ var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
12239
12240
  function validatePlatformInitialInventory(value) {
12240
12241
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
12241
12242
  throw new Error("initial platform inventory coordinates are invalid");
@@ -12341,7 +12342,7 @@ function validatePlatformSharedEnvironment(input) {
12341
12342
  if (input.otlpEndpoint !== "http://127.0.0.1:4318")
12342
12343
  throw new Error("OTLP must use the exact local collector endpoint.");
12343
12344
  validateCollectorUnit(input.otlpCollectorUnit);
12344
- httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint);
12345
+ agentTelemetryOrigin(input.agentOtlpEndpoint);
12345
12346
  for (const [name, value] of Object.entries({
12346
12347
  nodeHostname: input.nodeHostname,
12347
12348
  nodeRegion: input.nodeRegion,
@@ -12386,7 +12387,7 @@ function validatePlatformSharedEnvironment(input) {
12386
12387
  databaseReadPreferredCoordinators: readPreferred,
12387
12388
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
12388
12389
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
12389
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
12390
+ agentOtlpEndpoint: agentTelemetryOrigin(input.agentOtlpEndpoint),
12390
12391
  ...initialInventory ? { initialInventory } : {}
12391
12392
  };
12392
12393
  }
@@ -13740,6 +13741,7 @@ async function finalizeCloudflareBootstrapAcceptance(request, fetcher = fetch) {
13740
13741
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
13741
13742
  var FORGEZERO_OTEL_COLLECTOR_VERSION = "0.157.0";
13742
13743
  var FORGEZERO_OTEL_COLLECTOR_SHA256 = "2937cf24892af55b143c072fddece17862239cf78280620029276493eb81beae";
13744
+ var LOCAL_DEBUG_OTEL_EXPORT = "local-debug";
13743
13745
  var ARCHIVE = "/run/forgezero-otelcol.tar.gz";
13744
13746
  var EXTRACT = "/run/forgezero-otelcol-release";
13745
13747
  var BINARY = "/usr/local/lib/forgezero/otelcol/otelcol";
@@ -13765,7 +13767,9 @@ var destination = (value) => {
13765
13767
  return url.toString().replace(/\/$/, "");
13766
13768
  };
13767
13769
  function renderForgeZeroOtelCollector(exportEndpoint) {
13768
- const endpoint2 = destination(exportEndpoint);
13770
+ const exporter = exportEndpoint === LOCAL_DEBUG_OTEL_EXPORT ? { definition: ` debug:
13771
+ verbosity: basic`, name: "debug" } : { definition: ` otlp_http:
13772
+ endpoint: ${JSON.stringify(destination(exportEndpoint))}`, name: "otlp_http" };
13769
13773
  return {
13770
13774
  config: `receivers:
13771
13775
  otlp:
@@ -13773,19 +13777,18 @@ function renderForgeZeroOtelCollector(exportEndpoint) {
13773
13777
  http:
13774
13778
  endpoint: 127.0.0.1:4318
13775
13779
  exporters:
13776
- otlp_http:
13777
- endpoint: ${JSON.stringify(endpoint2)}
13780
+ ${exporter.definition}
13778
13781
  service:
13779
13782
  pipelines:
13780
13783
  traces:
13781
13784
  receivers: [otlp]
13782
- exporters: [otlp_http]
13785
+ exporters: [${exporter.name}]
13783
13786
  metrics:
13784
13787
  receivers: [otlp]
13785
- exporters: [otlp_http]
13788
+ exporters: [${exporter.name}]
13786
13789
  logs:
13787
13790
  receivers: [otlp]
13788
- exporters: [otlp_http]
13791
+ exporters: [${exporter.name}]
13789
13792
  `,
13790
13793
  unit: `[Unit]
13791
13794
  Description=ForgeZero independently supervised OpenTelemetry Collector
@@ -14200,14 +14203,20 @@ function validateBootstrapConfig(value) {
14200
14203
  if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?){2,}$/.test(value.nodeHostname)) {
14201
14204
  throw new Error("node hostname must be a lowercase public FQDN");
14202
14205
  }
14203
- let telemetry;
14204
- try {
14205
- telemetry = new URL(value.telemetryEndpoint);
14206
- } catch {
14207
- throw new Error("telemetry endpoint is malformed");
14208
- }
14209
- if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
14210
- throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
14206
+ if (value.telemetryEndpoint === LOCAL_DEBUG_OTEL_EXPORT) {
14207
+ if (value.kind !== "platform" || value.environment !== "development") {
14208
+ throw new Error("local debug telemetry is allowed only for the development platform profile");
14209
+ }
14210
+ } else {
14211
+ let telemetry;
14212
+ try {
14213
+ telemetry = new URL(value.telemetryEndpoint);
14214
+ } catch {
14215
+ throw new Error("telemetry endpoint is malformed");
14216
+ }
14217
+ if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
14218
+ throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
14219
+ }
14211
14220
  }
14212
14221
  const deploymentCredentials = value.deploymentCredentials ?? {};
14213
14222
  if (!deploymentCredentials || typeof deploymentCredentials !== "object" || Array.isArray(deploymentCredentials) || Object.keys(deploymentCredentials).length > 64) {
@@ -17918,7 +17927,8 @@ var PROFILES = {
17918
17927
  workerScriptName: "forgezero-api-edge-development",
17919
17928
  region: { key: "in-south", label: "India South", country: "IN" },
17920
17929
  seedSyncEpoch: "development-23c19168773d69ea",
17921
- agentOtlpEndpoint: "https://otel.forgezero.net",
17930
+ collectorExport: LOCAL_DEBUG_OTEL_EXPORT,
17931
+ agentOtlpEndpoint: "http://127.0.0.1:4318",
17922
17932
  privateCidrs: ["10.42.0.0/24"]
17923
17933
  },
17924
17934
  production: {
@@ -17931,6 +17941,7 @@ var PROFILES = {
17931
17941
  workerScriptName: "forgezero-api-edge-production",
17932
17942
  region: { key: "in-south", label: "India South", country: "IN" },
17933
17943
  seedSyncEpoch: "production-genesis-v1",
17944
+ collectorExport: "https://otel.forgezero.net",
17934
17945
  agentOtlpEndpoint: "https://otel.forgezero.net",
17935
17946
  privateCidrs: ["10.42.0.0/24"]
17936
17947
  }
@@ -17968,7 +17979,7 @@ function forgeZeroLaunchTemplate(profile, guests, bundle, owner) {
17968
17979
  manifestFile: bundle.manifestPath,
17969
17980
  branch: profile.branch
17970
17981
  },
17971
- telemetryEndpoint: profile.agentOtlpEndpoint,
17982
+ telemetryEndpoint: profile.collectorExport,
17972
17983
  database: {
17973
17984
  role: "master",
17974
17985
  agency: "member",
@@ -366,12 +366,13 @@ function systemdAgentEgressDirectives(loopbackTcpPorts = []) {
366
366
  }
367
367
 
368
368
  // src/version.ts
369
- var VERSION = "0.1.91";
369
+ var VERSION = "0.1.92";
370
370
 
371
371
  // src/otel-collector.ts
372
372
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
373
373
  var FORGEZERO_OTEL_COLLECTOR_VERSION = "0.157.0";
374
374
  var FORGEZERO_OTEL_COLLECTOR_SHA256 = "2937cf24892af55b143c072fddece17862239cf78280620029276493eb81beae";
375
+ var LOCAL_DEBUG_OTEL_EXPORT = "local-debug";
375
376
  var ARCHIVE = "/run/forgezero-otelcol.tar.gz";
376
377
  var EXTRACT = "/run/forgezero-otelcol-release";
377
378
  var BINARY = "/usr/local/lib/forgezero/otelcol/otelcol";
@@ -397,7 +398,9 @@ var destination = (value) => {
397
398
  return url.toString().replace(/\/$/, "");
398
399
  };
399
400
  function renderForgeZeroOtelCollector(exportEndpoint) {
400
- const endpoint = destination(exportEndpoint);
401
+ const exporter = exportEndpoint === LOCAL_DEBUG_OTEL_EXPORT ? { definition: ` debug:
402
+ verbosity: basic`, name: "debug" } : { definition: ` otlp_http:
403
+ endpoint: ${JSON.stringify(destination(exportEndpoint))}`, name: "otlp_http" };
401
404
  return {
402
405
  config: `receivers:
403
406
  otlp:
@@ -405,19 +408,18 @@ function renderForgeZeroOtelCollector(exportEndpoint) {
405
408
  http:
406
409
  endpoint: 127.0.0.1:4318
407
410
  exporters:
408
- otlp_http:
409
- endpoint: ${JSON.stringify(endpoint)}
411
+ ${exporter.definition}
410
412
  service:
411
413
  pipelines:
412
414
  traces:
413
415
  receivers: [otlp]
414
- exporters: [otlp_http]
416
+ exporters: [${exporter.name}]
415
417
  metrics:
416
418
  receivers: [otlp]
417
- exporters: [otlp_http]
419
+ exporters: [${exporter.name}]
418
420
  logs:
419
421
  receivers: [otlp]
420
- exporters: [otlp_http]
422
+ exporters: [${exporter.name}]
421
423
  `,
422
424
  unit: `[Unit]
423
425
  Description=ForgeZero independently supervised OpenTelemetry Collector
@@ -1420,7 +1420,7 @@ var UPDATE_RETRY_BASE_MS = 5 * 60000;
1420
1420
  var UPDATE_RETRY_MAX_MS = 24 * 60 * 60000;
1421
1421
 
1422
1422
  // src/version.ts
1423
- var VERSION = "0.1.91";
1423
+ var VERSION = "0.1.92";
1424
1424
 
1425
1425
  // src/software.ts
1426
1426
  var PINNED_BUN_VERSION = "1.3.14";
@@ -3088,6 +3088,7 @@ var httpsOrigin = (name, raw) => {
3088
3088
  }
3089
3089
  return value.origin;
3090
3090
  };
3091
+ var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
3091
3092
  function validatePlatformInitialInventory(value) {
3092
3093
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
3093
3094
  throw new Error("initial platform inventory coordinates are invalid");
@@ -3193,7 +3194,7 @@ function validatePlatformSharedEnvironment(input) {
3193
3194
  if (input.otlpEndpoint !== "http://127.0.0.1:4318")
3194
3195
  throw new Error("OTLP must use the exact local collector endpoint.");
3195
3196
  validateCollectorUnit(input.otlpCollectorUnit);
3196
- httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint);
3197
+ agentTelemetryOrigin(input.agentOtlpEndpoint);
3197
3198
  for (const [name, value] of Object.entries({
3198
3199
  nodeHostname: input.nodeHostname,
3199
3200
  nodeRegion: input.nodeRegion,
@@ -3238,7 +3239,7 @@ function validatePlatformSharedEnvironment(input) {
3238
3239
  databaseReadPreferredCoordinators: readPreferred,
3239
3240
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
3240
3241
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
3241
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
3242
+ agentOtlpEndpoint: agentTelemetryOrigin(input.agentOtlpEndpoint),
3242
3243
  ...initialInventory ? { initialInventory } : {}
3243
3244
  };
3244
3245
  }
@@ -3514,6 +3515,7 @@ function planLocalOtlpProof(endpoint2, collectorUnit) {
3514
3515
  var FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
3515
3516
  var FORGEZERO_OTEL_COLLECTOR_VERSION = "0.157.0";
3516
3517
  var FORGEZERO_OTEL_COLLECTOR_SHA256 = "2937cf24892af55b143c072fddece17862239cf78280620029276493eb81beae";
3518
+ var LOCAL_DEBUG_OTEL_EXPORT = "local-debug";
3517
3519
  var ARCHIVE = "/run/forgezero-otelcol.tar.gz";
3518
3520
  var EXTRACT = "/run/forgezero-otelcol-release";
3519
3521
  var BINARY = "/usr/local/lib/forgezero/otelcol/otelcol";
@@ -3539,7 +3541,9 @@ var destination = (value) => {
3539
3541
  return url.toString().replace(/\/$/, "");
3540
3542
  };
3541
3543
  function renderForgeZeroOtelCollector(exportEndpoint) {
3542
- const endpoint2 = destination(exportEndpoint);
3544
+ const exporter = exportEndpoint === LOCAL_DEBUG_OTEL_EXPORT ? { definition: ` debug:
3545
+ verbosity: basic`, name: "debug" } : { definition: ` otlp_http:
3546
+ endpoint: ${JSON.stringify(destination(exportEndpoint))}`, name: "otlp_http" };
3543
3547
  return {
3544
3548
  config: `receivers:
3545
3549
  otlp:
@@ -3547,19 +3551,18 @@ function renderForgeZeroOtelCollector(exportEndpoint) {
3547
3551
  http:
3548
3552
  endpoint: 127.0.0.1:4318
3549
3553
  exporters:
3550
- otlp_http:
3551
- endpoint: ${JSON.stringify(endpoint2)}
3554
+ ${exporter.definition}
3552
3555
  service:
3553
3556
  pipelines:
3554
3557
  traces:
3555
3558
  receivers: [otlp]
3556
- exporters: [otlp_http]
3559
+ exporters: [${exporter.name}]
3557
3560
  metrics:
3558
3561
  receivers: [otlp]
3559
- exporters: [otlp_http]
3562
+ exporters: [${exporter.name}]
3560
3563
  logs:
3561
3564
  receivers: [otlp]
3562
- exporters: [otlp_http]
3565
+ exporters: [${exporter.name}]
3563
3566
  `,
3564
3567
  unit: `[Unit]
3565
3568
  Description=ForgeZero independently supervised OpenTelemetry Collector
@@ -3816,14 +3819,20 @@ function validateBootstrapConfig(value) {
3816
3819
  if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?){2,}$/.test(value.nodeHostname)) {
3817
3820
  throw new Error("node hostname must be a lowercase public FQDN");
3818
3821
  }
3819
- let telemetry;
3820
- try {
3821
- telemetry = new URL(value.telemetryEndpoint);
3822
- } catch {
3823
- throw new Error("telemetry endpoint is malformed");
3824
- }
3825
- if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
3826
- throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
3822
+ if (value.telemetryEndpoint === LOCAL_DEBUG_OTEL_EXPORT) {
3823
+ if (value.kind !== "platform" || value.environment !== "development") {
3824
+ throw new Error("local debug telemetry is allowed only for the development platform profile");
3825
+ }
3826
+ } else {
3827
+ let telemetry;
3828
+ try {
3829
+ telemetry = new URL(value.telemetryEndpoint);
3830
+ } catch {
3831
+ throw new Error("telemetry endpoint is malformed");
3832
+ }
3833
+ if (telemetry.protocol !== "https:" || telemetry.port && telemetry.port !== "443" || telemetry.username || telemetry.password || telemetry.search || telemetry.hash) {
3834
+ throw new Error("telemetry endpoint must be public HTTPS on port 443 without credentials, query or fragment");
3835
+ }
3827
3836
  }
3828
3837
  const deploymentCredentials = value.deploymentCredentials ?? {};
3829
3838
  if (!deploymentCredentials || typeof deploymentCredentials !== "object" || Array.isArray(deploymentCredentials) || Object.keys(deploymentCredentials).length > 64) {
@@ -1,6 +1,7 @@
1
1
  export declare const FORGEZERO_OTEL_COLLECTOR_UNIT = "forgezero-otel-collector.service";
2
2
  export declare const FORGEZERO_OTEL_COLLECTOR_VERSION = "0.157.0";
3
3
  export declare const FORGEZERO_OTEL_COLLECTOR_SHA256 = "2937cf24892af55b143c072fddece17862239cf78280620029276493eb81beae";
4
+ export declare const LOCAL_DEBUG_OTEL_EXPORT = "local-debug";
4
5
  export interface OtelCollectorHost {
5
6
  write(path: string, content: string, mode: number): void;
6
7
  exec(argv: readonly string[]): Promise<{
@@ -728,6 +728,7 @@ var httpsOrigin = (name, raw) => {
728
728
  }
729
729
  return value.origin;
730
730
  };
731
+ var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
731
732
  function validatePlatformInitialInventory(value) {
732
733
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
733
734
  throw new Error("initial platform inventory coordinates are invalid");
@@ -833,7 +834,7 @@ function validatePlatformSharedEnvironment(input) {
833
834
  if (input.otlpEndpoint !== "http://127.0.0.1:4318")
834
835
  throw new Error("OTLP must use the exact local collector endpoint.");
835
836
  validateCollectorUnit(input.otlpCollectorUnit);
836
- httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint);
837
+ agentTelemetryOrigin(input.agentOtlpEndpoint);
837
838
  for (const [name, value] of Object.entries({
838
839
  nodeHostname: input.nodeHostname,
839
840
  nodeRegion: input.nodeRegion,
@@ -878,7 +879,7 @@ function validatePlatformSharedEnvironment(input) {
878
879
  databaseReadPreferredCoordinators: readPreferred,
879
880
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
880
881
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
881
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
882
+ agentOtlpEndpoint: agentTelemetryOrigin(input.agentOtlpEndpoint),
882
883
  ...initialInventory ? { initialInventory } : {}
883
884
  };
884
885
  }
@@ -2908,7 +2908,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2908
2908
  }
2909
2909
 
2910
2910
  // src/version.ts
2911
- var VERSION3 = "0.1.91";
2911
+ var VERSION3 = "0.1.92";
2912
2912
 
2913
2913
  // src/egress-policy.ts
2914
2914
  import { realpathSync as realpathSync3 } from "node:fs";
@@ -4140,6 +4140,7 @@ var httpsOrigin = (name, raw) => {
4140
4140
  }
4141
4141
  return value.origin;
4142
4142
  };
4143
+ var agentTelemetryOrigin = (raw) => raw === "http://127.0.0.1:4318" ? raw : httpsOrigin("agentOtlpEndpoint", raw);
4143
4144
  function validatePlatformInitialInventory(value) {
4144
4145
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes", "deployment"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
4145
4146
  throw new Error("initial platform inventory coordinates are invalid");
@@ -4245,7 +4246,7 @@ function validatePlatformSharedEnvironment(input) {
4245
4246
  if (input.otlpEndpoint !== "http://127.0.0.1:4318")
4246
4247
  throw new Error("OTLP must use the exact local collector endpoint.");
4247
4248
  validateCollectorUnit(input.otlpCollectorUnit);
4248
- httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint);
4249
+ agentTelemetryOrigin(input.agentOtlpEndpoint);
4249
4250
  for (const [name, value] of Object.entries({
4250
4251
  nodeHostname: input.nodeHostname,
4251
4252
  nodeRegion: input.nodeRegion,
@@ -4290,7 +4291,7 @@ function validatePlatformSharedEnvironment(input) {
4290
4291
  databaseReadPreferredCoordinators: readPreferred,
4291
4292
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
4292
4293
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
4293
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
4294
+ agentOtlpEndpoint: agentTelemetryOrigin(input.agentOtlpEndpoint),
4294
4295
  ...initialInventory ? { initialInventory } : {}
4295
4296
  };
4296
4297
  }
@@ -16,6 +16,7 @@ export interface ForgeZeroLaunchProfile {
16
16
  country: string;
17
17
  city?: string;
18
18
  };
19
+ collectorExport: string;
19
20
  agentOtlpEndpoint: string;
20
21
  seedSyncEpoch: string;
21
22
  privateCidrs: readonly string[];
package/dist/provision.js CHANGED
@@ -2908,7 +2908,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2908
2908
  }
2909
2909
 
2910
2910
  // src/version.ts
2911
- var VERSION3 = "0.1.91";
2911
+ var VERSION3 = "0.1.92";
2912
2912
 
2913
2913
  // src/egress-policy.ts
2914
2914
  import { realpathSync as realpathSync3 } from "node:fs";
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** One package version shared by both public binaries. Pinned to package.json by tests. */
2
- export declare const VERSION = "0.1.91";
2
+ export declare const VERSION = "0.1.92";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgezero/agent",
3
- "version": "0.1.91",
3
+ "version": "0.1.92",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsc --noEmit",