dsh-mobile 0.5.5 → 0.6.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.
package/lib/index.d.mts CHANGED
@@ -309,7 +309,10 @@ interface PluginConfig {
309
309
  maxActiveRequests?: number;
310
310
  maxWebSockets?: number;
311
311
  maxBodyBytes?: number;
312
+ /** Transport, upload, static-response and WebSocket-handshake idle timeout. */
312
313
  upstreamTimeoutMs?: number;
314
+ /** Authenticated /api response idle timeout after upload; zero disables it. */
315
+ upstreamApiTimeoutMs?: number;
313
316
  rateLimitWindowMs?: number;
314
317
  maxPairingAttempts?: number;
315
318
  maxRateLimitKeys?: number;
@@ -347,6 +350,7 @@ interface ResolvedGatewayConfig {
347
350
  readonly maxWebSockets: number;
348
351
  readonly maxBodyBytes: number;
349
352
  readonly upstreamTimeoutMs: number;
353
+ readonly upstreamApiTimeoutMs: number;
350
354
  readonly rateLimitWindowMs: number;
351
355
  readonly maxPairingAttempts: number;
352
356
  readonly maxRateLimitKeys: number;
@@ -358,6 +362,53 @@ export declare function parseControlFile(value: unknown): string;
358
362
  /** Parse configuration and reject unsafe topology, credential, and resource combinations. */
359
363
  export declare function parseGatewayConfig(raw: unknown): ResolvedGatewayConfig;
360
364
  //#endregion
365
+ //#region src/client-module-preferences.d.ts
366
+ /** Installed client module metadata, without upstream URLs or host paths. */
367
+ interface ClientModuleEntry {
368
+ readonly id: string;
369
+ readonly required: boolean;
370
+ readonly dependencies: readonly string[];
371
+ }
372
+ /** Selection returned to the computer administrator or the authenticated device. */
373
+ interface ClientModulePreferenceView {
374
+ readonly entries: readonly ClientModuleEntry[];
375
+ readonly excludedClientModules: readonly string[];
376
+ readonly defaultExcludedClientModules: readonly string[];
377
+ readonly source: 'device' | 'computer' | 'plugin';
378
+ readonly reloadRequired: true;
379
+ }
380
+ /** Effective exclusion selection and the current computer default. */
381
+ interface ClientModulePreferenceSelection {
382
+ readonly excludedClientModules: readonly string[];
383
+ readonly defaultExcludedClientModules: readonly string[];
384
+ readonly source: ClientModulePreferenceView['source'];
385
+ }
386
+ /** Atomic, serialized preferences shared by the LAN and remote Gateway instances. */
387
+ export declare class ClientModulePreferenceStore {
388
+ readonly file: string;
389
+ private readonly defaults;
390
+ private value;
391
+ private initialization;
392
+ private queue;
393
+ constructor(file: string, defaults: readonly string[]);
394
+ /** Read existing state once. Missing state is not written during initialization. */
395
+ initialize(): Promise<void>;
396
+ private load;
397
+ private selection;
398
+ private exclusive;
399
+ /** Resolve one device override, otherwise the computer or plugin default. */
400
+ read(deviceId?: string): Promise<ClientModulePreferenceSelection>;
401
+ /** Revalidate against the current boot manifest inside the serialized mutation. */
402
+ configure(excluded: unknown, deviceId: string | undefined, validate: (selection: readonly string[]) => Promise<void>): Promise<ClientModulePreferenceSelection>;
403
+ /** Remove only the selected override; retain all other device selections. */
404
+ reset(deviceId: string | undefined, validate: (selection: readonly string[]) => Promise<void>): Promise<ClientModulePreferenceSelection>;
405
+ /** Remove exactly the revoked device's record without evaluating its obsolete graph. */
406
+ removeDevice(deviceId: string): Promise<void>;
407
+ /** Remove an explicit set of revoked identities, not every record in the shared store. */
408
+ removeDevices(deviceIds: readonly string[]): Promise<void>;
409
+ private save;
410
+ }
411
+ //#endregion
361
412
  //#region src/control.d.ts
362
413
  /** Versioned durable preference for the resident mobile-access runtime. */
363
414
  interface MobileAccessControlState {
@@ -408,6 +459,21 @@ export declare class MobileAccessGatewayController {
408
459
  private enqueue;
409
460
  }
410
461
  //#endregion
462
+ //#region src/http-security.d.ts
463
+ export declare const DEVICE_COOKIE = "dsh_ma_device";
464
+ export declare const SESSION_COOKIE = "dsh_ma_session";
465
+ export declare const CSRF_COOKIE = "dsh_ma_csrf";
466
+ export declare const CSRF_HEADER = "x-dsh-mobile-csrf";
467
+ export declare const LOCAL_ADMIN_PREFIX = "/api/mobile-access";
468
+ export declare const AUTH_PREFIX = "/mobile-access";
469
+ export declare const WS_PATHS: Set<string>;
470
+ /** Terse request failure safe to expose without internal diagnostics. */
471
+ declare class HttpError extends Error {
472
+ readonly status: number;
473
+ readonly code: string;
474
+ constructor(status: number, code: string);
475
+ }
476
+ //#endregion
411
477
  //#region src/websocket-paths.d.ts
412
478
  /** Cap the admin-approved extra WebSocket upgrade paths (exact pathnames). */
413
479
  export declare const MAX_EXTRA_WEBSOCKET_PATHS = 16;
@@ -477,6 +543,8 @@ interface MobileHostAction {
477
543
  readonly input?: CallableActionInput | {
478
544
  parse(value: unknown): unknown;
479
545
  };
546
+ /** Optional per-action budget override; validated and snapshotted at registration. */
547
+ readonly timeoutMs?: number;
480
548
  readonly run: (context: MobileActionContext, input: unknown) => unknown | Promise<unknown>;
481
549
  }
482
550
  /** Context supplied to a host action. */
@@ -506,6 +574,8 @@ interface MobileHostRoute {
506
574
  readonly method: string;
507
575
  readonly path: string;
508
576
  readonly kind?: 'exact' | 'prefix';
577
+ /** Optional per-route handler budget override; validated and snapshotted at registration. */
578
+ readonly timeoutMs?: number;
509
579
  readonly handle: (request: MobileRouteRequest) => MobileRouteResponse | Promise<MobileRouteResponse>;
510
580
  }
511
581
  /** Metadata shared by local and npm-provided extensions. */
@@ -566,6 +636,8 @@ export declare class MobileAccessService extends Service {
566
636
  private readonly local;
567
637
  private readonly retired;
568
638
  private readonly failures;
639
+ /** Extensions with caller-detached, still-unresolved operations. */
640
+ private readonly abandoned;
569
641
  private readonly contentListeners;
570
642
  private contentHash;
571
643
  private localRoot;
@@ -602,6 +674,10 @@ export declare class MobileAccessService extends Service {
602
674
  readonly digest: string;
603
675
  readonly name: string;
604
676
  }>;
677
+ /** Reject new dispatches to an extension whose abandoned work is unresolved. */
678
+ private requireAdmission;
679
+ /** Account for one operation until its underlying work actually settles. */
680
+ private trackOperation;
605
681
  /** Invoke one action after parsing its input and binding the request lifetime. */
606
682
  invoke(id: string, actionName: string, input: unknown, context: MobileActionContext, generation?: string): Promise<unknown>;
607
683
  /** Match one route and invoke it with a generation-bound abort signal. */
@@ -619,6 +695,11 @@ export declare class MobileAccessService extends Service {
619
695
  export declare function createMobileAccessService(ctx: Context): MobileAccessService;
620
696
  //#endregion
621
697
  //#region src/gateway.d.ts
698
+ /** A graph-selection conflict with a bounded diagnostic safe for authenticated callers. */
699
+ export declare class ClientModuleConflictError extends HttpError {
700
+ readonly detail: string;
701
+ constructor(detail: string);
702
+ }
622
703
  /** Rewrite the dedicated mobile graph; exclusions are opt-in and leave stock DSH unchanged. */
623
704
  export declare function rewriteMobileIndex(html: string, excludedClientModules?: readonly string[]): string;
624
705
  /** Authenticated TLS edge in front of the ordinary loopback-only DSH Web server. */
@@ -676,9 +757,13 @@ export declare class MobileAccessGateway {
676
757
  private readonly removeExtensionContentListener;
677
758
  private readonly renewLimiter;
678
759
  private readonly probeLimiter;
760
+ private readonly clientModulePreferences;
761
+ private readonly clientModuleOperations;
762
+ private readonly clientModuleTasks;
763
+ private readonly clientModuleRevocations;
679
764
  constructor(config: ResolvedGatewayConfig, store: DeviceStore, extensions?: MobileAccessService | undefined, upstreamAuthenticatedUrl?: string | undefined, extraWebSocketPaths?: {
680
765
  has(pathname: string): boolean;
681
- } | undefined, blockedUpgradeLog?: BlockedUpgradePathLog | undefined, onDiscoveryDegraded?: ((source: 'broadcast' | 'mdns', code: string) => void) | undefined);
766
+ } | undefined, blockedUpgradeLog?: BlockedUpgradePathLog | undefined, onDiscoveryDegraded?: ((source: 'broadcast' | 'mdns', code: string) => void) | undefined, clientModulePreferences?: ClientModulePreferenceStore);
682
767
  /** Initialize durable state, validate TLS, and bind the externally reachable listener. */
683
768
  start(): Promise<void>;
684
769
  /** Install a newly signed provided leaf for future TLS handshakes without dropping sessions. */
@@ -727,6 +812,27 @@ export declare class MobileAccessGateway {
727
812
  /** Exchange DSH's process-local launch token for an authority-bound cookie kept inside this gateway. */
728
813
  private upstreamCookieHeader;
729
814
  private exchangeUpstreamCookie;
815
+ /** List installed modules and resolve the next-open selection.
816
+ * @param deviceId - Authenticated device identity; omitted for computer defaults.
817
+ * @param callerSignal - Cancels catalog fetching when the admin request closes.
818
+ * @returns The installed catalog and effective module selection.
819
+ */
820
+ describeClientModules(deviceId?: string, callerSignal?: AbortSignal): Promise<ClientModulePreferenceView>;
821
+ /** Persist a validated device override or computer default.
822
+ * @param excluded - Untrusted module IDs to validate against the current boot graph.
823
+ * @param deviceId - Authenticated device identity; omitted for computer defaults.
824
+ * @param callerSignal - Cancels fetching and validation, not an atomic write already started.
825
+ * @returns The catalog and saved selection without reloading clients.
826
+ */
827
+ configureClientModules(excluded: unknown, deviceId?: string, callerSignal?: AbortSignal): Promise<ClientModulePreferenceView>;
828
+ /** Reset one override without reloading connected clients.
829
+ * @param deviceId - Authenticated device identity; omitted to reset computer defaults.
830
+ * @param callerSignal - Cancels fetching and validation, not an atomic write already started.
831
+ * @returns The catalog and inherited selection.
832
+ */
833
+ resetClientModules(deviceId?: string, callerSignal?: AbortSignal): Promise<ClientModulePreferenceView>;
834
+ private clientModulePreferenceOperation;
835
+ private fetchAuthenticatedUpstreamIndex;
730
836
  private proxyMobileIndex;
731
837
  private rememberMobileBootBatch;
732
838
  /**
@@ -761,10 +867,10 @@ export declare class MobileAccessGateway {
761
867
  private readUpstreamClientBundle;
762
868
  private allocateRequest;
763
869
  /**
764
- * Proxy one request upstream. Pass-through client bundles (`GET /plugins`)
765
- * receive bounded transient retries — the upstream resets a fraction of fresh
766
- * connections — matching the resilience the merged-batch assembly already has.
767
- * A request is only retried before any byte reached the client.
870
+ * Proxy one request, retrying transient failures for plugin and asset GETs.
871
+ * Only bodyless GETs can be replayed, before response headers reach the client.
872
+ * One request slot and cancellation signal cover attempts and backoff together.
873
+ * API requests and requests with bodies are forwarded once.
768
874
  */
769
875
  private proxyHttp;
770
876
  private proxyHttpOnce;
@@ -797,15 +903,6 @@ export declare class MobileAccessGateway {
797
903
  };
798
904
  }
799
905
  //#endregion
800
- //#region src/http-security.d.ts
801
- export declare const DEVICE_COOKIE = "dsh_ma_device";
802
- export declare const SESSION_COOKIE = "dsh_ma_session";
803
- export declare const CSRF_COOKIE = "dsh_ma_csrf";
804
- export declare const CSRF_HEADER = "x-dsh-mobile-csrf";
805
- export declare const LOCAL_ADMIN_PREFIX = "/api/mobile-access";
806
- export declare const AUTH_PREFIX = "/mobile-access";
807
- export declare const WS_PATHS: Set<string>;
808
- //#endregion
809
906
  //#region src/frp-component.d.ts
810
907
  interface FrpArtifact {
811
908
  readonly platform: NodeJS.Platform;
@@ -1912,5 +2009,5 @@ export declare function originGatewayConfig(template: ResolvedGatewayConfig, set
1912
2009
  /** Mount the resident control route and its optional authenticated LAN gateway. */
1913
2010
  export declare function apply(ctx: Context, config: PluginConfig): Promise<void>;
1914
2011
  //#endregion
1915
- export { type AccessControllerOptions, type AuthoritySpec, type BlockedUpgradePathEntry, type CaddySiteOptions, type CertRenewalStatus, 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 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 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 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 };
2012
+ 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 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 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 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 };
1916
2013
  //# sourceMappingURL=index.d.mts.map