@kehto/shell 0.16.7 → 0.18.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/README.md +99 -15
- package/dist/index.d.ts +146 -621
- package/dist/index.js +593 -215
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,38 @@ import { NappletMessage, NostrEvent, NostrFilter } from '@napplet/core';
|
|
|
4
4
|
export { NappletMessage, NostrEvent, NostrFilter, TOPICS, TopicKey, TopicValue } from '@napplet/core';
|
|
5
5
|
import { Theme } from '@napplet/nap/theme/types';
|
|
6
6
|
|
|
7
|
+
/** NIP-5D identity metadata associated with a registered iframe window. */
|
|
8
|
+
interface OriginIdentity {
|
|
9
|
+
readonly dTag: string;
|
|
10
|
+
readonly aggregateHash: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bidirectional registry mapping Window references to windowId strings.
|
|
14
|
+
* Optionally stores NIP-5D identity metadata (dTag and aggregateHash) per window.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { originRegistry } from '@kehto/shell';
|
|
19
|
+
*
|
|
20
|
+
* originRegistry.register(iframe.contentWindow, 'napp-1');
|
|
21
|
+
* const id = originRegistry.getWindowId(iframe.contentWindow); // 'napp-1'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
interface OriginRegistry {
|
|
25
|
+
register(win: Window, windowId: string, identity?: OriginIdentity): void;
|
|
26
|
+
unregister(windowId: string): void;
|
|
27
|
+
getWindowId(win: Window): string | undefined;
|
|
28
|
+
getIframeWindow(windowId: string): Window | null;
|
|
29
|
+
getAllWindowIds(): string[];
|
|
30
|
+
getIdentity(win: Window): OriginIdentity | undefined;
|
|
31
|
+
setEnvironment(win: Window, environment: ShellEnvironment): void;
|
|
32
|
+
getEnvironment(win: Window): ShellEnvironment | undefined;
|
|
33
|
+
getRegistrationId(win: Window): number | undefined;
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
36
|
+
/** Shell-wide iframe window registry singleton. */
|
|
37
|
+
declare const originRegistry: OriginRegistry;
|
|
38
|
+
|
|
7
39
|
/**
|
|
8
40
|
* ACL entry controlling what a napplet pubkey is permitted to do.
|
|
9
41
|
* @example
|
|
@@ -42,8 +74,13 @@ interface RelayPoolHooks {
|
|
|
42
74
|
openScopedRelay(windowId: string, relayUrl: string, subId: string, filters: NostrFilter[], sourceWindow: Window): void;
|
|
43
75
|
/** Close a scoped relay connection. */
|
|
44
76
|
closeScopedRelay(windowId: string): void;
|
|
45
|
-
/**
|
|
46
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Publish to a scoped relay.
|
|
79
|
+
*
|
|
80
|
+
* Async hosts settle the returned promise after transport acceptance.
|
|
81
|
+
* Returns false if no active scoped relay or publication fails.
|
|
82
|
+
*/
|
|
83
|
+
publishToScopedRelay(windowId: string, event: NostrEvent): boolean | Promise<boolean>;
|
|
47
84
|
/** Select relay URLs for a given set of filters. */
|
|
48
85
|
selectRelayTier(filters: NostrFilter[]): string[];
|
|
49
86
|
}
|
|
@@ -54,7 +91,7 @@ interface RelayPoolLike {
|
|
|
54
91
|
unsubscribe(): void;
|
|
55
92
|
};
|
|
56
93
|
};
|
|
57
|
-
publish(relayUrls: string[], event: any): void
|
|
94
|
+
publish(relayUrls: string[], event: any): void | Promise<void>;
|
|
58
95
|
request(relayUrls: string[], filters: any): {
|
|
59
96
|
subscribe(observer: {
|
|
60
97
|
next: (event: unknown) => void;
|
|
@@ -205,8 +242,26 @@ interface WebrtcHooks {
|
|
|
205
242
|
* environments while still using the production shell-ready path.
|
|
206
243
|
*/
|
|
207
244
|
interface CapabilityHooks {
|
|
208
|
-
/** Bare capability domains to remove from
|
|
245
|
+
/** Bare capability domains to remove from the delivered environment. */
|
|
209
246
|
readonly disabledDomains?: readonly string[];
|
|
247
|
+
/**
|
|
248
|
+
* Narrow the live environment for one trusted creation-time identity.
|
|
249
|
+
*
|
|
250
|
+
* The shell supplies copied, frozen live domains and named services. Returned
|
|
251
|
+
* names are intersected with that exact availability set, so this hook cannot
|
|
252
|
+
* add aliases, disabled entries, or unwired capabilities.
|
|
253
|
+
*
|
|
254
|
+
* @param identity - Identity assigned by the host when the iframe was created.
|
|
255
|
+
* @param available - Immutable live domains and services before host policy.
|
|
256
|
+
* @returns The requested subset for this identity.
|
|
257
|
+
*/
|
|
258
|
+
readonly resolveEnvironment?: (identity: OriginIdentity, available: Readonly<{
|
|
259
|
+
domains: readonly string[];
|
|
260
|
+
services: readonly string[];
|
|
261
|
+
}>) => Readonly<{
|
|
262
|
+
domains: readonly string[];
|
|
263
|
+
services: readonly string[];
|
|
264
|
+
}>;
|
|
210
265
|
}
|
|
211
266
|
/**
|
|
212
267
|
* Event emitted on every ACL enforcement check.
|
|
@@ -262,71 +317,21 @@ interface UnroutedMessageInfo {
|
|
|
262
317
|
}
|
|
263
318
|
/**
|
|
264
319
|
* Static capability set sent to napplet iframes through the shell.ready /
|
|
265
|
-
* shell.init handshake.
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
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:
|
|
320
|
+
* shell.init handshake. Optional runtime domain presence is injected before
|
|
321
|
+
* authored code, while mandatory NAP-SHELL caches this environment for local
|
|
322
|
+
* capability queries.
|
|
272
323
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* The sandbox array remains for older payload readers, but Kehto emits it empty.
|
|
277
|
-
* NIP-5D no longer blesses additional browser sandbox tokens as interoperability
|
|
278
|
-
* requirements or napplet-visible capabilities.
|
|
279
|
-
*
|
|
280
|
-
* ## Compatibility NAP-SHELL shape
|
|
281
|
-
*
|
|
282
|
-
* Older shell consumers may read the structured
|
|
283
|
-
* `capabilities.{ domains: string[], protocols: Record<string, string[]> }`
|
|
284
|
-
* alongside the flat `naps` array:
|
|
285
|
-
*
|
|
286
|
-
* - `supports('relay')` → true iff `'relay' ∈ capabilities.domains`
|
|
287
|
-
* - `supports('inc','NAP-01')`→ true iff `capabilities.protocols['inc']`
|
|
288
|
-
* includes `'NAP-01'`
|
|
289
|
-
*
|
|
290
|
-
* `domains` and `protocols` are emitted as a superset alongside the
|
|
291
|
-
* `naps`/`sandbox` fields for back-compat.
|
|
324
|
+
* NAP-SHELL needs only a truthful set of bare domain names. The shim answers
|
|
325
|
+
* `shell.supports(domain)` locally from this snapshot after `shell.init`.
|
|
292
326
|
*/
|
|
293
327
|
interface ShellCapabilities {
|
|
294
|
-
/**
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
*/
|
|
302
|
-
domains: string[];
|
|
303
|
-
/**
|
|
304
|
-
* Compatibility NAP-SHELL per-domain numbered protocols. Maps a domain to the NAP-NN protocol IDs it
|
|
305
|
-
* speaks — `{ inc: ['NAP-01','NAP-02','NAP-03','NAP-04','NAP-05','NAP-06'] }`
|
|
306
|
-
* (derived from `NAP_INC_PROTOCOLS` by stripping the `inc:` prefix).
|
|
307
|
-
*
|
|
308
|
-
* Legacy supports helpers resolve `supports('<domain>','NAP-NN')` against this map.
|
|
309
|
-
*/
|
|
310
|
-
protocols: Record<string, string[]>;
|
|
311
|
-
/**
|
|
312
|
-
* NAP-vocabulary domain entries the shell handles (PRIMARY — consumed by
|
|
313
|
-
* `@napplet/shim >=0.9.0`). Bare domain `inc` (the NAP rename of `inc`)
|
|
314
|
-
* plus protocol IDs `inc:NAP-01..inc:NAP-06`. Conditional entries:
|
|
315
|
-
* `relay`, `outbox` prepended when a relay pool is wired; `upload` appended
|
|
316
|
-
* when an upload backend is wired; `intent` appended when an intent
|
|
317
|
-
* dispatcher is available.
|
|
318
|
-
*
|
|
319
|
-
* Contains NO `NAP-NN` protocol strings (those live in `protocols`).
|
|
320
|
-
*/
|
|
321
|
-
naps: string[];
|
|
322
|
-
/**
|
|
323
|
-
* Empty compatibility field for older `shell.init` payload consumers.
|
|
324
|
-
*
|
|
325
|
-
* Current NIP-5D keeps the web sandbox baseline narrow: hosted napplet iframes
|
|
326
|
-
* use `allow-scripts`, never `allow-same-origin`, and do not receive optional
|
|
327
|
-
* browser sandbox relaxations as advertised capabilities.
|
|
328
|
-
*/
|
|
329
|
-
sandbox: string[];
|
|
328
|
+
/** Immutable bare domain names the shell offers to this napplet. */
|
|
329
|
+
readonly domains: readonly string[];
|
|
330
|
+
}
|
|
331
|
+
/** Immutable NAP-SHELL environment delivered to one trusted iframe session. */
|
|
332
|
+
interface ShellEnvironment {
|
|
333
|
+
readonly capabilities: ShellCapabilities;
|
|
334
|
+
readonly services: readonly string[];
|
|
330
335
|
}
|
|
331
336
|
/**
|
|
332
337
|
* All adapters that the shell requires from the host application.
|
|
@@ -532,18 +537,13 @@ interface ShellBridge {
|
|
|
532
537
|
*/
|
|
533
538
|
registerConsentHandler(handler: (request: ConsentRequest) => void): void;
|
|
534
539
|
/**
|
|
535
|
-
* Publish a theme update to
|
|
540
|
+
* Publish a theme update to each eligible napplet.
|
|
536
541
|
*
|
|
537
542
|
* Posts a `theme.changed` envelope (shell → napplet push) to every
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
* ACL is enforced BY THE RECIPIENT NAPPLET — the runtime's
|
|
544
|
-
* `themeMap` in @kehto/acl assigns `recipientCap: 'theme:read'` for
|
|
545
|
-
* `theme.changed`, and @napplet/shim drops pushes the napplet lacks
|
|
546
|
-
* the capability for. Hosts should not self-filter here.
|
|
543
|
+
* live authenticated session whose frozen environment grants `theme` and
|
|
544
|
+
* whose current ACL grants `theme:read`. Stale or ineligible sessions are
|
|
545
|
+
* skipped before origin-registry delivery; recipient code is not trusted
|
|
546
|
+
* to enforce host authorization.
|
|
547
547
|
*
|
|
548
548
|
* @param theme - The new theme payload to broadcast.
|
|
549
549
|
* @example
|
|
@@ -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
|
-
*
|
|
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,77 +630,6 @@ declare function renderNappletNamespacePrelude(options: NappletNamespacePreludeO
|
|
|
621
630
|
*/
|
|
622
631
|
declare function injectNappletNamespacePrelude(html: string, options: NappletNamespacePreludeOptions): string;
|
|
623
632
|
|
|
624
|
-
/**
|
|
625
|
-
* Bidirectional registry mapping Window references to windowId strings.
|
|
626
|
-
* Optionally stores NIP-5D identity metadata (dTag and aggregateHash) per window.
|
|
627
|
-
*
|
|
628
|
-
* @example
|
|
629
|
-
* ```ts
|
|
630
|
-
* import { originRegistry } from '@kehto/shell';
|
|
631
|
-
*
|
|
632
|
-
* originRegistry.register(iframe.contentWindow, 'napp-1');
|
|
633
|
-
* const id = originRegistry.getWindowId(iframe.contentWindow); // 'napp-1'
|
|
634
|
-
* ```
|
|
635
|
-
*/
|
|
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
|
-
*/
|
|
653
|
-
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
|
-
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
|
-
getIframeWindow(windowId: string): Window | null;
|
|
668
|
-
/**
|
|
669
|
-
* Get all registered windowId strings.
|
|
670
|
-
*
|
|
671
|
-
* @returns Array of all registered window identifiers
|
|
672
|
-
*/
|
|
673
|
-
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
|
-
*/
|
|
690
|
-
getRegistrationId(win: Window): number | undefined;
|
|
691
|
-
/** Clear all registrations. */
|
|
692
|
-
clear(): void;
|
|
693
|
-
};
|
|
694
|
-
|
|
695
633
|
/**
|
|
696
634
|
* Manifest cache — persists verified NIP-5A aggregate hashes per napplet identity.
|
|
697
635
|
*/
|
|
@@ -723,44 +661,17 @@ interface ManifestCacheEntry {
|
|
|
723
661
|
* const entry = manifestCache.get('abc...', 'chat');
|
|
724
662
|
* ```
|
|
725
663
|
*/
|
|
726
|
-
|
|
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
|
-
*/
|
|
664
|
+
interface ManifestCache {
|
|
734
665
|
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
666
|
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
667
|
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
668
|
remove(pubkey: string, dTag: string): void;
|
|
757
|
-
/** Load the cache from localStorage. */
|
|
758
669
|
load(): void;
|
|
759
|
-
/** Persist the cache to localStorage. */
|
|
760
670
|
persist(): void;
|
|
761
|
-
/** Clear all cached entries and remove from localStorage. */
|
|
762
671
|
clear(): void;
|
|
763
|
-
}
|
|
672
|
+
}
|
|
673
|
+
/** Shell-wide manifest verification cache singleton. */
|
|
674
|
+
declare const manifestCache: ManifestCache;
|
|
764
675
|
|
|
765
676
|
/**
|
|
766
677
|
* ACL store — manages capability grants, revocations, and blocks for napp identities.
|
|
@@ -774,92 +685,22 @@ declare const manifestCache: {
|
|
|
774
685
|
* const allowed = aclStore.check(pubkey, dTag, hash, 'relay:read'); // true
|
|
775
686
|
* ```
|
|
776
687
|
*/
|
|
777
|
-
|
|
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
|
-
*/
|
|
688
|
+
interface AclStore {
|
|
788
689
|
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
690
|
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
691
|
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
692
|
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
693
|
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
694
|
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
695
|
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
696
|
getAllEntries(): AclEntry[];
|
|
847
|
-
/** Persist the ACL store to localStorage. */
|
|
848
697
|
persist(): void;
|
|
849
|
-
/** Load the ACL store from localStorage. Migrates old 3-segment keys to 2-segment format. */
|
|
850
698
|
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
699
|
getStateQuota(pubkey: string, dTag: string, aggregateHash: string): number;
|
|
860
|
-
/** Clear all ACL entries and remove from localStorage. */
|
|
861
700
|
clear(): void;
|
|
862
|
-
}
|
|
701
|
+
}
|
|
702
|
+
/** Shell ACL store singleton. */
|
|
703
|
+
declare const aclStore: AclStore;
|
|
863
704
|
|
|
864
705
|
/**
|
|
865
706
|
* audio-manager.ts — Shell-side registry of active audio sources.
|
|
@@ -895,69 +736,22 @@ interface AudioSource {
|
|
|
895
736
|
* audioManager.mute('win-1', true);
|
|
896
737
|
* ```
|
|
897
738
|
*/
|
|
898
|
-
|
|
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
|
-
*/
|
|
739
|
+
interface AudioManager {
|
|
906
740
|
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
741
|
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
742
|
updateState(windowId: string, update: {
|
|
920
743
|
title?: string;
|
|
921
744
|
}): 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
745
|
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
746
|
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
747
|
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
748
|
getSources(): Map<string, AudioSource>;
|
|
954
|
-
/** Current version counter (incremented on every change). */
|
|
955
749
|
readonly version: number;
|
|
956
|
-
/** Number of active audio sources. */
|
|
957
750
|
readonly count: number;
|
|
958
|
-
/** Clear all audio sources and reset version counter. */
|
|
959
751
|
clear(): void;
|
|
960
|
-
}
|
|
752
|
+
}
|
|
753
|
+
/** Shell-wide audio source registry singleton. */
|
|
754
|
+
declare const audioManager: AudioManager;
|
|
961
755
|
|
|
962
756
|
/**
|
|
963
757
|
* SessionRegistry — windowId to verified napplet pubkey bidirectional mapping.
|
|
@@ -978,149 +772,23 @@ declare const audioManager: {
|
|
|
978
772
|
* const entry = pubkey ? sessionRegistry.getEntry(pubkey) : undefined;
|
|
979
773
|
* ```
|
|
980
774
|
*/
|
|
981
|
-
|
|
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
|
-
*/
|
|
775
|
+
interface SessionRegistry {
|
|
988
776
|
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
777
|
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
778
|
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
779
|
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
780
|
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
781
|
isRegistered(windowId: string): boolean;
|
|
1023
|
-
/**
|
|
1024
|
-
* Get all registered napplet entries.
|
|
1025
|
-
*
|
|
1026
|
-
* @returns Array of all SessionEntry objects
|
|
1027
|
-
*/
|
|
1028
782
|
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
783
|
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
784
|
getPendingUpdate(windowId: string): PendingUpdate | undefined;
|
|
1043
|
-
/**
|
|
1044
|
-
* Clear a pending update for a window.
|
|
1045
|
-
*
|
|
1046
|
-
* @param windowId - The window identifier
|
|
1047
|
-
*/
|
|
1048
785
|
clearPendingUpdate(windowId: string): void;
|
|
1049
|
-
/** Clear all registrations and pending updates. */
|
|
1050
786
|
clear(): void;
|
|
1051
|
-
}
|
|
787
|
+
}
|
|
788
|
+
/** Shell-wide verified napplet session registry singleton. */
|
|
789
|
+
declare const sessionRegistry: SessionRegistry;
|
|
1052
790
|
/** @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
|
-
};
|
|
791
|
+
declare const nappKeyRegistry: SessionRegistry;
|
|
1124
792
|
|
|
1125
793
|
/**
|
|
1126
794
|
* hooks-adapter.ts — Converts ShellAdapter (browser-facing) to RuntimeAdapter (environment-agnostic).
|
|
@@ -1166,63 +834,36 @@ interface BrowserDeps {
|
|
|
1166
834
|
declare function adaptHooks(shellHooks: ShellAdapter, deps: BrowserDeps): RuntimeAdapter;
|
|
1167
835
|
|
|
1168
836
|
/**
|
|
1169
|
-
* Build the shell's
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
* injected `window.napplet.<domain>` presence; this payload remains for older
|
|
1174
|
-
* consumers that still inspect shell.init capabilities.
|
|
1175
|
-
*
|
|
1176
|
-
* ### naps array (NAP vocabulary)
|
|
1177
|
-
* Bare domain `inc` + `inc:NAP-01..inc:NAP-06`.
|
|
1178
|
-
* Conditional: `relay`+`outbox` prepended when hooks.relayPool;
|
|
1179
|
-
* `upload` appended when hooks.upload;
|
|
1180
|
-
* `intent` appended when hooks.intent.isAvailable();
|
|
1181
|
-
* `link` appended when hooks.link.isAvailable();
|
|
1182
|
-
* `common` appended when hooks.common.isAvailable().
|
|
1183
|
-
*
|
|
1184
|
-
* The sandbox array is retained as an always-empty compatibility field. Current
|
|
1185
|
-
* NIP-5D defines only the `allow-scripts` baseline and does not make additional
|
|
1186
|
-
* browser sandbox tokens a napplet capability surface.
|
|
1187
|
-
*
|
|
1188
|
-
* ### domains array + protocols map (compatibility NAP-SHELL)
|
|
1189
|
-
* The structured shape older shell capability consumers read:
|
|
1190
|
-
*
|
|
1191
|
-
* - `domains` — bare NAP domain names (the `naps` set MINUS the `inc:NAP-NN`
|
|
1192
|
-
* protocol strings) with the same conditional entries (relay/outbox under
|
|
1193
|
-
* `hooks.relayPool`, upload/intent/link/common under their hooks).
|
|
1194
|
-
* - `protocols` — `{ inc: ['NAP-01'..'NAP-06'] }`, derived from
|
|
1195
|
-
* `NAP_INC_PROTOCOLS` by stripping the `inc:` prefix.
|
|
1196
|
-
*
|
|
1197
|
-
* Emitted as a superset alongside `naps`/`sandbox` for back-compat.
|
|
1198
|
-
*
|
|
1199
|
-
* @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
|
|
837
|
+
* Build the shell's immutable live capability snapshot from adapter wiring.
|
|
838
|
+
*
|
|
839
|
+
* @param hooks - The ShellAdapter provided by the host app.
|
|
840
|
+
* @returns Domain-only ShellCapabilities for the current live wiring.
|
|
1202
841
|
* @example
|
|
1203
842
|
* ```ts
|
|
1204
843
|
* const caps = buildShellCapabilities(hooks);
|
|
1205
|
-
* // caps.domains => ['relay','
|
|
1206
|
-
* // (relay + outbox present when hooks.relayPool is provided; 'upload'/'intent'
|
|
1207
|
-
* // appended under their hooks)
|
|
1208
|
-
* // caps.protocols => { inc: ['NAP-01','NAP-02','NAP-03','NAP-04','NAP-05','NAP-06'] }
|
|
1209
|
-
* // caps.naps => ['relay','outbox','identity','storage','inc','theme','keys','media','notify','config','resource','cvm',
|
|
1210
|
-
* // 'inc:NAP-01','inc:NAP-02','inc:NAP-03','inc:NAP-04','inc:NAP-05','inc:NAP-06']
|
|
1211
|
-
* // (relay + outbox present when hooks.relayPool is provided; 'upload'
|
|
1212
|
-
* // appended when hooks.upload is provided; 'intent' appended when
|
|
1213
|
-
* // hooks.intent.isAvailable() is true)
|
|
1214
|
-
* // caps.sandbox => [] // retained for compatibility; not a NAP capability surface
|
|
844
|
+
* // caps.domains => ['relay', 'identity', 'storage', 'inc', 'theme', 'keys', 'media', 'notify']
|
|
1215
845
|
* ```
|
|
1216
846
|
*/
|
|
1217
847
|
declare function buildShellCapabilities(hooks: ShellAdapter): ShellCapabilities;
|
|
848
|
+
/**
|
|
849
|
+
* Resolve a trusted creation identity's immutable NAP-SHELL environment.
|
|
850
|
+
*
|
|
851
|
+
* This host-adapter API is intentionally not part of `window.napplet`: it
|
|
852
|
+
* bounds host policy to current runtime wiring before `shell.init` crosses into
|
|
853
|
+
* an untrusted iframe.
|
|
854
|
+
*
|
|
855
|
+
* @param hooks - Shell host wiring and optional per-identity grant policy.
|
|
856
|
+
* @param identity - The source's creation-time identity.
|
|
857
|
+
* @returns A fresh immutable environment whose entries are exact live subsets.
|
|
858
|
+
*/
|
|
859
|
+
declare function resolveShellEnvironment(hooks: ShellAdapter, identity: OriginIdentity): ShellEnvironment;
|
|
1218
860
|
|
|
1219
861
|
/**
|
|
1220
862
|
* identity-proxy.ts — Shell-side per-domain proxy for identity.* envelopes.
|
|
1221
863
|
*
|
|
1222
864
|
* Establishes the canonical proxy shape for @kehto/shell (Plan 12-11): each
|
|
1223
865
|
* per-domain proxy exposes a `dispatch` method that delegates napplet→shell
|
|
1224
|
-
* requests to the runtime
|
|
1225
|
-
* push envelopes through the origin registry.
|
|
866
|
+
* requests to the runtime.
|
|
1226
867
|
*
|
|
1227
868
|
* By default, `createShellBridge()` does NOT compose this proxy into its
|
|
1228
869
|
* dispatch path — the runtime already owns identity.* dispatch per Plan
|
|
@@ -1231,10 +872,9 @@ declare function buildShellCapabilities(hooks: ShellAdapter): ShellCapabilities;
|
|
|
1231
872
|
* augment identity dispatch (e.g. custom logging, sandboxed rewrites, test
|
|
1232
873
|
* doubles).
|
|
1233
874
|
*
|
|
1234
|
-
*
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1237
|
-
* this shape can be added later if host apps need a composition seam.
|
|
875
|
+
* Identity changes are deliberately not emitted through this proxy. Hosts
|
|
876
|
+
* must use `ShellBridge.publishIdentityChanged()`, which enforces the live
|
|
877
|
+
* session, granted-domain, and current recipient-capability checks.
|
|
1238
878
|
*/
|
|
1239
879
|
|
|
1240
880
|
/**
|
|
@@ -1267,9 +907,8 @@ interface IdentityProxyDeps {
|
|
|
1267
907
|
/**
|
|
1268
908
|
* Per-domain proxy for `identity.*` envelopes.
|
|
1269
909
|
*
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
* Window.
|
|
910
|
+
* `dispatch` routes napplet→shell requests into the runtime. The deprecated
|
|
911
|
+
* `emit` member remains only as a fail-closed compatibility trap.
|
|
1273
912
|
*/
|
|
1274
913
|
interface IdentityProxy {
|
|
1275
914
|
/**
|
|
@@ -1283,13 +922,10 @@ interface IdentityProxy {
|
|
|
1283
922
|
*/
|
|
1284
923
|
dispatch(windowId: string, envelope: NappletMessage): void;
|
|
1285
924
|
/**
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
* No-op when the originRegistry cannot resolve the windowId (unknown or
|
|
1289
|
-
* unregistered napplet). Never throws.
|
|
925
|
+
* Direct identity delivery is prohibited.
|
|
1290
926
|
*
|
|
1291
|
-
* @
|
|
1292
|
-
*
|
|
927
|
+
* @deprecated Use `ShellBridge.publishIdentityChanged()` so delivery is
|
|
928
|
+
* filtered by live session, granted domain, and current ACL.
|
|
1293
929
|
*/
|
|
1294
930
|
emit(windowId: string, envelope: NappletMessage): void;
|
|
1295
931
|
}
|
|
@@ -1326,12 +962,9 @@ declare function createIdentityProxy(deps: IdentityProxyDeps): IdentityProxy;
|
|
|
1326
962
|
* API that emits `theme.changed` push envelopes to registered napplets;
|
|
1327
963
|
* this proxy is the canonical seam those pieces plug into.
|
|
1328
964
|
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
* the runtime (where Phase 13's theme-service will answer).
|
|
1333
|
-
* - `emit(windowId, envelope)` posts shell→napplet `theme.changed`
|
|
1334
|
-
* envelopes through the origin registry.
|
|
965
|
+
* `dispatch(windowId, envelope)` routes napplet→shell `theme.get` into the
|
|
966
|
+
* runtime. Theme changes must use `ShellBridge.publishTheme()` so the host
|
|
967
|
+
* projection enforces live-session, granted-domain, and current-ACL checks.
|
|
1335
968
|
*
|
|
1336
969
|
* By default `createShellBridge()` does NOT compose this proxy into its
|
|
1337
970
|
* dispatch path — the runtime owns theme.* dispatch. This module is an
|
|
@@ -1358,8 +991,8 @@ interface ThemeProxyDeps {
|
|
|
1358
991
|
/**
|
|
1359
992
|
* Per-domain proxy for `theme.*` envelopes.
|
|
1360
993
|
*
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
994
|
+
* `dispatch` routes napplet→shell requests into the runtime. The deprecated
|
|
995
|
+
* `emit` member remains only as a fail-closed compatibility trap.
|
|
1363
996
|
*/
|
|
1364
997
|
interface ThemeProxy {
|
|
1365
998
|
/**
|
|
@@ -1371,14 +1004,10 @@ interface ThemeProxy {
|
|
|
1371
1004
|
*/
|
|
1372
1005
|
dispatch(windowId: string, envelope: NappletMessage): void;
|
|
1373
1006
|
/**
|
|
1374
|
-
*
|
|
1375
|
-
* into a napplet iframe.
|
|
1007
|
+
* Direct theme delivery is prohibited.
|
|
1376
1008
|
*
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
*
|
|
1380
|
-
* @param windowId - The target napplet's windowId
|
|
1381
|
-
* @param envelope - The NIP-5D NappletMessage envelope to deliver
|
|
1009
|
+
* @deprecated Use `ShellBridge.publishTheme()` so delivery is filtered by
|
|
1010
|
+
* live session, granted domain, and current ACL.
|
|
1382
1011
|
*/
|
|
1383
1012
|
emit(windowId: string, envelope: NappletMessage): void;
|
|
1384
1013
|
}
|
|
@@ -1389,18 +1018,13 @@ interface ThemeProxy {
|
|
|
1389
1018
|
* @returns A {@link ThemeProxy} ready to route theme.* envelopes
|
|
1390
1019
|
* @example
|
|
1391
1020
|
* ```ts
|
|
1392
|
-
* import { createThemeProxy, originRegistry
|
|
1021
|
+
* import { createThemeProxy, originRegistry } from '@kehto/shell';
|
|
1393
1022
|
*
|
|
1394
|
-
* const bridge = createShellBridge(hooks);
|
|
1395
1023
|
* const themeProxy = createThemeProxy({
|
|
1396
|
-
* runtime
|
|
1024
|
+
* runtime,
|
|
1397
1025
|
* originRegistry,
|
|
1398
1026
|
* });
|
|
1399
|
-
*
|
|
1400
|
-
* // Phase 13: broadcast theme.changed to every registered napplet
|
|
1401
|
-
* for (const entry of bridge.runtime.sessionRegistry.getAllEntries()) {
|
|
1402
|
-
* themeProxy.emit(entry.windowId, { type: 'theme.changed', theme: newTheme });
|
|
1403
|
-
* }
|
|
1027
|
+
* themeProxy.dispatch(windowId, { type: 'theme.get', id: requestId });
|
|
1404
1028
|
* ```
|
|
1405
1029
|
*/
|
|
1406
1030
|
declare function createThemeProxy(deps: ThemeProxyDeps): ThemeProxy;
|
|
@@ -1408,11 +1032,11 @@ declare function createThemeProxy(deps: ThemeProxyDeps): ThemeProxy;
|
|
|
1408
1032
|
/**
|
|
1409
1033
|
* keys-proxy.ts — Shell-side per-domain proxy for keys.* envelopes.
|
|
1410
1034
|
*
|
|
1411
|
-
*
|
|
1412
|
-
* registerAction, unregisterAction) to the keys
|
|
1413
|
-
* shell-side composition point for host apps that want to observe or
|
|
1414
|
-
* inject keys envelopes
|
|
1415
|
-
*
|
|
1035
|
+
* The runtime already dispatches napplet-originated `keys.*` (forward,
|
|
1036
|
+
* registerAction, unregisterAction) to the keys service. This proxy is the
|
|
1037
|
+
* shell-side composition point for host apps that want to observe requests or
|
|
1038
|
+
* inject shell-originated keys envelopes such as `keys.action` and
|
|
1039
|
+
* `keys.bindings`.
|
|
1416
1040
|
*
|
|
1417
1041
|
* Shape mirrors identity-proxy (Plan 12-11):
|
|
1418
1042
|
*
|
|
@@ -1463,10 +1087,6 @@ interface KeysProxy {
|
|
|
1463
1087
|
* Push a shell-initiated keys-domain envelope (e.g. `keys.action`,
|
|
1464
1088
|
* `keys.bindings`) into a napplet iframe.
|
|
1465
1089
|
*
|
|
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
1090
|
* No-op when the originRegistry cannot resolve the windowId (unknown or
|
|
1471
1091
|
* unregistered napplet). Never throws.
|
|
1472
1092
|
*
|
|
@@ -1672,101 +1292,6 @@ interface NotifyProxy {
|
|
|
1672
1292
|
*/
|
|
1673
1293
|
declare function createNotifyProxy(deps: NotifyProxyDeps): NotifyProxy;
|
|
1674
1294
|
|
|
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
1295
|
/**
|
|
1771
1296
|
* @file internal-resource.ts
|
|
1772
1297
|
*
|
|
@@ -1938,4 +1463,4 @@ type ResourceInbound = ResourceInfoRequest | ResourceBytesRequest | ResourceByte
|
|
|
1938
1463
|
*/
|
|
1939
1464
|
type ResourceOutbound = ResourceInfoResult | ResourceInfoError | ResourceBytesResult | ResourceBytesError | ResourceBytesManyResult | ResourceBytesManyError;
|
|
1940
1465
|
|
|
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
|
|
1466
|
+
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 ShellEnvironment, 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, resolveShellEnvironment, sessionRegistry };
|