@le-space/ui 0.3.28 → 0.3.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/ui",
3
- "version": "0.3.28",
3
+ "version": "0.3.31",
4
4
  "description": "Floating Aleph sponsor relay UI components for Svelte and React.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,8 +36,8 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@le-space/browser": "0.3.28",
40
- "@le-space/core": "0.3.28",
39
+ "@le-space/browser": "0.3.31",
40
+ "@le-space/core": "0.3.31",
41
41
  "viem": "^2.38.5"
42
42
  },
43
43
  "peerDependencies": {
package/react/index.js CHANGED
@@ -28,7 +28,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
28
28
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
29
29
 
30
30
  // src/shared/package-version.ts
31
- var UI_PACKAGE_VERSION = "0.3.28";
31
+ var UI_PACKAGE_VERSION = "0.3.31";
32
32
 
33
33
  // src/shared/format.ts
34
34
  function shortHash(value, head = 8, tail = 6) {
@@ -2869,7 +2869,14 @@ function normalizeVmBootstrapConfigSignalRecord(value) {
2869
2869
  instanceItemHash,
2870
2870
  updatedAt,
2871
2871
  publisherAddress: typeof candidate.publisherAddress === "string" && candidate.publisherAddress.trim() ? candidate.publisherAddress.trim() : null,
2872
- authorization: candidate.authorization
2872
+ authorization: candidate.authorization,
2873
+ peerId: typeof candidate.peerId === "string" && candidate.peerId.trim() ? candidate.peerId.trim() : null,
2874
+ probeMultiaddrs: Array.isArray(candidate.probeMultiaddrs) ? candidate.probeMultiaddrs.filter(
2875
+ (entry) => typeof entry === "string" && entry.trim().length > 0
2876
+ ) : [],
2877
+ browserBootstrapMultiaddrs: Array.isArray(candidate.browserBootstrapMultiaddrs) ? candidate.browserBootstrapMultiaddrs.filter(
2878
+ (entry) => typeof entry === "string" && entry.trim().length > 0
2879
+ ) : []
2873
2880
  };
2874
2881
  }
2875
2882
  async function fetchVmBootstrapConfigSignals(args) {
@@ -3401,6 +3408,7 @@ var SponsorRelayController = class {
3401
3408
  if (!setupPort) {
3402
3409
  throw new Error("Relay runtime did not expose the temporary setup endpoint.");
3403
3410
  }
3411
+ let bootstrapSignalRelayMetadata = null;
3404
3412
  if (profile === "orbitdb-relay-pinner") {
3405
3413
  this.emitProgress({
3406
3414
  stage: "deployment-confirmed",
@@ -3483,6 +3491,14 @@ var SponsorRelayController = class {
3483
3491
  crns: this.state.crns,
3484
3492
  crnListUrl: this.props.crnListUrl
3485
3493
  }).catch(() => latestRuntime);
3494
+ this.emitProgress({
3495
+ stage: "deployment-confirmed",
3496
+ label: "Waiting for HTTPS route",
3497
+ progress: 93,
3498
+ status: latestRuntime.webAccess?.active === true ? "info" : "warning",
3499
+ itemHash: args.itemHash,
3500
+ detail: `2n6 activation ${attempt + 1}/${UI_RUNTIME_WAIT_ATTEMPTS}: ${latestRuntime.webAccess?.active === true ? "active" : "still pending"} for ${latestRuntime.proxyUrl ?? runtime.proxyUrl ?? "reserved proxy URL"}.`
3501
+ });
3486
3502
  this.trace("deploy:bootstrap-proxy-activation", {
3487
3503
  itemHash: args.itemHash,
3488
3504
  attempt: attempt + 1,
@@ -3493,11 +3509,6 @@ var SponsorRelayController = class {
3493
3509
  }
3494
3510
  runtime = latestRuntime;
3495
3511
  mappedPorts2 = runtime.mappedPorts ?? mappedPorts2;
3496
- if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
3497
- throw new Error(
3498
- "Aleph reserved a 2n6 proxy URL, but it never became active in time. Aborting guest HTTPS configuration to avoid a broken Caddy setup."
3499
- );
3500
- }
3501
3512
  }
3502
3513
  if (!runtime.hostIpv4) {
3503
3514
  throw new Error("Relay runtime lost its host IPv4 address while waiting for HTTPS activation.");
@@ -3579,46 +3590,85 @@ var SponsorRelayController = class {
3579
3590
  "The relay VM did not confirm that it applied the Aleph bootstrap config in time."
3580
3591
  );
3581
3592
  }
3582
- }
3583
- this.emitProgress({
3584
- stage: "publishing-bootstrap",
3585
- label: "Reading relay multiaddrs",
3586
- progress: 95,
3587
- status: "info",
3588
- itemHash: args.itemHash,
3589
- detail: "Waiting for the relay to report its final public multiaddrs."
3590
- });
3591
- const relayMetadata = await fetchRelayMetadataForRuntime({
3592
- runtime,
3593
- fetch: (url, init) => fetch(url, init),
3594
- preferSecureMetadata: profile === "uc-go-peer",
3595
- attempts: 80,
3596
- delayMs: 3e3,
3597
- timeoutMs: 24e4,
3598
- onAttempt: (result) => {
3599
- const payload = result.payload && typeof result.payload === "object" ? result.payload : null;
3600
- const metadata = payload?.metadata && typeof payload.metadata === "object" ? payload.metadata : null;
3601
- this.trace("deploy:relay-metadata-attempt", {
3593
+ bootstrapSignalRelayMetadata = typeof bootstrapConfigSignal.peerId === "string" && bootstrapConfigSignal.peerId.length > 0 && Array.isArray(bootstrapConfigSignal.probeMultiaddrs) && bootstrapConfigSignal.probeMultiaddrs.length > 0 ? {
3594
+ peerId: bootstrapConfigSignal.peerId,
3595
+ probeMultiaddrs: bootstrapConfigSignal.probeMultiaddrs,
3596
+ browserBootstrapMultiaddrs: bootstrapConfigSignal.browserBootstrapMultiaddrs ?? []
3597
+ } : null;
3598
+ if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
3599
+ this.trace("deploy:bootstrap-proxy-fallback", {
3600
+ itemHash: args.itemHash,
3601
+ deploymentToken: args.deploymentToken,
3602
+ proxyUrl: runtime.proxyUrl,
3603
+ bootstrapSignalRelayMetadata
3604
+ });
3605
+ this.emitProgress({
3606
+ stage: "deployment-confirmed",
3607
+ label: "Continuing without HTTPS route",
3608
+ progress: 94,
3609
+ status: "warning",
3602
3610
  itemHash: args.itemHash,
3603
- attempt: result.attempt,
3604
- attempts: result.attempts,
3605
- requestUrl: result.requestUrl,
3606
- metadataUrl: result.metadataUrl,
3607
- hostIpv4: result.hostIpv4,
3608
- setupPort: result.setupPort,
3609
- ok: result.ok,
3610
- status: result.status,
3611
- ready: result.ready,
3612
- error: result.error ?? null,
3613
- payloadStatus: payload && typeof payload.status === "string" ? payload.status : null,
3614
- peerId: metadata && typeof metadata.peer_id === "string" ? metadata.peer_id : null,
3615
- probeMultiaddrCount: Array.isArray(metadata?.probe_multiaddrs) ? metadata.probe_multiaddrs.length : 0,
3616
- browserBootstrapMultiaddrCount: Array.isArray(
3617
- metadata?.browser_bootstrap_multiaddrs
3618
- ) ? metadata.browser_bootstrap_multiaddrs.length : 0
3611
+ detail: "The 2n6 HTTPS route stayed inactive, so guest setup continued without Caddy. Secure browser routing can be enabled later when the proxy becomes available."
3619
3612
  });
3613
+ runtime = {
3614
+ ...runtime,
3615
+ proxyUrl: null,
3616
+ webAccess: runtime.webAccess ? {
3617
+ ...runtime.webAccess,
3618
+ active: false
3619
+ } : runtime.webAccess
3620
+ };
3620
3621
  }
3621
- });
3622
+ }
3623
+ let relayMetadata = bootstrapSignalRelayMetadata;
3624
+ if (relayMetadata) {
3625
+ this.trace("deploy:relay-metadata-from-bootstrap-signal", {
3626
+ itemHash: args.itemHash,
3627
+ peerId: relayMetadata.peerId,
3628
+ probeMultiaddrCount: relayMetadata.probeMultiaddrs.length,
3629
+ browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
3630
+ });
3631
+ } else {
3632
+ this.emitProgress({
3633
+ stage: "publishing-bootstrap",
3634
+ label: "Reading relay multiaddrs",
3635
+ progress: 95,
3636
+ status: "info",
3637
+ itemHash: args.itemHash,
3638
+ detail: "Waiting for the relay to report its final public multiaddrs."
3639
+ });
3640
+ relayMetadata = await fetchRelayMetadataForRuntime({
3641
+ runtime,
3642
+ fetch: (url, init) => fetch(url, init),
3643
+ preferSecureMetadata: profile === "uc-go-peer" && Boolean(runtime.proxyUrl),
3644
+ attempts: 80,
3645
+ delayMs: 3e3,
3646
+ timeoutMs: 24e4,
3647
+ onAttempt: (result) => {
3648
+ const payload = result.payload && typeof result.payload === "object" ? result.payload : null;
3649
+ const metadata = payload?.metadata && typeof payload.metadata === "object" ? payload.metadata : null;
3650
+ this.trace("deploy:relay-metadata-attempt", {
3651
+ itemHash: args.itemHash,
3652
+ attempt: result.attempt,
3653
+ attempts: result.attempts,
3654
+ requestUrl: result.requestUrl,
3655
+ metadataUrl: result.metadataUrl,
3656
+ hostIpv4: result.hostIpv4,
3657
+ setupPort: result.setupPort,
3658
+ ok: result.ok,
3659
+ status: result.status,
3660
+ ready: result.ready,
3661
+ error: result.error ?? null,
3662
+ payloadStatus: payload && typeof payload.status === "string" ? payload.status : null,
3663
+ peerId: metadata && typeof metadata.peer_id === "string" ? metadata.peer_id : null,
3664
+ probeMultiaddrCount: Array.isArray(metadata?.probe_multiaddrs) ? metadata.probe_multiaddrs.length : 0,
3665
+ browserBootstrapMultiaddrCount: Array.isArray(
3666
+ metadata?.browser_bootstrap_multiaddrs
3667
+ ) ? metadata.browser_bootstrap_multiaddrs.length : 0
3668
+ });
3669
+ }
3670
+ });
3671
+ }
3622
3672
  if (!relayMetadata) {
3623
3673
  throw new Error("Relay metadata did not include a peer ID and public multiaddrs.");
3624
3674
  }
@@ -3788,6 +3838,7 @@ var SponsorRelayController = class {
3788
3838
  const currentProgress = this.state.deploymentProgress;
3789
3839
  const currentProgressIsForLatestHash = currentProgress.itemHash === itemHash || currentProgress.itemHash == null && currentProgress.stage !== "idle" && currentProgress.stage !== "error";
3790
3840
  const keepTerminalSuccess = this.lastCompletedDeploymentHash === itemHash || currentProgressIsForLatestHash && currentProgress.stage === "completed" && currentProgress.status === "success";
3841
+ const keepSpecificInFlightProgress = currentProgressIsForLatestHash && currentProgress.stage !== "completed" && currentProgress.stage !== "error" && currentProgress.progress >= 93;
3791
3842
  const status = latest.details.messageStatus;
3792
3843
  if (status === "rejected") {
3793
3844
  this.emitProgress({
@@ -3830,6 +3881,16 @@ var SponsorRelayController = class {
3830
3881
  });
3831
3882
  return;
3832
3883
  }
3884
+ if (keepSpecificInFlightProgress) {
3885
+ this.trace("progress:retain-inflight", {
3886
+ reason: "latest refresh would overwrite a more specific in-flight deployment phase",
3887
+ itemHash,
3888
+ currentStage: currentProgress.stage,
3889
+ currentLabel: currentProgress.label,
3890
+ currentProgress: currentProgress.progress
3891
+ });
3892
+ return;
3893
+ }
3833
3894
  this.emitProgress({
3834
3895
  stage: "deployment-confirmed",
3835
3896
  label: "Waiting for runtime",
@@ -3840,6 +3901,16 @@ var SponsorRelayController = class {
3840
3901
  });
3841
3902
  return;
3842
3903
  }
3904
+ if (keepSpecificInFlightProgress) {
3905
+ this.trace("progress:retain-inflight", {
3906
+ reason: "latest refresh would overwrite a more specific in-flight deployment phase",
3907
+ itemHash,
3908
+ currentStage: currentProgress.stage,
3909
+ currentLabel: currentProgress.label,
3910
+ currentProgress: currentProgress.progress
3911
+ });
3912
+ return;
3913
+ }
3843
3914
  this.emitProgress({
3844
3915
  stage: "deployment-confirmed",
3845
3916
  label: "Runtime ready",
@@ -4470,6 +4541,15 @@ var SponsorRelayController = class {
4470
4541
  });
4471
4542
  if (attemptItemHash) {
4472
4543
  if (attemptDeploymentToken) {
4544
+ this.emitProgress({
4545
+ stage: "refreshing-instances",
4546
+ label: "Cleaning up failed attempt",
4547
+ progress: 16,
4548
+ status: "warning",
4549
+ itemHash: attemptItemHash,
4550
+ detail: `Removing bootstrap handoff state for failed deployment on ${attemptLabel}.`,
4551
+ error: lastError.message
4552
+ });
4473
4553
  this.trace("deploy:bootstrap-config-cleanup-start", {
4474
4554
  itemHash: attemptItemHash,
4475
4555
  deploymentToken: attemptDeploymentToken
@@ -4495,8 +4575,26 @@ var SponsorRelayController = class {
4495
4575
  deploymentToken: attemptDeploymentToken,
4496
4576
  error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4497
4577
  });
4578
+ this.emitProgress({
4579
+ stage: "refreshing-instances",
4580
+ label: "Cleanup warning",
4581
+ progress: 16,
4582
+ status: "warning",
4583
+ itemHash: attemptItemHash,
4584
+ detail: `Bootstrap cleanup reported an issue for ${attemptLabel}, but retry cleanup will continue.`,
4585
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4586
+ });
4498
4587
  });
4499
4588
  }
4589
+ this.emitProgress({
4590
+ stage: "refreshing-instances",
4591
+ label: "Discarding failed deployment",
4592
+ progress: 17,
4593
+ status: "warning",
4594
+ itemHash: attemptItemHash,
4595
+ detail: `Forgetting failed deployment ${attemptItemHash.slice(0, 12)} on ${attemptLabel} before retrying.`,
4596
+ error: lastError.message
4597
+ });
4500
4598
  this.trace("deploy:forget-failed-attempt-start", {
4501
4599
  itemHash: attemptItemHash,
4502
4600
  crnHash: candidateCrn.hash,
@@ -4519,12 +4617,30 @@ var SponsorRelayController = class {
4519
4617
  itemHash: attemptItemHash,
4520
4618
  error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4521
4619
  });
4620
+ this.emitProgress({
4621
+ stage: "refreshing-instances",
4622
+ label: "Cleanup warning",
4623
+ progress: 17,
4624
+ status: "warning",
4625
+ itemHash: attemptItemHash,
4626
+ detail: `Failed deployment cleanup reported an issue for ${attemptLabel}.`,
4627
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4628
+ });
4522
4629
  });
4523
4630
  this.trace("deploy:forget-failed-attempt-complete", {
4524
4631
  itemHash: attemptItemHash,
4525
4632
  crnHash: candidateCrn.hash,
4526
4633
  crnName: candidateCrn.name
4527
4634
  });
4635
+ this.emitProgress({
4636
+ stage: "refreshing-instances",
4637
+ label: "Cleanup complete",
4638
+ progress: 18,
4639
+ status: "info",
4640
+ itemHash: attemptItemHash,
4641
+ detail: `Finished cleaning up failed deployment on ${attemptLabel}.`,
4642
+ error: null
4643
+ });
4528
4644
  }
4529
4645
  if (candidateIndex < orderedCrns.length - 1) {
4530
4646
  this.emitProgress({
package/shared/index.d.ts CHANGED
@@ -290,7 +290,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
290
290
  declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
291
291
  declare const DEPLOYMENT_PENDING_WARNING_MS: number;
292
292
 
293
- declare const UI_PACKAGE_VERSION = "0.3.28";
293
+ declare const UI_PACKAGE_VERSION = "0.3.31";
294
294
 
295
295
  interface RootfsRequiredPortForward {
296
296
  port: number;
package/shared/index.js CHANGED
@@ -27,7 +27,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
27
27
  var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
28
28
 
29
29
  // src/shared/package-version.ts
30
- var UI_PACKAGE_VERSION = "0.3.28";
30
+ var UI_PACKAGE_VERSION = "0.3.31";
31
31
 
32
32
  // src/shared/format.ts
33
33
  function shortHash(value, head = 8, tail = 6) {
@@ -2868,7 +2868,14 @@ function normalizeVmBootstrapConfigSignalRecord(value) {
2868
2868
  instanceItemHash,
2869
2869
  updatedAt,
2870
2870
  publisherAddress: typeof candidate.publisherAddress === "string" && candidate.publisherAddress.trim() ? candidate.publisherAddress.trim() : null,
2871
- authorization: candidate.authorization
2871
+ authorization: candidate.authorization,
2872
+ peerId: typeof candidate.peerId === "string" && candidate.peerId.trim() ? candidate.peerId.trim() : null,
2873
+ probeMultiaddrs: Array.isArray(candidate.probeMultiaddrs) ? candidate.probeMultiaddrs.filter(
2874
+ (entry) => typeof entry === "string" && entry.trim().length > 0
2875
+ ) : [],
2876
+ browserBootstrapMultiaddrs: Array.isArray(candidate.browserBootstrapMultiaddrs) ? candidate.browserBootstrapMultiaddrs.filter(
2877
+ (entry) => typeof entry === "string" && entry.trim().length > 0
2878
+ ) : []
2872
2879
  };
2873
2880
  }
2874
2881
  async function fetchVmBootstrapConfigSignals(args) {
@@ -3400,6 +3407,7 @@ var SponsorRelayController = class {
3400
3407
  if (!setupPort) {
3401
3408
  throw new Error("Relay runtime did not expose the temporary setup endpoint.");
3402
3409
  }
3410
+ let bootstrapSignalRelayMetadata = null;
3403
3411
  if (profile === "orbitdb-relay-pinner") {
3404
3412
  this.emitProgress({
3405
3413
  stage: "deployment-confirmed",
@@ -3482,6 +3490,14 @@ var SponsorRelayController = class {
3482
3490
  crns: this.state.crns,
3483
3491
  crnListUrl: this.props.crnListUrl
3484
3492
  }).catch(() => latestRuntime);
3493
+ this.emitProgress({
3494
+ stage: "deployment-confirmed",
3495
+ label: "Waiting for HTTPS route",
3496
+ progress: 93,
3497
+ status: latestRuntime.webAccess?.active === true ? "info" : "warning",
3498
+ itemHash: args.itemHash,
3499
+ detail: `2n6 activation ${attempt + 1}/${UI_RUNTIME_WAIT_ATTEMPTS}: ${latestRuntime.webAccess?.active === true ? "active" : "still pending"} for ${latestRuntime.proxyUrl ?? runtime.proxyUrl ?? "reserved proxy URL"}.`
3500
+ });
3485
3501
  this.trace("deploy:bootstrap-proxy-activation", {
3486
3502
  itemHash: args.itemHash,
3487
3503
  attempt: attempt + 1,
@@ -3492,11 +3508,6 @@ var SponsorRelayController = class {
3492
3508
  }
3493
3509
  runtime = latestRuntime;
3494
3510
  mappedPorts2 = runtime.mappedPorts ?? mappedPorts2;
3495
- if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
3496
- throw new Error(
3497
- "Aleph reserved a 2n6 proxy URL, but it never became active in time. Aborting guest HTTPS configuration to avoid a broken Caddy setup."
3498
- );
3499
- }
3500
3511
  }
3501
3512
  if (!runtime.hostIpv4) {
3502
3513
  throw new Error("Relay runtime lost its host IPv4 address while waiting for HTTPS activation.");
@@ -3578,46 +3589,85 @@ var SponsorRelayController = class {
3578
3589
  "The relay VM did not confirm that it applied the Aleph bootstrap config in time."
3579
3590
  );
3580
3591
  }
3581
- }
3582
- this.emitProgress({
3583
- stage: "publishing-bootstrap",
3584
- label: "Reading relay multiaddrs",
3585
- progress: 95,
3586
- status: "info",
3587
- itemHash: args.itemHash,
3588
- detail: "Waiting for the relay to report its final public multiaddrs."
3589
- });
3590
- const relayMetadata = await fetchRelayMetadataForRuntime({
3591
- runtime,
3592
- fetch: (url, init) => fetch(url, init),
3593
- preferSecureMetadata: profile === "uc-go-peer",
3594
- attempts: 80,
3595
- delayMs: 3e3,
3596
- timeoutMs: 24e4,
3597
- onAttempt: (result) => {
3598
- const payload = result.payload && typeof result.payload === "object" ? result.payload : null;
3599
- const metadata = payload?.metadata && typeof payload.metadata === "object" ? payload.metadata : null;
3600
- this.trace("deploy:relay-metadata-attempt", {
3592
+ bootstrapSignalRelayMetadata = typeof bootstrapConfigSignal.peerId === "string" && bootstrapConfigSignal.peerId.length > 0 && Array.isArray(bootstrapConfigSignal.probeMultiaddrs) && bootstrapConfigSignal.probeMultiaddrs.length > 0 ? {
3593
+ peerId: bootstrapConfigSignal.peerId,
3594
+ probeMultiaddrs: bootstrapConfigSignal.probeMultiaddrs,
3595
+ browserBootstrapMultiaddrs: bootstrapConfigSignal.browserBootstrapMultiaddrs ?? []
3596
+ } : null;
3597
+ if (runtime.proxyUrl && runtime.webAccess?.active !== true) {
3598
+ this.trace("deploy:bootstrap-proxy-fallback", {
3599
+ itemHash: args.itemHash,
3600
+ deploymentToken: args.deploymentToken,
3601
+ proxyUrl: runtime.proxyUrl,
3602
+ bootstrapSignalRelayMetadata
3603
+ });
3604
+ this.emitProgress({
3605
+ stage: "deployment-confirmed",
3606
+ label: "Continuing without HTTPS route",
3607
+ progress: 94,
3608
+ status: "warning",
3601
3609
  itemHash: args.itemHash,
3602
- attempt: result.attempt,
3603
- attempts: result.attempts,
3604
- requestUrl: result.requestUrl,
3605
- metadataUrl: result.metadataUrl,
3606
- hostIpv4: result.hostIpv4,
3607
- setupPort: result.setupPort,
3608
- ok: result.ok,
3609
- status: result.status,
3610
- ready: result.ready,
3611
- error: result.error ?? null,
3612
- payloadStatus: payload && typeof payload.status === "string" ? payload.status : null,
3613
- peerId: metadata && typeof metadata.peer_id === "string" ? metadata.peer_id : null,
3614
- probeMultiaddrCount: Array.isArray(metadata?.probe_multiaddrs) ? metadata.probe_multiaddrs.length : 0,
3615
- browserBootstrapMultiaddrCount: Array.isArray(
3616
- metadata?.browser_bootstrap_multiaddrs
3617
- ) ? metadata.browser_bootstrap_multiaddrs.length : 0
3610
+ detail: "The 2n6 HTTPS route stayed inactive, so guest setup continued without Caddy. Secure browser routing can be enabled later when the proxy becomes available."
3618
3611
  });
3612
+ runtime = {
3613
+ ...runtime,
3614
+ proxyUrl: null,
3615
+ webAccess: runtime.webAccess ? {
3616
+ ...runtime.webAccess,
3617
+ active: false
3618
+ } : runtime.webAccess
3619
+ };
3619
3620
  }
3620
- });
3621
+ }
3622
+ let relayMetadata = bootstrapSignalRelayMetadata;
3623
+ if (relayMetadata) {
3624
+ this.trace("deploy:relay-metadata-from-bootstrap-signal", {
3625
+ itemHash: args.itemHash,
3626
+ peerId: relayMetadata.peerId,
3627
+ probeMultiaddrCount: relayMetadata.probeMultiaddrs.length,
3628
+ browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
3629
+ });
3630
+ } else {
3631
+ this.emitProgress({
3632
+ stage: "publishing-bootstrap",
3633
+ label: "Reading relay multiaddrs",
3634
+ progress: 95,
3635
+ status: "info",
3636
+ itemHash: args.itemHash,
3637
+ detail: "Waiting for the relay to report its final public multiaddrs."
3638
+ });
3639
+ relayMetadata = await fetchRelayMetadataForRuntime({
3640
+ runtime,
3641
+ fetch: (url, init) => fetch(url, init),
3642
+ preferSecureMetadata: profile === "uc-go-peer" && Boolean(runtime.proxyUrl),
3643
+ attempts: 80,
3644
+ delayMs: 3e3,
3645
+ timeoutMs: 24e4,
3646
+ onAttempt: (result) => {
3647
+ const payload = result.payload && typeof result.payload === "object" ? result.payload : null;
3648
+ const metadata = payload?.metadata && typeof payload.metadata === "object" ? payload.metadata : null;
3649
+ this.trace("deploy:relay-metadata-attempt", {
3650
+ itemHash: args.itemHash,
3651
+ attempt: result.attempt,
3652
+ attempts: result.attempts,
3653
+ requestUrl: result.requestUrl,
3654
+ metadataUrl: result.metadataUrl,
3655
+ hostIpv4: result.hostIpv4,
3656
+ setupPort: result.setupPort,
3657
+ ok: result.ok,
3658
+ status: result.status,
3659
+ ready: result.ready,
3660
+ error: result.error ?? null,
3661
+ payloadStatus: payload && typeof payload.status === "string" ? payload.status : null,
3662
+ peerId: metadata && typeof metadata.peer_id === "string" ? metadata.peer_id : null,
3663
+ probeMultiaddrCount: Array.isArray(metadata?.probe_multiaddrs) ? metadata.probe_multiaddrs.length : 0,
3664
+ browserBootstrapMultiaddrCount: Array.isArray(
3665
+ metadata?.browser_bootstrap_multiaddrs
3666
+ ) ? metadata.browser_bootstrap_multiaddrs.length : 0
3667
+ });
3668
+ }
3669
+ });
3670
+ }
3621
3671
  if (!relayMetadata) {
3622
3672
  throw new Error("Relay metadata did not include a peer ID and public multiaddrs.");
3623
3673
  }
@@ -3787,6 +3837,7 @@ var SponsorRelayController = class {
3787
3837
  const currentProgress = this.state.deploymentProgress;
3788
3838
  const currentProgressIsForLatestHash = currentProgress.itemHash === itemHash || currentProgress.itemHash == null && currentProgress.stage !== "idle" && currentProgress.stage !== "error";
3789
3839
  const keepTerminalSuccess = this.lastCompletedDeploymentHash === itemHash || currentProgressIsForLatestHash && currentProgress.stage === "completed" && currentProgress.status === "success";
3840
+ const keepSpecificInFlightProgress = currentProgressIsForLatestHash && currentProgress.stage !== "completed" && currentProgress.stage !== "error" && currentProgress.progress >= 93;
3790
3841
  const status = latest.details.messageStatus;
3791
3842
  if (status === "rejected") {
3792
3843
  this.emitProgress({
@@ -3829,6 +3880,16 @@ var SponsorRelayController = class {
3829
3880
  });
3830
3881
  return;
3831
3882
  }
3883
+ if (keepSpecificInFlightProgress) {
3884
+ this.trace("progress:retain-inflight", {
3885
+ reason: "latest refresh would overwrite a more specific in-flight deployment phase",
3886
+ itemHash,
3887
+ currentStage: currentProgress.stage,
3888
+ currentLabel: currentProgress.label,
3889
+ currentProgress: currentProgress.progress
3890
+ });
3891
+ return;
3892
+ }
3832
3893
  this.emitProgress({
3833
3894
  stage: "deployment-confirmed",
3834
3895
  label: "Waiting for runtime",
@@ -3839,6 +3900,16 @@ var SponsorRelayController = class {
3839
3900
  });
3840
3901
  return;
3841
3902
  }
3903
+ if (keepSpecificInFlightProgress) {
3904
+ this.trace("progress:retain-inflight", {
3905
+ reason: "latest refresh would overwrite a more specific in-flight deployment phase",
3906
+ itemHash,
3907
+ currentStage: currentProgress.stage,
3908
+ currentLabel: currentProgress.label,
3909
+ currentProgress: currentProgress.progress
3910
+ });
3911
+ return;
3912
+ }
3842
3913
  this.emitProgress({
3843
3914
  stage: "deployment-confirmed",
3844
3915
  label: "Runtime ready",
@@ -4469,6 +4540,15 @@ var SponsorRelayController = class {
4469
4540
  });
4470
4541
  if (attemptItemHash) {
4471
4542
  if (attemptDeploymentToken) {
4543
+ this.emitProgress({
4544
+ stage: "refreshing-instances",
4545
+ label: "Cleaning up failed attempt",
4546
+ progress: 16,
4547
+ status: "warning",
4548
+ itemHash: attemptItemHash,
4549
+ detail: `Removing bootstrap handoff state for failed deployment on ${attemptLabel}.`,
4550
+ error: lastError.message
4551
+ });
4472
4552
  this.trace("deploy:bootstrap-config-cleanup-start", {
4473
4553
  itemHash: attemptItemHash,
4474
4554
  deploymentToken: attemptDeploymentToken
@@ -4494,8 +4574,26 @@ var SponsorRelayController = class {
4494
4574
  deploymentToken: attemptDeploymentToken,
4495
4575
  error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4496
4576
  });
4577
+ this.emitProgress({
4578
+ stage: "refreshing-instances",
4579
+ label: "Cleanup warning",
4580
+ progress: 16,
4581
+ status: "warning",
4582
+ itemHash: attemptItemHash,
4583
+ detail: `Bootstrap cleanup reported an issue for ${attemptLabel}, but retry cleanup will continue.`,
4584
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4585
+ });
4497
4586
  });
4498
4587
  }
4588
+ this.emitProgress({
4589
+ stage: "refreshing-instances",
4590
+ label: "Discarding failed deployment",
4591
+ progress: 17,
4592
+ status: "warning",
4593
+ itemHash: attemptItemHash,
4594
+ detail: `Forgetting failed deployment ${attemptItemHash.slice(0, 12)} on ${attemptLabel} before retrying.`,
4595
+ error: lastError.message
4596
+ });
4499
4597
  this.trace("deploy:forget-failed-attempt-start", {
4500
4598
  itemHash: attemptItemHash,
4501
4599
  crnHash: candidateCrn.hash,
@@ -4518,12 +4616,30 @@ var SponsorRelayController = class {
4518
4616
  itemHash: attemptItemHash,
4519
4617
  error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4520
4618
  });
4619
+ this.emitProgress({
4620
+ stage: "refreshing-instances",
4621
+ label: "Cleanup warning",
4622
+ progress: 17,
4623
+ status: "warning",
4624
+ itemHash: attemptItemHash,
4625
+ detail: `Failed deployment cleanup reported an issue for ${attemptLabel}.`,
4626
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
4627
+ });
4521
4628
  });
4522
4629
  this.trace("deploy:forget-failed-attempt-complete", {
4523
4630
  itemHash: attemptItemHash,
4524
4631
  crnHash: candidateCrn.hash,
4525
4632
  crnName: candidateCrn.name
4526
4633
  });
4634
+ this.emitProgress({
4635
+ stage: "refreshing-instances",
4636
+ label: "Cleanup complete",
4637
+ progress: 18,
4638
+ status: "info",
4639
+ itemHash: attemptItemHash,
4640
+ detail: `Finished cleaning up failed deployment on ${attemptLabel}.`,
4641
+ error: null
4642
+ });
4527
4643
  }
4528
4644
  if (candidateIndex < orderedCrns.length - 1) {
4529
4645
  this.emitProgress({