dsh-mobile 0.6.18 → 0.7.1

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 (42) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/CONTRIBUTORS.md +4 -1
  3. package/README.en.md +34 -20
  4. package/README.md +34 -20
  5. package/SECURITY.md +7 -0
  6. package/THIRD_PARTY_NOTICES.md +33 -0
  7. package/apps/mobile/README.md +28 -3
  8. package/apps/mobile/README.zh-CN.md +28 -3
  9. package/apps/mobile/release.json +3 -3
  10. package/docs/CADDY_MANAGED.en.md +1 -1
  11. package/docs/CADDY_MANAGED.md +1 -1
  12. package/docs/CLIENT_MODULES.en.md +2 -0
  13. package/docs/CLIENT_MODULES.md +2 -0
  14. package/docs/CLOUDFLARE_TUNNEL.en.md +7 -5
  15. package/docs/CLOUDFLARE_TUNNEL.md +7 -5
  16. package/docs/CPOLAR_SUBDOMAIN.en.md +2 -2
  17. package/docs/CPOLAR_SUBDOMAIN.md +2 -2
  18. package/docs/IROH.en.md +65 -0
  19. package/docs/IROH.md +65 -0
  20. package/docs/MOBILE_PLUGIN_ADAPTATION.en.md +8 -0
  21. package/docs/MOBILE_PLUGIN_ADAPTATION.md +8 -0
  22. package/docs/README.md +2 -1
  23. package/docs/SELF_HOSTED_ORIGIN.en.md +26 -1
  24. package/docs/SELF_HOSTED_ORIGIN.md +27 -2
  25. package/docs/SKIN_COMPATIBILITY.en.md +2 -0
  26. package/docs/SKIN_COMPATIBILITY.md +2 -0
  27. package/docs/SLOW_CONNECTIONS.en.md +8 -0
  28. package/docs/SLOW_CONNECTIONS.md +8 -0
  29. package/lib/cli.js.map +1 -1
  30. package/lib/client.js +1475 -240
  31. package/lib/client.js.map +1 -1
  32. package/lib/index.d.mts +270 -2
  33. package/lib/index.mjs +1934 -251
  34. package/lib/index.mjs.map +1 -1
  35. package/lib/mobile-layout.js +17 -6
  36. package/lib/mobile-layout.js.map +1 -1
  37. package/native/iroh-host/LICENSE.dsh-mobile-iroh +21 -0
  38. package/native/iroh-host/LICENSE.dsh-tether +21 -0
  39. package/native/iroh-host/NOTICE.dsh-mobile-iroh +13 -0
  40. package/native/iroh-host/README.md +66 -0
  41. package/package.json +14 -5
  42. package/packages/question-fixes/package.json +1 -1
package/lib/index.d.mts CHANGED
@@ -1842,7 +1842,7 @@ export declare function issueServerCertificate(authority: ServerCertificateAutho
1842
1842
  //#endregion
1843
1843
  //#region src/remote.d.ts
1844
1844
  /** Remote transports supported by the desktop plugin and Android client. */
1845
- type RemoteProvider = 'tailscale' | 'cpolar' | 'cloudflared' | 'frp' | 'origin';
1845
+ type RemoteProvider = 'tailscale' | 'cpolar' | 'cloudflared' | 'frp' | 'origin' | 'iroh';
1846
1846
  /** Common safe status returned by every remote provider controller. */
1847
1847
  interface RemoteProviderStatus {
1848
1848
  readonly enabled: boolean;
@@ -2367,6 +2367,274 @@ export declare class CloudflaredController implements RemoteProviderController {
2367
2367
  private stopProcessAndGateway;
2368
2368
  }
2369
2369
  //#endregion
2370
+ //#region src/iroh-component.d.ts
2371
+ export declare const IROH_VERSION = "0.1.0-alpha.1";
2372
+ /** A size- and content-pinned sidecar release asset with independent wire and installed-byte checks. */
2373
+ interface IrohArtifact {
2374
+ readonly version: string;
2375
+ readonly platform: NodeJS.Platform;
2376
+ readonly arch: string;
2377
+ readonly downloadUrl: string;
2378
+ readonly downloadBytes: number;
2379
+ readonly downloadSha256: string;
2380
+ readonly executableName: string;
2381
+ readonly executableBytes: number;
2382
+ readonly executableSha256: string;
2383
+ }
2384
+ export declare const IROH_COMPONENT_RELEASES: Readonly<Record<string, IrohArtifact>>;
2385
+ /** Public, credential-free description of the iroh sidecar. */
2386
+ interface IrohComponentStatus {
2387
+ readonly supported: boolean;
2388
+ readonly installed: boolean;
2389
+ readonly version: string;
2390
+ readonly downloadBytes: number;
2391
+ readonly installedBytes: number;
2392
+ readonly sourceUrl: string;
2393
+ readonly releasePage: string;
2394
+ readonly storagePath: string;
2395
+ readonly errorCode?: string;
2396
+ }
2397
+ interface IrohComponentManagerOptions {
2398
+ readonly stateDirectory: string;
2399
+ readonly platform?: NodeJS.Platform;
2400
+ readonly arch?: string;
2401
+ /** Candidate companion package directories, in preference order. */
2402
+ readonly locateCompanionRoots?: () => readonly string[];
2403
+ /** Instance-local release metadata for tests or a verified immutable release. */
2404
+ readonly artifact?: IrohArtifact;
2405
+ readonly fetchArtifact?: (url: string, signal: AbortSignal) => Promise<Uint8Array>;
2406
+ readonly resolveSidecar?: (companionRoot: string, platform: string, arch: string) => Promise<string>;
2407
+ }
2408
+ export declare class IrohComponentManager {
2409
+ private readonly stateDirectory;
2410
+ private readonly platform;
2411
+ private readonly arch;
2412
+ private readonly locateCompanionRoots;
2413
+ private readonly resolveSidecar;
2414
+ private readonly artifact;
2415
+ private readonly fetchArtifact;
2416
+ private readonly componentRoot;
2417
+ private readonly componentStorage;
2418
+ private readonly executablePath;
2419
+ private readonly stagingRoot;
2420
+ private cached;
2421
+ private cachedExecutable;
2422
+ private origin;
2423
+ private queue;
2424
+ constructor(options: IrohComponentManagerOptions);
2425
+ /** Resolved, verified sidecar executable, or undefined when unavailable. */
2426
+ get executable(): string | undefined;
2427
+ /** Cached component state; refresh with {@link initialize} or {@link install}. */
2428
+ status(): IrohComponentStatus;
2429
+ /** Verify the sidecar once at startup; safe to call before any status read. */
2430
+ initialize(): Promise<void>;
2431
+ /**
2432
+ * Confirm a usable sidecar without downloading anything.
2433
+ *
2434
+ * Enabling the channel calls this: starting must never trigger a download
2435
+ * on its own. Only the explicit install button below may fetch bytes.
2436
+ */
2437
+ ensureAvailable(): Promise<IrohComponentStatus>;
2438
+ /**
2439
+ * Ensure a verified sidecar in the plugin private directory.
2440
+ *
2441
+ * Prefers an already installed companion copy (no network), otherwise
2442
+ * downloads the pinned release and verifies size and SHA-256 before
2443
+ * promoting it. A companion that exists but fails verification is reported
2444
+ * instead of being silently replaced by a download.
2445
+ */
2446
+ install(): Promise<IrohComponentStatus>;
2447
+ private enqueue;
2448
+ private baseStatus;
2449
+ private publishInstalled;
2450
+ private checkStateExecutable;
2451
+ private findCompanionExecutable;
2452
+ private downloadArtifact;
2453
+ private publishBytes;
2454
+ /** Remove the installed sidecar component from the plugin private directory. */
2455
+ purge(): Promise<IrohComponentStatus>;
2456
+ private refresh;
2457
+ }
2458
+ //#endregion
2459
+ //#region src/iroh-pairing.d.ts
2460
+ export declare const PAIRING_DESCRIPTOR_VERSION = 1;
2461
+ export declare const PAIRING_DESCRIPTOR_TYPE = "dsh-mobile-iroh-pairing";
2462
+ export declare const MAX_PAIRING_DESCRIPTOR_BYTES = 2200;
2463
+ export declare const MAX_PAIRING_LIFETIME_MS: number;
2464
+ declare const FIELDS: readonly ["version", "type", "endpointId", "origin", "localPort", "irohCode", "gatewayToken", "caCertificate", "instanceId", "expiresAt"];
2465
+ type PairingDescriptorField = (typeof FIELDS)[number];
2466
+ interface IrohPairingDescriptor {
2467
+ readonly version: 1;
2468
+ readonly type: 'dsh-mobile-iroh-pairing';
2469
+ readonly endpointId: string;
2470
+ readonly origin: string;
2471
+ readonly localPort: number;
2472
+ readonly irohCode: string;
2473
+ readonly gatewayToken: string;
2474
+ readonly caCertificate: string;
2475
+ readonly instanceId: string;
2476
+ readonly expiresAt: number;
2477
+ }
2478
+ /**
2479
+ * Validate QR transport material, not a DSH Session or persistent credential.
2480
+ * localPort is mandatory on the wire and must match the identity-derived HTTPS
2481
+ * Origin. The QR is sensitive: only the public CA may be retained or logged on
2482
+ * its own; neither pairing secret may be copied into logs or device-list text.
2483
+ *
2484
+ * Scanning this descriptor is the user's out-of-band trust action. A self-signed
2485
+ * CA does not independently authenticate a QR received from an untrusted party.
2486
+ */
2487
+ export declare function validatePairingDescriptor(value: unknown, options?: {
2488
+ now?: number;
2489
+ }): IrohPairingDescriptor;
2490
+ /** Encode a bounded canonical-field-order QR payload without implicit defaults. */
2491
+ export declare function encodePairingDescriptor(value: unknown, options?: {
2492
+ now?: number;
2493
+ }): string;
2494
+ /** Decode untrusted QR text, validating its expiry and public CA before use. */
2495
+ export declare function decodePairingDescriptor(encoded: string, options?: {
2496
+ now?: number;
2497
+ }): IrohPairingDescriptor;
2498
+ /** Phone-side listener port advertised in QR codes minted by this computer. */
2499
+ export declare const PAIRING_DESCRIPTOR_LOCAL_PORT = 25443;
2500
+ //#endregion
2501
+ //#region src/iroh.d.ts
2502
+ /** Product-facing states for the experimental iroh transport. */
2503
+ type IrohState = 'off' | 'unavailable' | 'starting' | 'connecting' | 'ready' | 'error';
2504
+ /** Safe iroh state returned only through the loopback DSH control route. */
2505
+ interface IrohStatus extends RemoteProviderStatus {
2506
+ readonly state: IrohState;
2507
+ }
2508
+ /** Inputs for one iroh sidecar process and dedicated DSH gateway. */
2509
+ interface IrohControllerOptions {
2510
+ readonly store: MobileAccessControlStore;
2511
+ readonly component: IrohComponentManager;
2512
+ /** Private directory owning the sidecar `--data-dir`. */
2513
+ readonly dataDirectory: string;
2514
+ readonly createGateway: (endpointId: string) => Promise<MobileAccessGateway>;
2515
+ /** Read the pairing CA DER plus the fingerprint the gateway advertises. */
2516
+ readonly resolvePairingCa?: () => Promise<{
2517
+ der: Buffer;
2518
+ fingerprint: string;
2519
+ }>;
2520
+ readonly onStatus?: (status: IrohStatus) => void;
2521
+ readonly launchSidecar?: (executable: string, args: readonly string[]) => ChildProcessWithoutNullStreams;
2522
+ readonly resolveIdentity?: (executable: string, dataDir: string) => Promise<string>;
2523
+ readonly readyTimeoutMs?: number;
2524
+ readonly pairingTimeoutMs?: number;
2525
+ }
2526
+ /** Short-lived pairing material minted for one QR code. */
2527
+ interface IrohPairingResult {
2528
+ readonly descriptor: IrohPairingDescriptor;
2529
+ /** Canonical JSON payload rendered into the QR code. */
2530
+ readonly encoded: string;
2531
+ /** Six-digit sidecar code for manual confirmation. */
2532
+ readonly code: string;
2533
+ readonly expiresAt: number;
2534
+ }
2535
+ export declare class IrohController implements RemoteProviderController {
2536
+ private readonly options;
2537
+ private enabled;
2538
+ private initialized;
2539
+ private disposed;
2540
+ private generation;
2541
+ private queue;
2542
+ private latest;
2543
+ private gatewayValue;
2544
+ private child;
2545
+ private identityChild;
2546
+ private closeTask;
2547
+ private endpointId;
2548
+ constructor(options: IrohControllerOptions);
2549
+ initialize(initialState?: MobileAccessControlState): Promise<void>;
2550
+ /** Return the active iroh-backed DSH gateway. */
2551
+ gateway(): MobileAccessGateway | undefined;
2552
+ /** Return state safe for the desktop control UI. */
2553
+ status(): IrohStatus;
2554
+ setEnabled(enabled: boolean): Promise<IrohStatus>;
2555
+ /** Restart iroh while retaining its sidecar identity and devices. */
2556
+ reconnect(): Promise<IrohStatus>;
2557
+ /** Disable iroh without deleting its sidecar identity or companion files. */
2558
+ reset(): Promise<IrohStatus>;
2559
+ /**
2560
+ * Mint one short-lived pairing descriptor for a QR code.
2561
+ *
2562
+ * Requires a live channel: the sidecar issues its six-digit code while the
2563
+ * gateway opens a one-time pairing window, and the descriptor binds both to
2564
+ * the pinned CA. Opening again replaces both windows without returning the
2565
+ * replaced secrets. The Phase 2 phone redeems the gateway token through the
2566
+ * ordinary pair endpoint over the iroh transport.
2567
+ */
2568
+ beginPairing(): Promise<IrohPairingResult>;
2569
+ /** Stop all iroh resources without changing the remembered switch. */
2570
+ close(): Promise<void>;
2571
+ private enqueue;
2572
+ private publish;
2573
+ private failGeneration;
2574
+ private stop;
2575
+ private stopResources;
2576
+ private start;
2577
+ private waitForReady;
2578
+ private waitForPairingCode;
2579
+ }
2580
+ //#endregion
2581
+ //#region src/iroh-origin.d.ts
2582
+ /** Identity-derived browser origins for the raw TLS-over-iroh carrier.
2583
+ *
2584
+ * Ported from the independent `dsh-mobile-iroh` companion's origin contract.
2585
+ * The local port is a deployment choice; changing it changes browser storage
2586
+ * identity, so the selected port is part of every persisted record.
2587
+ */
2588
+ export declare const DEFAULT_IROH_LOCAL_PORT = 25443;
2589
+ /** Keep the full endpoint key in DNS-safe labels rather than a colliding port hash. */
2590
+ export declare function irohHostname(endpointId: string): string;
2591
+ /** HTTPS origin the phone's local transport listener serves for one endpoint. */
2592
+ export declare function irohOrigin(endpointId: string, localPort?: number): string;
2593
+ /** Reject an Origin that does not belong to the selected cryptographic host identity. */
2594
+ export declare function validateIrohOrigin(value: unknown, endpointId: string, localPort?: number): string;
2595
+ //#endregion
2596
+ //#region src/iroh-tls.d.ts
2597
+ /** Leaf lifetime and renewal headroom, matching the companion's native policy. */
2598
+ export declare const IROH_LEAF_VALIDITY_DAYS = 90;
2599
+ export declare const IROH_LEAF_RENEW_BEFORE_DAYS = 30;
2600
+ /** Private files owned by the iroh TLS identity. */
2601
+ interface IrohTlsPaths {
2602
+ readonly directory: string;
2603
+ readonly caCertFile: string;
2604
+ readonly caKeyFile: string;
2605
+ readonly certFile: string;
2606
+ readonly keyFile: string;
2607
+ readonly statusFile: string;
2608
+ }
2609
+ /** Signed iroh material plus the fingerprint the app must pin. */
2610
+ interface IrohTlsCertificate {
2611
+ readonly paths: IrohTlsPaths;
2612
+ readonly ca: X509Certificate;
2613
+ readonly leaf: X509Certificate;
2614
+ readonly caFingerprint: string;
2615
+ readonly endpointId: string;
2616
+ }
2617
+ /** Private TLS directory, always a sibling of the remote device file. */
2618
+ export declare function irohTlsPaths(stateFile: string, ownedRoot?: string): IrohTlsPaths;
2619
+ /**
2620
+ * Materialize the CA and endpoint leaf the iroh gateway terminates TLS with.
2621
+ *
2622
+ * A recorded CA fingerprint that no longer matches fails closed: deleting or
2623
+ * replacing the CA is an explicit operator act, never an automatic recovery.
2624
+ * The endpoint may change under a stable CA; only the leaf is re-issued then.
2625
+ */
2626
+ export declare function ensureIrohTls(endpointId: string, stateFile: string, ownedRoot: string, now?: number): Promise<IrohTlsCertificate>;
2627
+ /**
2628
+ * Gateway config for the iroh endpoint-pinned entry.
2629
+ *
2630
+ * Like the self-signed FRP ingress, the gateway itself terminates TLS: the
2631
+ * sidecar only forwards raw TCP, so the listener speaks HTTPS with the leaf
2632
+ * the iroh CA signed, and the pairing CA is retained so the app can pin it
2633
+ * from `GET /mobile-access/ca.cer`. The listener stays on loopback because
2634
+ * the public path is the iroh transport, never a direct bind.
2635
+ */
2636
+ export declare function irohGatewayConfig(template: ResolvedGatewayConfig, endpointId: string, stateFile: string, tls: Pick<FrpIngressCertificate, 'paths' | 'caFingerprint'>, listenPort?: number): ResolvedGatewayConfig;
2637
+ //#endregion
2370
2638
  //#region src/task-events.d.ts
2371
2639
  /**
2372
2640
  * Host-side task-completion fan-out for phone notifications.
@@ -2449,5 +2717,5 @@ export declare function originGatewayConfig(template: ResolvedGatewayConfig, set
2449
2717
  /** Mount the resident control route and its optional authenticated LAN gateway. */
2450
2718
  export declare function apply(ctx: Context, config: PluginConfig): Promise<void>;
2451
2719
  //#endregion
2452
- export { type AccessControllerOptions, type AuthoritySpec, type BlockedUpgradePathEntry, type CaddySiteOptions, type CertRenewalStatus, type ClientModuleEntry, type ClientModulePreferenceSelection, type ClientModulePreferenceView, type CloudflaredComponentStatus, type CloudflaredControllerOptions, type CloudflaredState, type CloudflaredStatus, type CloudflaredTunnelMode, type CloudflaredTunnelSettings, type CloudflaredTunnelStatus, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, type DeviceProbeResult, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, type FrpAttachOptions, type FrpAttachPlan, type FrpAttachPlanLocal, type FrpAttachPlanStep, type FrpAttachStepId, type FrpAttachTemplate, type FrpAttachVpsParts, type FrpComponentStatus, type FrpConfigurationStatus, type FrpControllerOptions, type FrpEntryTls, type FrpIngressCertificate, type FrpIngressPaths, type FrpIngressSelfCheck, type FrpSettings, type FrpState, type FrpStatus, type HostExecutionConfig, type LocalExtensionManifest, type MobileAccessControlState, type MobileAccessControlStore, type MobileAccessService as MobileAccessRegistry, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type MobileWorkerHostApi, type OriginConfigurationStatus, type OriginControllerOptions, type OriginSettings, type OriginState, type OriginStatus, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, type ResolvedGatewayConfig, type ResolvedHostExecutionConfig, type ServerCertificateAuthority, type ServerCertificateFiles, type ServerCertificateTarget, type SessionAuthorization, type SessionEndReason, type StoredDevice, type TaskCompletionEvent, type TaskEventContext, type TaskEventSession, type TaskEventSink, type TaskEventWatcherOptions, type TaskTurnEvent, type TlsConfig };
2720
+ export { type AccessControllerOptions, type AuthoritySpec, type BlockedUpgradePathEntry, type CaddySiteOptions, type CertRenewalStatus, type ClientModuleEntry, type ClientModulePreferenceSelection, type ClientModulePreferenceView, type CloudflaredComponentStatus, type CloudflaredControllerOptions, type CloudflaredState, type CloudflaredStatus, type CloudflaredTunnelMode, type CloudflaredTunnelSettings, type CloudflaredTunnelStatus, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, type DeviceProbeResult, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, type FrpAttachOptions, type FrpAttachPlan, type FrpAttachPlanLocal, type FrpAttachPlanStep, type FrpAttachStepId, type FrpAttachTemplate, type FrpAttachVpsParts, type FrpComponentStatus, type FrpConfigurationStatus, type FrpControllerOptions, type FrpEntryTls, type FrpIngressCertificate, type FrpIngressPaths, type FrpIngressSelfCheck, type FrpSettings, type FrpState, type FrpStatus, type HostExecutionConfig, type IrohArtifact, type IrohComponentManagerOptions, type IrohComponentStatus, type IrohControllerOptions, type IrohPairingDescriptor, type IrohState, type IrohStatus, type IrohTlsCertificate, type IrohTlsPaths, type LocalExtensionManifest, type MobileAccessControlState, type MobileAccessControlStore, type MobileAccessService as MobileAccessRegistry, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type MobileWorkerHostApi, type OriginConfigurationStatus, type OriginControllerOptions, type OriginSettings, type OriginState, type OriginStatus, type PairingDescriptorField, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, type ResolvedGatewayConfig, type ResolvedHostExecutionConfig, type ServerCertificateAuthority, type ServerCertificateFiles, type ServerCertificateTarget, type SessionAuthorization, type SessionEndReason, type StoredDevice, type TaskCompletionEvent, type TaskEventContext, type TaskEventSession, type TaskEventSink, type TaskEventWatcherOptions, type TaskTurnEvent, type TlsConfig };
2453
2721
  //# sourceMappingURL=index.d.mts.map