dsh-mobile 0.3.16 → 0.4.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/lib/index.d.mts CHANGED
@@ -85,6 +85,13 @@ interface SessionAuthorization {
85
85
  readonly deviceId: string;
86
86
  readonly expiresAt: number;
87
87
  }
88
+ /** Result of a persistent-device reachability check without opening a Session. */
89
+ interface DeviceProbeResult {
90
+ readonly deviceId: string;
91
+ readonly deviceExpiresAt: number;
92
+ }
93
+ /** Why a short-lived Session ended; only device revocation is sent to clients. */
94
+ type SessionEndReason = 'logout' | 'expired' | 'evicted' | 'revoked';
88
95
  /** Safe device metadata returned by the loopback administration API. */
89
96
  interface DeviceSummary {
90
97
  readonly id: string;
@@ -139,6 +146,8 @@ declare class AccessController {
139
146
  pair(sourceKey: string, token: string, label?: string): Promise<PairingResult>;
140
147
  /** Exchange a valid persistent device credential for a new short Session. */
141
148
  renew(deviceToken: string): Promise<RenewalResult>;
149
+ /** Validate a persistent device credential without consuming a Session slot. */
150
+ probe(deviceToken: string): Promise<DeviceProbeResult>;
142
151
  /** Resolve a short Session Cookie without revealing whether device or Session failed. */
143
152
  authorizeSession(sessionToken: string): SessionAuthorization;
144
153
  /** Require the Session-bound anti-CSRF value for an authenticated mutation. */
@@ -157,7 +166,7 @@ declare class AccessController {
157
166
  expiresAt?: number;
158
167
  };
159
168
  /** Subscribe gateway resources to Session logout, expiry, eviction, and device revocation. */
160
- onSessionEnded(listener: (authorization: SessionAuthorization) => void): () => void;
169
+ onSessionEnded(listener: (authorization: SessionAuthorization, reason: SessionEndReason) => void): () => void;
161
170
  /** Stop new operations, drain durable mutations, then clear volatile credentials. */
162
171
  close(): Promise<void>;
163
172
  private finishClose;
@@ -598,6 +607,9 @@ declare class MobileAccessGateway {
598
607
  private readonly mobileBootBatches;
599
608
  private readonly extensionEventListeners;
600
609
  private extensionEventRevision;
610
+ private readonly taskEventListeners;
611
+ private readonly deviceEventListeners;
612
+ private readonly pendingDeviceRevocations;
601
613
  private extensionChangeTimer;
602
614
  private extensionChangeTask;
603
615
  private legacyCustomDigest;
@@ -612,6 +624,7 @@ declare class MobileAccessGateway {
612
624
  private readonly removeSessionListener;
613
625
  private readonly removeExtensionContentListener;
614
626
  private readonly renewLimiter;
627
+ private readonly probeLimiter;
615
628
  constructor(config: ResolvedGatewayConfig, store: DeviceStore, extensions?: MobileAccessService | undefined, upstreamAuthenticatedUrl?: string | undefined, extraWebSocketPaths?: {
616
629
  has(pathname: string): boolean;
617
630
  } | undefined, blockedUpgradeLog?: BlockedUpgradePathLog | undefined);
@@ -635,6 +648,7 @@ declare class MobileAccessGateway {
635
648
  private handleRenew;
636
649
  private handleNativePair;
637
650
  private handleNativeRenew;
651
+ private handleNativeProbe;
638
652
  private handleLogout;
639
653
  private handleExternalRequest;
640
654
  private handleExtensionRequest;
@@ -664,6 +678,13 @@ declare class MobileAccessGateway {
664
678
  private proxyHttp;
665
679
  private abortSessionResources;
666
680
  private broadcastExtensionChange;
681
+ /** Fan a completed task to every phone holding this gateway's event stream. */
682
+ broadcastTaskEvent(event: {
683
+ readonly sessionId: string;
684
+ readonly turn: number;
685
+ }): void;
686
+ /** Notify only the device whose persistent credential was revoked by the Host. */
687
+ private broadcastDeviceRevoked;
667
688
  private pollLegacyCustomChanges;
668
689
  private openExtensionEventStream;
669
690
  private readUpgradeResponse;
@@ -934,6 +955,69 @@ declare class FrpController implements RemoteProviderController {
934
955
  private stopProcessAndGateway;
935
956
  }
936
957
  //#endregion
958
+ //#region src/task-events.d.ts
959
+ /**
960
+ * Host-side task-completion fan-out for phone notifications.
961
+ *
962
+ * The exact moment a run ends is known only on the Host (the phone page can
963
+ * merely infer it from UI state), so this module watches the public
964
+ * `session/event` bus for completed root turns and hands them to a hub that
965
+ * fans out to every live mobile gateway. Phones render the text locally, so
966
+ * no user content crosses this boundary — only opaque session and turn ids.
967
+ */
968
+ /** A completed root turn worth announcing on paired phones. */
969
+ interface TaskCompletionEvent {
970
+ readonly sessionId: string;
971
+ readonly turn: number;
972
+ }
973
+ /** Minimal session shape read off the `session/event` bus. */
974
+ interface TaskEventSession {
975
+ readonly id: unknown;
976
+ readonly header?: {
977
+ readonly parentSession?: unknown;
978
+ } | null | undefined;
979
+ }
980
+ /**
981
+ * Minimal turn event shape read off the `session/event` bus. Fields stay
982
+ * unknown here and are validated at runtime below so this module never
983
+ * depends on the harness session packages.
984
+ */
985
+ interface TaskTurnEvent {
986
+ readonly type: string;
987
+ readonly data?: unknown;
988
+ }
989
+ /** Structural slice of the Host context this module needs (keeps tests cordis-free). */
990
+ interface TaskEventContext {
991
+ on(event: 'session/event', handler: (session: TaskEventSession, event: TaskTurnEvent) => void): () => void;
992
+ }
993
+ interface TaskEventWatcherOptions {
994
+ /** Trailing debounce per session that merges turn-boundary bursts. */
995
+ readonly debounceMs?: number;
996
+ readonly onTaskCompleted: (event: TaskCompletionEvent) => void;
997
+ readonly log?: (event: string, fields: Readonly<Record<string, string | number | boolean>>) => void;
998
+ }
999
+ declare const TASK_EVENT_DEBOUNCE_MS = 1000;
1000
+ /**
1001
+ * Subscribe to completed root turns. Subagent turns are skipped so one task
1002
+ * announces once, and rapid turn boundaries collapse into a single event.
1003
+ * Returns a disposer that also drops pending debounces.
1004
+ */
1005
+ declare function watchTaskCompletions(ctx: TaskEventContext, options: TaskEventWatcherOptions): () => void;
1006
+ /** Receives fanned-out completion events (normally a mobile gateway). */
1007
+ interface TaskEventSink {
1008
+ broadcastTaskEvent(event: TaskCompletionEvent): void;
1009
+ }
1010
+ /** One subscription feeding every live gateway; gateways register on start. */
1011
+ declare class TaskEventHub {
1012
+ private readonly sinks;
1013
+ /** Register a sink; returns its disposer. */
1014
+ add(sink: TaskEventSink): () => void;
1015
+ /** Fan out to a snapshot so a failing sink cannot break its siblings. */
1016
+ broadcast(event: TaskCompletionEvent): void;
1017
+ /** Visible for tests. */
1018
+ get size(): number;
1019
+ }
1020
+ //#endregion
937
1021
  //#region src/plugin.d.ts
938
1022
  /** Stable Cordis plugin name. */
939
1023
  declare const name = "dsh-mobile";
@@ -942,5 +1026,5 @@ declare const inject: string[];
942
1026
  /** Mount the resident control route and its optional authenticated LAN gateway. */
943
1027
  declare function apply(ctx: Context, config: PluginConfig): Promise<void>;
944
1028
  //#endregion
945
- export { AUTH_PREFIX, AccessController, type AccessControllerOptions, AccessError, type AuthoritySpec, type BlockedUpgradePathEntry, BlockedUpgradePathLog, BoundedRateLimiter, CSRF_COOKIE, CSRF_HEADER, Config, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, EXTENSION_LIMITS, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FrpComponentManager, type FrpComponentStatus, FrpConfigStore, type FrpConfigurationStatus, FrpController, type FrpControllerOptions, type FrpSettings, type FrpState, type FrpStatus, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, type LocalExtensionManifest, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, type MobileAccessControlState, type MobileAccessControlStore, MobileAccessGateway, MobileAccessGatewayController, type MobileAccessService as MobileAccessRegistry, MobileAccessService, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, MobileExtensionError, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, RequestTrustPolicy, type ResolvedGatewayConfig, SESSION_COOKIE, type SessionAuthorization, type StoredDevice, type TlsConfig, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, inject, isGloballyRoutableIpv4, isLoopbackAddress, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, parseAuthority, parseCidr, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseRemoteProviderState, resolveAuthority, rewriteMobileIndex, validateFrpPublicOrigin, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateWebSocketPath };
1029
+ export { AUTH_PREFIX, AccessController, type AccessControllerOptions, AccessError, type AuthoritySpec, type BlockedUpgradePathEntry, BlockedUpgradePathLog, BoundedRateLimiter, CSRF_COOKIE, CSRF_HEADER, Config, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, type DeviceProbeResult, type DeviceSnapshot, type DeviceStore, type DeviceSummary, type DisabledTlsConfig, EXTENSION_LIMITS, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FrpComponentManager, type FrpComponentStatus, FrpConfigStore, type FrpConfigurationStatus, FrpController, type FrpControllerOptions, type FrpSettings, type FrpState, type FrpStatus, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, type LocalExtensionManifest, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, type MobileAccessControlState, type MobileAccessControlStore, MobileAccessGateway, MobileAccessGatewayController, type MobileAccessService as MobileAccessRegistry, MobileAccessService, type MobileAccessRuntime, type MobileActionContext, type MobileExtensionClientEntry, type MobileExtensionDefinition, MobileExtensionError, type MobileExtensionManifest, type MobileExtensionStatus, type MobileHostAction, type MobileHostRoute, type MobileRouteRequest, type MobileRouteResponse, type PairingResult, type ParsedCidr, type PluginConfig, type ProvidedTlsConfig, type RemoteProvider, type RemoteProviderController, type RemoteProviderState, type RemoteProviderStatus, type RenewalResult, RequestTrustPolicy, type ResolvedGatewayConfig, SESSION_COOKIE, type SessionAuthorization, type SessionEndReason, type StoredDevice, TASK_EVENT_DEBOUNCE_MS, type TaskCompletionEvent, type TaskEventContext, TaskEventHub, type TaskEventSession, type TaskEventSink, type TaskEventWatcherOptions, type TaskTurnEvent, type TlsConfig, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, inject, isGloballyRoutableIpv4, isLoopbackAddress, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, parseAuthority, parseCidr, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseRemoteProviderState, resolveAuthority, rewriteMobileIndex, validateFrpPublicOrigin, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateWebSocketPath, watchTaskCompletions };
946
1030
  //# sourceMappingURL=index.d.mts.map