@le-space/ui 0.9.8 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/shared/index.d.ts CHANGED
@@ -1,6 +1,17 @@
1
+ import { AttestWasm } from '@le-space/attest-wasm/instance';
2
+
1
3
  type CrnSource = 'list' | 'aggregate';
2
4
  type CrnSourcePreference = 'auto' | 'aggregate' | 'list';
3
5
 
6
+ interface EthereumProviderLike {
7
+ isMetaMask?: boolean;
8
+ request<T = unknown>(args: {
9
+ method: string;
10
+ params?: unknown[] | Record<string, unknown>;
11
+ }): Promise<T>;
12
+ on?(event: string, listener: (...args: unknown[]) => void): void;
13
+ removeListener?(event: string, listener: (...args: unknown[]) => void): void;
14
+ }
4
15
  type MessageStatus = 'processed' | 'pending' | 'rejected' | 'removing' | 'removed' | 'unknown';
5
16
  interface BalanceResponse {
6
17
  address: string;
@@ -64,7 +75,17 @@ interface Crn {
64
75
  gpu_support?: boolean;
65
76
  system_usage?: CrnUsage | null;
66
77
  payment_receiver_address?: string | null;
78
+ /** Registered owner (corechannel aggregate). */
79
+ owner?: string | null;
67
80
  version?: string | null;
81
+ /** CPU features from the node's /about/usage/system, e.g. ["sev", "sev_es", "sev_snp"]. */
82
+ cpu_features?: string[] | null;
83
+ /** TEE properties from /about/usage/system; present on SEV-SNP nodes. */
84
+ tee?: {
85
+ sev_snp?: {
86
+ supported_vcpu_types?: string[];
87
+ };
88
+ } | null;
68
89
  city?: string | null;
69
90
  region?: string | null;
70
91
  country?: string | null;
@@ -184,7 +205,7 @@ interface RootfsResolution {
184
205
  gatewayError?: string | null;
185
206
  }
186
207
 
187
- type DeploymentProgressStage = "idle" | "validating" | "loading-manifest" | "verifying-rootfs" | "loading-pricing" | "loading-balance" | "selecting-crn" | "building-message" | "signing-message" | "broadcasting" | "notifying-crn" | "waiting-for-aleph" | "deployment-confirmed" | "deployment-rejected" | "publishing-bootstrap" | "building-delete-message" | "signing-delete-message" | "broadcasting-delete" | "delete-completed" | "refreshing-instances" | "completed" | "error";
208
+ type DeploymentProgressStage = "idle" | "validating" | "loading-manifest" | "verifying-rootfs" | "loading-pricing" | "loading-balance" | "selecting-crn" | "building-message" | "signing-message" | "broadcasting" | "notifying-crn" | "preparing-confidential" | "attesting-guest" | "unlocking-guest" | "waiting-for-aleph" | "deployment-confirmed" | "deployment-rejected" | "publishing-bootstrap" | "building-delete-message" | "signing-delete-message" | "broadcasting-delete" | "delete-completed" | "refreshing-instances" | "completed" | "error";
188
209
  interface DeploymentProgressEvent {
189
210
  stage: DeploymentProgressStage;
190
211
  label: string;
@@ -278,6 +299,27 @@ interface SponsorRelayUcanStoreBootstrapInput {
278
299
  pwaOrigin: string;
279
300
  serviceOrigin: string;
280
301
  }
302
+ interface SponsorRelayConfidentialStart {
303
+ /** STORE item hash of the LUKS-encrypted rootfs (aleph-confidential-rootfs, or the reusable workflow's confidential_rootfs_item_hash). */
304
+ rootfsItemHash: string;
305
+ /** Its size in MiB, if larger than the manifest's rootfs. */
306
+ rootfsSizeMiB?: number;
307
+ /** `wss://…/attest` of an attest relay (@le-space/attest-relay). */
308
+ relayUrl: string;
309
+ /**
310
+ * Loads the attestation WASM, e.g.
311
+ * `async () => { const m = await import('@le-space/attest-wasm/pkg/relay_button_attest.js'); await m.default(); return m }`.
312
+ */
313
+ loadWasm: () => Promise<AttestWasm>;
314
+ /** An SNP instance runtime by name (vm-images); the network's default if absent. */
315
+ runtimeName?: string;
316
+ /**
317
+ * localStorage key under which nodes AMD cannot vouch for (KDS has no VCEK
318
+ * for their chip) are remembered for a week and tried last. Omit it and
319
+ * they are remembered for the page only.
320
+ */
321
+ refusedNodesStorageKey?: string;
322
+ }
281
323
  interface SponsorRelayProps {
282
324
  debug?: boolean;
283
325
  manifestUrl?: string;
@@ -298,6 +340,21 @@ interface SponsorRelayProps {
298
340
  * fallback. `localStorage.LE_SPACE_CRN_SOURCE` overrides this at runtime.
299
341
  */
300
342
  crnSource?: CrnSourcePreference;
343
+ /**
344
+ * Ask for a confidential VM (AMD SEV-SNP): only nodes that report SEV-SNP and
345
+ * run a patched aleph-vm are offered, and pricing uses Aleph's
346
+ * `instance_confidential` entry. The person can switch it in the panel too.
347
+ * Starting one needs `confidentialStart`; without it the panel refuses.
348
+ */
349
+ confidential?: boolean;
350
+ /**
351
+ * What a confidential start needs (relay-button#169): the encrypted rootfs,
352
+ * an attest relay, and the attestation WASM. The browser computes the
353
+ * launch measurements for the connected wallet, signs the INSTANCE with
354
+ * them, verifies the guest through the relay against AMD, and unlocks it
355
+ * with the passphrase the person enters, signed by their wallet.
356
+ */
357
+ confidentialStart?: SponsorRelayConfidentialStart;
301
358
  schedulerApiHost?: string;
302
359
  twoN6ApiHost?: string;
303
360
  /**
@@ -416,6 +473,12 @@ interface SponsorRelayState {
416
473
  instanceName: string;
417
474
  ucanStoreBootstrap: SponsorRelayUcanStoreBootstrapInput;
418
475
  tierId: string;
476
+ /** Confidential VM requested (AMD SEV-SNP); see the `confidential` prop. */
477
+ confidential: boolean;
478
+ /** Whether the host set `confidentialStart`, so a confidential VM can start. */
479
+ confidentialStartAvailable: boolean;
480
+ /** The encrypted rootfs's passphrase, held only until the unlock; never stored. */
481
+ confidentialPassphrase: string;
419
482
  showAdvanced: boolean;
420
483
  showInstances: boolean;
421
484
  showPasteManifest: boolean;
@@ -443,6 +506,12 @@ interface SponsorRelayState {
443
506
  hash: string;
444
507
  name: string | null;
445
508
  score: number | null;
509
+ /** ISO country code, when known. */
510
+ country: string | null;
511
+ /** aleph-vm version, when known. */
512
+ version: string | null;
513
+ /** Shortened owner / reward address: nodes of one operator share it. */
514
+ operator: string | null;
446
515
  }>;
447
516
  crnPinnedByUser: boolean;
448
517
  instances: CompactInstanceRecord[];
@@ -480,7 +549,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
480
549
  declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
481
550
  declare const DEPLOYMENT_PENDING_WARNING_MS: number;
482
551
 
483
- declare const UI_PACKAGE_VERSION = "0.9.8";
552
+ declare const UI_PACKAGE_VERSION = "0.10.0";
484
553
 
485
554
  interface RootfsRequiredPortForward {
486
555
  port: number;
@@ -496,25 +565,35 @@ declare function formatTierSpecLabel(vcpus: number | null | undefined, memoryMiB
496
565
  declare function buildSshCommand(hostIpv4: string | null, mappedPorts: CompactInstanceRecord["details"]["mappedPorts"]): string | null;
497
566
  declare function joinMappedPorts(mappedPorts: CompactInstanceRecord["details"]["mappedPorts"]): string;
498
567
  declare function joinRequiredPortForwards(portForwards: ReadonlyArray<RootfsRequiredPortForward> | null | undefined): string;
568
+ /**
569
+ * One line per node in the CRN picker: name and score, and for a confidential
570
+ * VM also country, aleph-vm version and operator — few nodes qualify, often
571
+ * several from one operator, and the person should see that.
572
+ */
573
+ declare function formatCrnOptionLabel(option: {
574
+ hash: string;
575
+ name: string | null;
576
+ score: number | null;
577
+ country?: string | null;
578
+ version?: string | null;
579
+ operator?: string | null;
580
+ }, confidential?: boolean): string;
499
581
 
500
582
  declare function resolveManifestSource(args: {
501
583
  manifestJson: string;
502
584
  }): RootfsManifestState | null;
503
585
 
504
- interface EthereumProviderLike {
505
- isMetaMask?: boolean;
506
- request<T = unknown>(args: {
507
- method: string;
508
- params?: unknown[] | Record<string, unknown>;
509
- }): Promise<T>;
510
- on?(event: string, listener: (...args: unknown[]) => void): void;
511
- removeListener?(event: string, listener: (...args: unknown[]) => void): void;
512
- }
586
+ declare function personalSign(address: string, message: string, provider?: EthereumProviderLike | null | undefined): Promise<string>;
587
+
513
588
  declare function getEthereumProvider(): EthereumProviderLike | null;
589
+ declare function watchWallet(onChange: () => void, provider?: EthereumProviderLike | null | undefined): () => void;
590
+
514
591
  declare function toChecksumAddress(address: string): string;
592
+ /**
593
+ * The wallet helpers live in `@le-space/browser`, which carries no runtime
594
+ * dependencies. Checksumming needs viem, so this package supplies it.
595
+ */
515
596
  declare function connectWallet(provider?: EthereumProviderLike | null): Promise<SponsorRelayWalletState>;
516
- declare function personalSign(address: string, message: string, provider?: EthereumProviderLike | null): Promise<string>;
517
- declare function watchWallet(onChange: () => void, provider?: EthereumProviderLike | null): () => void;
518
597
 
519
598
  /**
520
599
  * What a request was, for an error that otherwise says nothing.
@@ -615,6 +694,16 @@ declare class SponsorRelayController {
615
694
  setUcanStoreBootstrapField(field: keyof SponsorRelayUcanStoreBootstrapInput, value: string): void;
616
695
  setTierId(tierId: string): void;
617
696
  private recomputePricingSummary;
697
+ /**
698
+ * Switch between a normal and a confidential VM. Pricing and the node list
699
+ * differ between the two, so both are loaded again.
700
+ */
701
+ setConfidential(confidential: boolean): Promise<void>;
702
+ /**
703
+ * The encrypted rootfs's passphrase for a confidential start. Kept in
704
+ * memory only until the unlock, then cleared; never persisted.
705
+ */
706
+ setConfidentialPassphrase(passphrase: string): void;
618
707
  /** Pin a specific CRN as the first deploy attempt (null = automatic). */
619
708
  selectCrn(hash: string | null): void;
620
709
  private queueManifestRefresh;
@@ -646,4 +735,16 @@ interface DeploymentProgressEmitter {
646
735
  }
647
736
  declare function createDeploymentProgressEmitter(): DeploymentProgressEmitter;
648
737
 
649
- export { type CompactBootstrapRegistrationRecord, type CompactInstanceDetails, type CompactInstanceRecord, DEFAULT_FAB_CORNER, DEFAULT_INSTANCE_NAME, DEFAULT_MANIFEST_URL, DEFAULT_TIER_ID, DEFAULT_UCAN_STORE_ALLOWED_CAPABILITIES, DEFAULT_UCAN_STORE_MAX_DELEGATION_EXPIRATION_SECONDS, DEFAULT_UCAN_STORE_PWA_ORIGIN, DEFAULT_UCAN_STORE_SERVICE_DID, DEFAULT_UCAN_STORE_SERVICE_ORIGIN, DEFAULT_UCAN_STORE_USER_DELEGATION_EXPIRATION_SECONDS, DEPLOYMENT_PENDING_WARNING_MS, type DeploymentProgressEmitter, type EthereumProviderLike, FAB_DRAG_THRESHOLD, FAB_EDGE_MARGIN, type FabCorner, type FabPanelPlacement, type FabPanelSide, type FabPlacement, type FabPoint, type FabSize, type FabViewport, IDLE_DEPLOYMENT_PROGRESS, INSTANCE_RUNTIME_PENDING_REFRESH_MS, INSTANCE_RUNTIME_READY_REFRESH_MS, INSTANCE_RUNTIME_STALE_REFRESH_MS, MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS, RECENT_INSTANCE_RUNTIME_GRACE_MS, REFRESH_INTERVAL_MS, ROOTFS_MISSING_STATE, STALE_INSTANCE_ALLOCATION_COOLDOWN_MS, type SponsorRelayAddressGroup, SponsorRelayController, type SponsorRelayHealthTone, type SponsorRelayInstanceAddresses, type SponsorRelayPricingSummary, type SponsorRelayProps, type SponsorRelayRootfsHealth, type SponsorRelayState, type SponsorRelaySubscriber, type SponsorRelayUcanStoreBootstrapInput, type SponsorRelayWalletState, UI_PACKAGE_VERSION, anchorPanelToLauncher, buildSshCommand, clampToViewport, connectWallet, createDeploymentProgressEmitter, createSponsorRelayController, deploymentFailureMessage, describeRequest, describeThrown, dragExceedsThreshold, formatDateTime, formatNumber, formatTierSpecLabel, getEthereumProvider, joinMappedPorts, joinRequiredPortForwards, parseInstanceAddressPayload, personalSign, readStoredPosition, resolveCornerPlacement, resolveManifestSource, rootfsHealth, shortHash, toChecksumAddress, watchWallet, writeStoredPosition };
738
+ /** The verdict that means "AMD has no certificate for this chip". */
739
+ declare function isUnverifiableNodeError(message: string): boolean;
740
+ /** Hashes of nodes refused within the last week. */
741
+ declare function unverifiableCrnHashes(storageKey?: string, now?: number): Set<string>;
742
+ declare function rememberUnverifiableCrn(hash: string, storageKey?: string, now?: number): void;
743
+ /** `crns` with the remembered nodes moved to the end, except one the person pinned. */
744
+ declare function demoteUnverifiableCrns<T extends {
745
+ hash: string;
746
+ }>(crns: T[], refused: Set<string>, pinned: string | null): T[];
747
+ /** Tests only. */
748
+ declare function forgetUnverifiableCrns(): void;
749
+
750
+ export { type CompactBootstrapRegistrationRecord, type CompactInstanceDetails, type CompactInstanceRecord, DEFAULT_FAB_CORNER, DEFAULT_INSTANCE_NAME, DEFAULT_MANIFEST_URL, DEFAULT_TIER_ID, DEFAULT_UCAN_STORE_ALLOWED_CAPABILITIES, DEFAULT_UCAN_STORE_MAX_DELEGATION_EXPIRATION_SECONDS, DEFAULT_UCAN_STORE_PWA_ORIGIN, DEFAULT_UCAN_STORE_SERVICE_DID, DEFAULT_UCAN_STORE_SERVICE_ORIGIN, DEFAULT_UCAN_STORE_USER_DELEGATION_EXPIRATION_SECONDS, DEPLOYMENT_PENDING_WARNING_MS, type DeploymentProgressEmitter, type EthereumProviderLike, FAB_DRAG_THRESHOLD, FAB_EDGE_MARGIN, type FabCorner, type FabPanelPlacement, type FabPanelSide, type FabPlacement, type FabPoint, type FabSize, type FabViewport, IDLE_DEPLOYMENT_PROGRESS, INSTANCE_RUNTIME_PENDING_REFRESH_MS, INSTANCE_RUNTIME_READY_REFRESH_MS, INSTANCE_RUNTIME_STALE_REFRESH_MS, MANIFEST_SOURCE_REFRESH_DEBOUNCE_MS, RECENT_INSTANCE_RUNTIME_GRACE_MS, REFRESH_INTERVAL_MS, ROOTFS_MISSING_STATE, STALE_INSTANCE_ALLOCATION_COOLDOWN_MS, type SponsorRelayAddressGroup, type SponsorRelayConfidentialStart, SponsorRelayController, type SponsorRelayHealthTone, type SponsorRelayInstanceAddresses, type SponsorRelayPricingSummary, type SponsorRelayProps, type SponsorRelayRootfsHealth, type SponsorRelayState, type SponsorRelaySubscriber, type SponsorRelayUcanStoreBootstrapInput, type SponsorRelayWalletState, UI_PACKAGE_VERSION, anchorPanelToLauncher, buildSshCommand, clampToViewport, connectWallet, createDeploymentProgressEmitter, createSponsorRelayController, demoteUnverifiableCrns, deploymentFailureMessage, describeRequest, describeThrown, dragExceedsThreshold, forgetUnverifiableCrns, formatCrnOptionLabel, formatDateTime, formatNumber, formatTierSpecLabel, getEthereumProvider, isUnverifiableNodeError, joinMappedPorts, joinRequiredPortForwards, parseInstanceAddressPayload, personalSign, readStoredPosition, rememberUnverifiableCrn, resolveCornerPlacement, resolveManifestSource, rootfsHealth, shortHash, toChecksumAddress, unverifiableCrnHashes, watchWallet, writeStoredPosition };