@kehto/shell 0.16.6 → 0.17.2

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/dist/index.d.ts CHANGED
@@ -262,13 +262,13 @@ interface UnroutedMessageInfo {
262
262
  }
263
263
  /**
264
264
  * Static capability set sent to napplet iframes through the shell.ready /
265
- * shell.init handshake. The current runtime availability primitive is injected
266
- * `window.napplet.<domain>` presence; this shape remains for older consumers
267
- * that still read shell.init capability metadata.
265
+ * shell.init handshake. Optional runtime domain presence is injected before
266
+ * authored code, while mandatory NAP-SHELL caches this environment for local
267
+ * capability queries.
268
268
  *
269
269
  * Current availability is the injected `window.napplet.<domain>` namespace.
270
- * Compatibility supports() helpers should treat only NAP domains and protocols
271
- * as advertised capabilities:
270
+ * NAP-SHELL supports() treats only NAP domains and protocols as advertised
271
+ * capabilities:
272
272
  *
273
273
  * - Bare names for NAP-capability lookups, resolved against the `naps`
274
274
  * array — e.g. `supports('relay')`, `supports('identity')`.
@@ -277,9 +277,9 @@ interface UnroutedMessageInfo {
277
277
  * NIP-5D no longer blesses additional browser sandbox tokens as interoperability
278
278
  * requirements or napplet-visible capabilities.
279
279
  *
280
- * ## Compatibility NAP-SHELL shape
280
+ * ## NAP-SHELL shape
281
281
  *
282
- * Older shell consumers may read the structured
282
+ * The shell shim reads the structured
283
283
  * `capabilities.{ domains: string[], protocols: Record<string, string[]> }`
284
284
  * alongside the flat `naps` array:
285
285
  *
@@ -292,7 +292,7 @@ interface UnroutedMessageInfo {
292
292
  */
293
293
  interface ShellCapabilities {
294
294
  /**
295
- * Compatibility NAP-SHELL domain list.
295
+ * NAP-SHELL domain list.
296
296
  * Bare NAP domain names the shell offers — `'identity'`, `'storage'`,
297
297
  * `'inc'`, `'theme'`, etc. — with the same conditional entries as `naps`
298
298
  * (`relay`/`outbox` when a relay pool is wired, `upload`/`intent` under their
@@ -301,11 +301,11 @@ interface ShellCapabilities {
301
301
  */
302
302
  domains: string[];
303
303
  /**
304
- * Compatibility NAP-SHELL per-domain numbered protocols. Maps a domain to the NAP-NN protocol IDs it
304
+ * NAP-SHELL per-domain numbered protocols. Maps a domain to the NAP-NN protocol IDs it
305
305
  * speaks — `{ inc: ['NAP-01','NAP-02','NAP-03','NAP-04','NAP-05','NAP-06'] }`
306
306
  * (derived from `NAP_INC_PROTOCOLS` by stripping the `inc:` prefix).
307
307
  *
308
- * Legacy supports helpers resolve `supports('<domain>','NAP-NN')` against this map.
308
+ * Local supports helpers resolve `supports('<domain>','NAP-NN')` against this map.
309
309
  */
310
310
  protocols: Record<string, string[]>;
311
311
  /**
@@ -575,6 +575,14 @@ interface ShellBridge {
575
575
  }
576
576
  declare function createShellBridge(hooks: ShellAdapter): ShellBridge;
577
577
 
578
+ /**
579
+ * The injected implementation must remain one self-contained function: the
580
+ * renderer serializes it ahead of verified artifact scripts without changing
581
+ * the signed artifact bytes. Splitting it into imported helpers would leave
582
+ * unresolved closures in the generated `srcdoc`.
583
+ *
584
+ * aislop-ignore-file complexity/file-too-large complexity/function-too-long
585
+ */
578
586
  /**
579
587
  * Options for rendering the host-owned NIP-5D `window.napplet` namespace prelude.
580
588
  *
@@ -587,7 +595,8 @@ declare function createShellBridge(hooks: ShellAdapter): ShellBridge;
587
595
  */
588
596
  interface NappletNamespacePreludeOptions {
589
597
  /**
590
- * Bare NAP domain names the shell exposes to this napplet.
598
+ * Optional bare NAP domain names the shell exposes to this napplet.
599
+ * Mandatory `shell` is injected even when omitted here.
591
600
  */
592
601
  domains: readonly string[];
593
602
  }
@@ -621,6 +630,11 @@ declare function renderNappletNamespacePrelude(options: NappletNamespacePreludeO
621
630
  */
622
631
  declare function injectNappletNamespacePrelude(html: string, options: NappletNamespacePreludeOptions): string;
623
632
 
633
+ /** NIP-5D identity metadata associated with a registered iframe window. */
634
+ interface OriginIdentity {
635
+ readonly dTag: string;
636
+ readonly aggregateHash: string;
637
+ }
624
638
  /**
625
639
  * Bidirectional registry mapping Window references to windowId strings.
626
640
  * Optionally stores NIP-5D identity metadata (dTag and aggregateHash) per window.
@@ -633,64 +647,18 @@ declare function injectNappletNamespacePrelude(html: string, options: NappletNam
633
647
  * const id = originRegistry.getWindowId(iframe.contentWindow); // 'napp-1'
634
648
  * ```
635
649
  */
636
- declare const originRegistry: {
637
- /**
638
- * Register a window reference with a windowId and optional identity metadata.
639
- *
640
- * @param win - The iframe's contentWindow reference
641
- * @param windowId - The unique identifier for this napplet window
642
- * @param identity - Optional NIP-5D identity metadata (dTag and aggregateHash)
643
- */
644
- register(win: Window, windowId: string, identity?: {
645
- dTag: string;
646
- aggregateHash: string;
647
- }): void;
648
- /**
649
- * Unregister a window by its windowId, removing the mapping.
650
- *
651
- * @param windowId - The window identifier to remove
652
- */
650
+ interface OriginRegistry {
651
+ register(win: Window, windowId: string, identity?: OriginIdentity): void;
653
652
  unregister(windowId: string): void;
654
- /**
655
- * Look up the windowId for a given Window reference.
656
- *
657
- * @param win - The Window reference (typically from event.source)
658
- * @returns The windowId string, or undefined if not registered
659
- */
660
653
  getWindowId(win: Window): string | undefined;
661
- /**
662
- * Look up the Window reference for a given windowId.
663
- *
664
- * @param windowId - The window identifier to look up
665
- * @returns The Window reference, or null if not found
666
- */
667
654
  getIframeWindow(windowId: string): Window | null;
668
- /**
669
- * Get all registered windowId strings.
670
- *
671
- * @returns Array of all registered window identifiers
672
- */
673
655
  getAllWindowIds(): string[];
674
- /**
675
- * Get identity metadata for a registered Window.
676
- *
677
- * @param win - The Window reference to look up
678
- * @returns Identity metadata, or undefined if not registered or no identity set
679
- */
680
- getIdentity(win: Window): {
681
- dTag: string;
682
- aggregateHash: string;
683
- } | undefined;
684
- /**
685
- * Look up the monotonically increasing registration id for a Window.
686
- *
687
- * @param win - The Window reference to look up
688
- * @returns The registration id, or undefined if the Window is not registered
689
- */
656
+ getIdentity(win: Window): OriginIdentity | undefined;
690
657
  getRegistrationId(win: Window): number | undefined;
691
- /** Clear all registrations. */
692
658
  clear(): void;
693
- };
659
+ }
660
+ /** Shell-wide iframe window registry singleton. */
661
+ declare const originRegistry: OriginRegistry;
694
662
 
695
663
  /**
696
664
  * Manifest cache — persists verified NIP-5A aggregate hashes per napplet identity.
@@ -723,44 +691,17 @@ interface ManifestCacheEntry {
723
691
  * const entry = manifestCache.get('abc...', 'chat');
724
692
  * ```
725
693
  */
726
- declare const manifestCache: {
727
- /**
728
- * Get a cached manifest entry by pubkey and dTag.
729
- *
730
- * @param pubkey - The napp's pubkey
731
- * @param dTag - The napp's dTag
732
- * @returns The cached entry, or undefined if not found
733
- */
694
+ interface ManifestCache {
734
695
  get(pubkey: string, dTag: string): ManifestCacheEntry | undefined;
735
- /**
736
- * Set (upsert) a manifest cache entry and persist to localStorage.
737
- *
738
- * @param entry - The manifest entry to cache
739
- */
740
696
  set(entry: ManifestCacheEntry): void;
741
- /**
742
- * Check if a specific hash is cached for a pubkey/dTag combination.
743
- *
744
- * @param pubkey - The napp's pubkey
745
- * @param dTag - The napp's dTag
746
- * @param hash - The aggregateHash to check
747
- * @returns True if the exact hash matches the cached entry
748
- */
749
697
  has(pubkey: string, dTag: string, hash: string): boolean;
750
- /**
751
- * Remove a cached entry for a pubkey/dTag and persist.
752
- *
753
- * @param pubkey - The napp's pubkey
754
- * @param dTag - The napp's dTag
755
- */
756
698
  remove(pubkey: string, dTag: string): void;
757
- /** Load the cache from localStorage. */
758
699
  load(): void;
759
- /** Persist the cache to localStorage. */
760
700
  persist(): void;
761
- /** Clear all cached entries and remove from localStorage. */
762
701
  clear(): void;
763
- };
702
+ }
703
+ /** Shell-wide manifest verification cache singleton. */
704
+ declare const manifestCache: ManifestCache;
764
705
 
765
706
  /**
766
707
  * ACL store — manages capability grants, revocations, and blocks for napp identities.
@@ -774,92 +715,22 @@ declare const manifestCache: {
774
715
  * const allowed = aclStore.check(pubkey, dTag, hash, 'relay:read'); // true
775
716
  * ```
776
717
  */
777
- declare const aclStore: {
778
- /**
779
- * Check if a napp identity has a specific capability.
780
- * Returns true for unknown identities (permissive default).
781
- *
782
- * @param pubkey - The napp's pubkey
783
- * @param dTag - The napp's dTag
784
- * @param aggregateHash - The napp's build hash
785
- * @param capability - The capability to check
786
- * @returns True if the capability is granted and the napp is not blocked
787
- */
718
+ interface AclStore {
788
719
  check(pubkey: string, dTag: string, aggregateHash: string, capability: Capability): boolean;
789
- /**
790
- * Grant a capability to a napp identity.
791
- *
792
- * @param pubkey - The napp's pubkey
793
- * @param dTag - The napp's dTag
794
- * @param aggregateHash - The napp's build hash
795
- * @param capability - The capability to grant
796
- */
797
720
  grant(pubkey: string, dTag: string, aggregateHash: string, capability: Capability): void;
798
- /**
799
- * Revoke a capability from a napp identity.
800
- *
801
- * @param pubkey - The napp's pubkey
802
- * @param dTag - The napp's dTag
803
- * @param aggregateHash - The napp's build hash
804
- * @param capability - The capability to revoke
805
- */
806
721
  revoke(pubkey: string, dTag: string, aggregateHash: string, capability: Capability): void;
807
- /**
808
- * Block a napp identity entirely (all capabilities denied).
809
- *
810
- * @param pubkey - The napp's pubkey
811
- * @param dTag - The napp's dTag
812
- * @param aggregateHash - The napp's build hash
813
- */
814
722
  block(pubkey: string, dTag: string, aggregateHash: string): void;
815
- /**
816
- * Unblock a napp identity.
817
- *
818
- * @param pubkey - The napp's pubkey
819
- * @param dTag - The napp's dTag
820
- * @param aggregateHash - The napp's build hash
821
- */
822
723
  unblock(pubkey: string, dTag: string, aggregateHash: string): void;
823
- /**
824
- * Check if a napp identity is blocked.
825
- *
826
- * @param pubkey - The napp's pubkey
827
- * @param dTag - The napp's dTag
828
- * @param aggregateHash - The napp's build hash
829
- * @returns True if the identity is blocked
830
- */
831
724
  isBlocked(pubkey: string, dTag: string, aggregateHash: string): boolean;
832
- /**
833
- * Get the external ACL entry for a napp identity.
834
- *
835
- * @param pubkey - The napp's pubkey
836
- * @param dTag - The napp's dTag
837
- * @param aggregateHash - The napp's build hash
838
- * @returns The ACL entry, or undefined if no explicit entry exists
839
- */
840
725
  getEntry(pubkey: string, dTag: string, aggregateHash: string): AclEntry | undefined;
841
- /**
842
- * Get all ACL entries.
843
- *
844
- * @returns Array of all ACL entries
845
- */
846
726
  getAllEntries(): AclEntry[];
847
- /** Persist the ACL store to localStorage. */
848
727
  persist(): void;
849
- /** Load the ACL store from localStorage. Migrates old 3-segment keys to 2-segment format. */
850
728
  load(): void;
851
- /**
852
- * Get the state quota for a napp identity.
853
- *
854
- * @param pubkey - The napp's pubkey
855
- * @param dTag - The napp's dTag
856
- * @param aggregateHash - The napp's build hash
857
- * @returns The quota in bytes (defaults to DEFAULT_STATE_QUOTA)
858
- */
859
729
  getStateQuota(pubkey: string, dTag: string, aggregateHash: string): number;
860
- /** Clear all ACL entries and remove from localStorage. */
861
730
  clear(): void;
862
- };
731
+ }
732
+ /** Shell ACL store singleton. */
733
+ declare const aclStore: AclStore;
863
734
 
864
735
  /**
865
736
  * audio-manager.ts — Shell-side registry of active audio sources.
@@ -895,69 +766,22 @@ interface AudioSource {
895
766
  * audioManager.mute('win-1', true);
896
767
  * ```
897
768
  */
898
- declare const audioManager: {
899
- /**
900
- * Register a new audio source for a window.
901
- *
902
- * @param windowId - The window identifier
903
- * @param nappletClass - The napplet class/type (e.g., 'music-player')
904
- * @param title - Human-readable title for the audio source
905
- */
769
+ interface AudioManager {
906
770
  register(windowId: string, nappletClass: string, title: string): void;
907
- /**
908
- * Unregister an audio source for a window.
909
- *
910
- * @param windowId - The window identifier to remove
911
- */
912
771
  unregister(windowId: string): void;
913
- /**
914
- * Update the state of an audio source (e.g., change title).
915
- *
916
- * @param windowId - The window identifier
917
- * @param update - Partial update with optional title
918
- */
919
772
  updateState(windowId: string, update: {
920
773
  title?: string;
921
774
  }): void;
922
- /**
923
- * Mute or unmute an audio source and notify the napplet via postMessage.
924
- *
925
- * @param windowId - The window identifier
926
- * @param muted - True to mute, false to unmute
927
- * @example
928
- * ```ts
929
- * audioManager.mute('win-1', true); // mute
930
- * audioManager.mute('win-1', false); // unmute
931
- * ```
932
- */
933
775
  mute(windowId: string, muted: boolean): void;
934
- /**
935
- * Check if a window has a registered audio source.
936
- *
937
- * @param windowId - The window identifier
938
- * @returns True if the window has an active audio source
939
- */
940
776
  has(windowId: string): boolean;
941
- /**
942
- * Get the audio source for a window.
943
- *
944
- * @param windowId - The window identifier
945
- * @returns The AudioSource, or undefined if not found
946
- */
947
777
  get(windowId: string): AudioSource | undefined;
948
- /**
949
- * Get a snapshot of all audio sources.
950
- *
951
- * @returns A new Map of all active audio sources
952
- */
953
778
  getSources(): Map<string, AudioSource>;
954
- /** Current version counter (incremented on every change). */
955
779
  readonly version: number;
956
- /** Number of active audio sources. */
957
780
  readonly count: number;
958
- /** Clear all audio sources and reset version counter. */
959
781
  clear(): void;
960
- };
782
+ }
783
+ /** Shell-wide audio source registry singleton. */
784
+ declare const audioManager: AudioManager;
961
785
 
962
786
  /**
963
787
  * SessionRegistry — windowId to verified napplet pubkey bidirectional mapping.
@@ -978,149 +802,23 @@ declare const audioManager: {
978
802
  * const entry = pubkey ? sessionRegistry.getEntry(pubkey) : undefined;
979
803
  * ```
980
804
  */
981
- declare const sessionRegistry: {
982
- /**
983
- * Register a napplet entry, mapping windowId to pubkey and vice versa.
984
- *
985
- * @param windowId - The window identifier
986
- * @param entry - The verified napplet session entry from AUTH handshake
987
- */
805
+ interface SessionRegistry {
988
806
  register(windowId: string, entry: SessionEntry): void;
989
- /**
990
- * Unregister a napplet by windowId, removing both mappings.
991
- *
992
- * @param windowId - The window identifier to remove
993
- */
994
807
  unregister(windowId: string): void;
995
- /**
996
- * Get the pubkey associated with a windowId.
997
- *
998
- * @param windowId - The window identifier
999
- * @returns The napplet's pubkey, or undefined if not registered
1000
- */
1001
808
  getPubkey(windowId: string): string | undefined;
1002
- /**
1003
- * Get the full entry for a napplet pubkey.
1004
- *
1005
- * @param pubkey - The napplet's pubkey
1006
- * @returns The full SessionEntry, or undefined if not found
1007
- */
1008
809
  getEntry(pubkey: string): SessionEntry | undefined;
1009
- /**
1010
- * Get the windowId for a napplet pubkey.
1011
- *
1012
- * @param pubkey - The napplet's pubkey
1013
- * @returns The windowId, or undefined if not found
1014
- */
1015
810
  getWindowId(pubkey: string): string | undefined;
1016
- /**
1017
- * Check if a windowId has a registered napplet.
1018
- *
1019
- * @param windowId - The window identifier
1020
- * @returns True if the windowId has a registered napplet
1021
- */
1022
811
  isRegistered(windowId: string): boolean;
1023
- /**
1024
- * Get all registered napplet entries.
1025
- *
1026
- * @returns Array of all SessionEntry objects
1027
- */
1028
812
  getAllEntries(): SessionEntry[];
1029
- /**
1030
- * Set a pending update for a window (napplet reconnected with different hash).
1031
- *
1032
- * @param windowId - The window identifier
1033
- * @param update - The pending update details with resolve callback
1034
- */
1035
813
  setPendingUpdate(windowId: string, update: PendingUpdate): void;
1036
- /**
1037
- * Get a pending update for a window.
1038
- *
1039
- * @param windowId - The window identifier
1040
- * @returns The pending update, or undefined if none
1041
- */
1042
814
  getPendingUpdate(windowId: string): PendingUpdate | undefined;
1043
- /**
1044
- * Clear a pending update for a window.
1045
- *
1046
- * @param windowId - The window identifier
1047
- */
1048
815
  clearPendingUpdate(windowId: string): void;
1049
- /** Clear all registrations and pending updates. */
1050
816
  clear(): void;
1051
- };
817
+ }
818
+ /** Shell-wide verified napplet session registry singleton. */
819
+ declare const sessionRegistry: SessionRegistry;
1052
820
  /** @deprecated Use sessionRegistry. Will be removed in v0.9.0. */
1053
- declare const nappKeyRegistry: {
1054
- /**
1055
- * Register a napplet entry, mapping windowId to pubkey and vice versa.
1056
- *
1057
- * @param windowId - The window identifier
1058
- * @param entry - The verified napplet session entry from AUTH handshake
1059
- */
1060
- register(windowId: string, entry: SessionEntry): void;
1061
- /**
1062
- * Unregister a napplet by windowId, removing both mappings.
1063
- *
1064
- * @param windowId - The window identifier to remove
1065
- */
1066
- unregister(windowId: string): void;
1067
- /**
1068
- * Get the pubkey associated with a windowId.
1069
- *
1070
- * @param windowId - The window identifier
1071
- * @returns The napplet's pubkey, or undefined if not registered
1072
- */
1073
- getPubkey(windowId: string): string | undefined;
1074
- /**
1075
- * Get the full entry for a napplet pubkey.
1076
- *
1077
- * @param pubkey - The napplet's pubkey
1078
- * @returns The full SessionEntry, or undefined if not found
1079
- */
1080
- getEntry(pubkey: string): SessionEntry | undefined;
1081
- /**
1082
- * Get the windowId for a napplet pubkey.
1083
- *
1084
- * @param pubkey - The napplet's pubkey
1085
- * @returns The windowId, or undefined if not found
1086
- */
1087
- getWindowId(pubkey: string): string | undefined;
1088
- /**
1089
- * Check if a windowId has a registered napplet.
1090
- *
1091
- * @param windowId - The window identifier
1092
- * @returns True if the windowId has a registered napplet
1093
- */
1094
- isRegistered(windowId: string): boolean;
1095
- /**
1096
- * Get all registered napplet entries.
1097
- *
1098
- * @returns Array of all SessionEntry objects
1099
- */
1100
- getAllEntries(): SessionEntry[];
1101
- /**
1102
- * Set a pending update for a window (napplet reconnected with different hash).
1103
- *
1104
- * @param windowId - The window identifier
1105
- * @param update - The pending update details with resolve callback
1106
- */
1107
- setPendingUpdate(windowId: string, update: PendingUpdate): void;
1108
- /**
1109
- * Get a pending update for a window.
1110
- *
1111
- * @param windowId - The window identifier
1112
- * @returns The pending update, or undefined if none
1113
- */
1114
- getPendingUpdate(windowId: string): PendingUpdate | undefined;
1115
- /**
1116
- * Clear a pending update for a window.
1117
- *
1118
- * @param windowId - The window identifier
1119
- */
1120
- clearPendingUpdate(windowId: string): void;
1121
- /** Clear all registrations and pending updates. */
1122
- clear(): void;
1123
- };
821
+ declare const nappKeyRegistry: SessionRegistry;
1124
822
 
1125
823
  /**
1126
824
  * hooks-adapter.ts — Converts ShellAdapter (browser-facing) to RuntimeAdapter (environment-agnostic).
@@ -1168,10 +866,9 @@ declare function adaptHooks(shellHooks: ShellAdapter, deps: BrowserDeps): Runtim
1168
866
  /**
1169
867
  * Build the shell's static capability set from adapter configuration.
1170
868
  *
1171
- * Returns the compatibility NAP-SHELL `domains`/`protocols` shape alongside
1172
- * the flat `naps` array and the `sandbox` array. Current availability is
1173
- * injected `window.napplet.<domain>` presence; this payload remains for older
1174
- * consumers that still inspect shell.init capabilities.
869
+ * Returns the NAP-SHELL `domains`/`protocols` environment used by local
870
+ * `window.napplet.shell.supports()` queries. Flat `naps` and empty `sandbox`
871
+ * fields remain alongside it for older payload readers.
1175
872
  *
1176
873
  * ### naps array (NAP vocabulary)
1177
874
  * Bare domain `inc` + `inc:NAP-01..inc:NAP-06`.
@@ -1185,8 +882,8 @@ declare function adaptHooks(shellHooks: ShellAdapter, deps: BrowserDeps): Runtim
1185
882
  * NIP-5D defines only the `allow-scripts` baseline and does not make additional
1186
883
  * browser sandbox tokens a napplet capability surface.
1187
884
  *
1188
- * ### domains array + protocols map (compatibility NAP-SHELL)
1189
- * The structured shape older shell capability consumers read:
885
+ * ### domains array + protocols map (NAP-SHELL)
886
+ * The structured environment delivered to the mandatory shell shim:
1190
887
  *
1191
888
  * - `domains` — bare NAP domain names (the `naps` set MINUS the `inc:NAP-NN`
1192
889
  * protocol strings) with the same conditional entries (relay/outbox under
@@ -1194,11 +891,10 @@ declare function adaptHooks(shellHooks: ShellAdapter, deps: BrowserDeps): Runtim
1194
891
  * - `protocols` — `{ inc: ['NAP-01'..'NAP-06'] }`, derived from
1195
892
  * `NAP_INC_PROTOCOLS` by stripping the `inc:` prefix.
1196
893
  *
1197
- * Emitted as a superset alongside `naps`/`sandbox` for back-compat.
894
+ * `naps`/`sandbox` are emitted as compatibility fields alongside this shape.
1198
895
  *
1199
896
  * @param hooks - The ShellAdapter provided by the host app
1200
- * @returns ShellCapabilities with domains/protocols (compatibility shape), naps
1201
- * (NAP vocab), and an empty sandbox compatibility array
897
+ * @returns ShellCapabilities with normative local-query data plus legacy fields
1202
898
  * @example
1203
899
  * ```ts
1204
900
  * const caps = buildShellCapabilities(hooks);
@@ -1408,11 +1104,11 @@ declare function createThemeProxy(deps: ThemeProxyDeps): ThemeProxy;
1408
1104
  /**
1409
1105
  * keys-proxy.ts — Shell-side per-domain proxy for keys.* envelopes.
1410
1106
  *
1411
- * Per Plan 12-05, the runtime already dispatches `keys.*` (forward,
1412
- * registerAction, unregisterAction) to the keys-service. This proxy is the
1413
- * shell-side composition point for host apps that want to observe or
1414
- * inject keys envelopes — it pairs with `keys-forwarder.ts` (Plan 12-11)
1415
- * which covers the shell→napplet `keys.forward` push path.
1107
+ * The runtime already dispatches napplet-originated `keys.*` (forward,
1108
+ * registerAction, unregisterAction) to the keys service. This proxy is the
1109
+ * shell-side composition point for host apps that want to observe requests or
1110
+ * inject shell-originated keys envelopes such as `keys.action` and
1111
+ * `keys.bindings`.
1416
1112
  *
1417
1113
  * Shape mirrors identity-proxy (Plan 12-11):
1418
1114
  *
@@ -1463,10 +1159,6 @@ interface KeysProxy {
1463
1159
  * Push a shell-initiated keys-domain envelope (e.g. `keys.action`,
1464
1160
  * `keys.bindings`) into a napplet iframe.
1465
1161
  *
1466
- * Paired with `keys-forwarder.ts`: the forwarder targets the DOM
1467
- * `keydown` → `keys.forward` path; this `emit` covers the complementary
1468
- * host-initiated pushes (binding updates, action triggers).
1469
- *
1470
1162
  * No-op when the originRegistry cannot resolve the windowId (unknown or
1471
1163
  * unregistered napplet). Never throws.
1472
1164
  *
@@ -1672,101 +1364,6 @@ interface NotifyProxy {
1672
1364
  */
1673
1365
  declare function createNotifyProxy(deps: NotifyProxyDeps): NotifyProxy;
1674
1366
 
1675
- /**
1676
- * keys-forwarder.ts — Shell-side host keydown listener that forwards events
1677
- * to registered napplets as `keys.forward` envelopes (Plan 12-11, NAP-05
1678
- * shell-side half).
1679
- *
1680
- * Per `@napplet/nap/keys`, `keys.forward` is fire-and-forget (no result
1681
- * envelope, no correlation id). Field names follow the nap convention:
1682
- * `{ ctrl, alt, shift, meta }` — NOT the DOM-style `ctrlKey`/etc.
1683
- *
1684
- * Capability gate: only forwards to napplets whose ACL grants the
1685
- * `keys:forward` capability (per Plan 12-10 `resolveCapabilitiesNap` 'keys'
1686
- * case). The caller wires the cap-lookup via the `hasKeysForwardCap` dep so
1687
- * this module stays free of any direct ACL-store dependency.
1688
- *
1689
- * Lifecycle: `createShellBridge()` attaches a forwarder on construction and
1690
- * detaches it inside `bridge.destroy()`.
1691
- */
1692
-
1693
- /**
1694
- * Minimal origin-registry contract used by the forwarder — matches the
1695
- * `@kehto/shell` singleton `originRegistry` and test doubles alike.
1696
- */
1697
- interface KeysForwarderOriginRegistry {
1698
- /** Resolve a registered napplet windowId to its iframe Window, or null. */
1699
- getIframeWindow(windowId: string): Window | null;
1700
- }
1701
- /**
1702
- * Minimal session-registry contract used by the forwarder — matches the
1703
- * `@kehto/shell` singleton `sessionRegistry` and test doubles alike.
1704
- */
1705
- interface KeysForwarderSessionRegistry {
1706
- /** Return every registered napplet session entry. */
1707
- getAllEntries(): SessionEntry[];
1708
- }
1709
- /**
1710
- * Dependencies for `createKeysForwarder`.
1711
- *
1712
- * @example
1713
- * ```ts
1714
- * const forwarder = createKeysForwarder({
1715
- * originRegistry,
1716
- * sessionRegistry,
1717
- * hasKeysForwardCap: (pubkey) =>
1718
- * aclStore.getAclEntry(pubkey)?.capabilities.includes('keys:forward') ?? false,
1719
- * });
1720
- * ```
1721
- */
1722
- interface KeysForwarderDeps {
1723
- /** Origin registry for resolving windowId → iframe Window. */
1724
- originRegistry: KeysForwarderOriginRegistry;
1725
- /** Session registry for enumerating napplets to forward to. */
1726
- sessionRegistry: KeysForwarderSessionRegistry;
1727
- /**
1728
- * Capability check: returns true when the given napplet pubkey holds the
1729
- * `keys:forward` capability. Called per keydown per registered napplet —
1730
- * keep the implementation cheap.
1731
- */
1732
- hasKeysForwardCap(pubkey: string): boolean;
1733
- /**
1734
- * Optional EventTarget to attach to. Defaults to the global `window` when
1735
- * running in a DOM environment. Passing a fresh `new EventTarget()` is
1736
- * useful for unit tests.
1737
- */
1738
- target?: EventTarget;
1739
- }
1740
- /**
1741
- * Handle returned by `createKeysForwarder`. Call `destroy()` to remove the
1742
- * keydown listener (e.g. inside `bridge.destroy()`).
1743
- */
1744
- interface KeysForwarder {
1745
- /** Detach the keydown listener and release resources. */
1746
- destroy(): void;
1747
- }
1748
- /**
1749
- * Create a host-keydown forwarder that posts `keys.forward` envelopes to
1750
- * every registered napplet granted the `keys:forward` capability.
1751
- *
1752
- * @param deps - Origin registry, session registry, cap checker, optional target
1753
- * @returns A {@link KeysForwarder} — call `destroy()` to detach
1754
- * @example
1755
- * ```ts
1756
- * // Inside createShellBridge():
1757
- * const keysForwarder = createKeysForwarder({
1758
- * originRegistry,
1759
- * sessionRegistry,
1760
- * hasKeysForwardCap: (pubkey) =>
1761
- * aclStore.getAclEntry(pubkey)?.capabilities.includes('keys:forward') ?? false,
1762
- * });
1763
- * // ...
1764
- * // Inside bridge.destroy():
1765
- * keysForwarder.destroy();
1766
- * ```
1767
- */
1768
- declare function createKeysForwarder(deps: KeysForwarderDeps): KeysForwarder;
1769
-
1770
1367
  /**
1771
1368
  * @file internal-resource.ts
1772
1369
  *
@@ -1938,4 +1535,4 @@ type ResourceInbound = ResourceInfoRequest | ResourceBytesRequest | ResourceByte
1938
1535
  */
1939
1536
  type ResourceOutbound = ResourceInfoResult | ResourceInfoError | ResourceBytesResult | ResourceBytesError | ResourceBytesManyResult | ResourceBytesManyError;
1940
1537
 
1941
- export { type AclCheckEvent, type AclEntry, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysForwarder, type KeysForwarderDeps, type KeysForwarderOriginRegistry, type KeysForwarderSessionRegistry, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletNamespacePreludeOptions, type NotifyProxy, type NotifyProxyDeps, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type ResourceInfo, type ResourceInfoError, type ResourceInfoRequest, type ResourceInfoResult, type ResourceOutbound, type ResourceRequestId, type SerialHooks, type ShellAdapter, type ShellBridge, type ShellCapabilities, type ThemeProxy, type ThemeProxyDeps, type UnroutedMessageInfo, type UploadBackendLike, type UploadHooks, type WebrtcHooks, type WindowManagerHooks, type WorkerRelayHooks, type WorkerRelayLike, adaptHooks, audioManager, buildShellCapabilities, createIdentityProxy, createKeysForwarder, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, originRegistry, renderNappletNamespacePrelude, sessionRegistry };
1538
+ export { type AclCheckEvent, type AclEntry, type AclStore, type AudioManager, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type ManifestCache, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletNamespacePreludeOptions, type NotifyProxy, type NotifyProxyDeps, type OriginIdentity, type OriginRegistry, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type ResourceInfo, type ResourceInfoError, type ResourceInfoRequest, type ResourceInfoResult, type ResourceOutbound, type ResourceRequestId, type SerialHooks, type SessionRegistry, type ShellAdapter, type ShellBridge, type ShellCapabilities, type ThemeProxy, type ThemeProxyDeps, type UnroutedMessageInfo, type UploadBackendLike, type UploadHooks, type WebrtcHooks, type WindowManagerHooks, type WorkerRelayHooks, type WorkerRelayLike, adaptHooks, audioManager, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, originRegistry, renderNappletNamespacePrelude, sessionRegistry };