@kehto/shell 0.22.0 → 0.24.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 CHANGED
@@ -34,7 +34,7 @@ Current draft behaviors this package enforces:
34
34
  when the runtime can identify it. The shell forwards this optional context
35
35
  without imposing a consent policy; host runtimes may ignore it or use it to
36
36
  resolve their own identity-scoped signer decisions.
37
- - `prepareNappletSrcdoc()` inserts validated CSP first, then the NIP-5D bootstrap and mandatory NAP-SHELL shim, outside verified artifact bytes. The shim installs the parent-bound `shell.init` receiver, emits one `shell.ready`, and exposes callable NAP interfaces before authored scripts run. Optional namespaces are filtered to the bare-domain allowlist; `shell` is always retained. Published core 0.32.0 and shim 0.30.0 omit generic mandatory shell, so Kehto retains this host-owned prelude under NAP-SHELL `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24` until an upstream correction is reviewed.
37
+ - `prepareNappletSrcdoc()` inserts validated CSP and the runtime namespace outside verified artifact bytes. It exposes only the host-selected bare domains. Optional `shell` installs its parent-bound receiver before readiness; routing uses trusted iframe creation identity independently of that exchange. See the living [NAP-SHELL](https://github.com/napplet/naps/blob/master/naps/NAP-SHELL.md).
38
38
  - The injected resource projection follows draft NAP-RESOURCE `9511232f69313aa7953d110e35d32cc28d506f66`: `bytes(url, { servers? })` carries advisory Blossom locations and `bytesMany(requests)` keeps each `{ url, servers? }` entry intact.
39
39
  - `window.napplet.shell.supports(domain)` answers synchronously and locally from the cached first `shell.init` environment. It returns `false` before `shell.init`, for unknown values, and for domains that are not live and granted to that napplet; it never sends a support-query message.
40
40
  - Five optional per-domain proxies — `createIdentityProxy`, `createThemeProxy`, `createKeysProxy`, `createMediaProxy`, `createNotifyProxy` — can be composed between napplet and runtime to intercept request traffic per NAP. They are NOT wired by default. Identity/theme proxy `emit()` compatibility members fail closed; hosts must deliver automatic changes through `ShellBridge.publishIdentityChanged()` / `publishTheme()`, which enforce live session, granted domain, and current ACL.
@@ -76,24 +76,23 @@ the prior opener-only interpretation is obsolete.
76
76
 
77
77
  ### NAP-INTENT binding and delivery
78
78
 
79
- Kehto implements merged [NAP-INTENT at
80
- `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`](https://github.com/napplet/naps/blob/5ac0490461ca6fec2f0d2e45b4835cf9bc08de24/naps/NAP-INTENT.md).
81
- The protected `window.napplet.intent` binding accepts structured
82
- `invoke(request)` calls and `open(archetype, payload?, opts?)`. It defaults
83
- `action` to `open`, preserves an optional queryless convention, rejects
84
- unsupported fields and caller-supplied sender data, and resolves only
85
- parent-originated correlated results.
86
-
87
- Successful results include `handled`, `handler`, `windowId`, and `convention`
88
- after target dispatch completes. Target delivery now follows NAP-INTENT at
89
- `25b29ee49e5bff8ebfe031f4b76dce98705c8b7e`: one `intent.deliver` envelope
90
- feeds the buffered `onDelivery` binding described below. Broader invocation and
91
- result changes from that newer spec remain deferred.
92
-
93
- Phase 105 completed released `@napplet/*` package adoption and persistent live
94
- Paja/playground catalogs and target controllers. The Phase 104 Paja simulator
95
- and playground catalog builder are historical exact-contract consumers; preserve
96
- archived planning rather than presenting it as active guidance.
79
+ Kehto follows [NAP-INTENT PR #106](https://github.com/napplet/naps/blob/fc121fc264615482143eda86125863d2e1f741a2/naps/NAP-INTENT.md) at `fc121fc264615482143eda86125863d2e1f741a2`. The protected binding supports
80
+ `window.napplet.intent.invoke('napplet:profile/open?pubkey=abc%2B123')` and
81
+ `invoke(uri, { payload, handler, handlerHint, behavior })`. Query fields decode
82
+ once into text; `+` remains literal. An explicit payload cannot accompany an
83
+ inner query, and a `#naddr` recommendation cannot accompany `handlerHint`.
84
+ Unsupported options and caller-supplied sender data are rejected. Only a
85
+ parent-originated correlated result can settle the call.
86
+
87
+ Successful results identify retained delivery responsibility with `ok`,
88
+ `archetype`, `action`, `convention`, and an opaque `handler`. A target receives
89
+ one parent-attested `intent.deliver`, buffered by `onDelivery` until registration.
90
+ Acceptance is separate from later target completion.
91
+
92
+ Legacy object-form `invoke(request)` and `open(archetype, payload?, opts?)`
93
+ remain bounded compatibility adapters and warn once per iframe with
94
+ `KEHTO_COMPAT_INTENT_OBJECT_INVOKE`. Their removal conditions are tracked in
95
+ [compatibility](https://github.com/kehto/web/blob/main/docs/compatibility.md).
97
96
 
98
97
  ## Quick Start
99
98
 
@@ -199,7 +198,7 @@ automatic changes are accepted only when their `MessageEvent.source` is
199
198
  the canonical operations.
200
199
 
201
200
  `ShellBridge` delivers `identity.changed` and `theme.changed` exactly once per
202
- eligible recipient: a live authenticated `shell.ready` session, its frozen
201
+ eligible recipient: a live authenticated source-bound session, its frozen
203
202
  environment includes the relevant domain, and its current recipient read
204
203
  capability is still granted. Identity sign-out is `pubkey: ""`. Theme updates
205
204
  arrive only after the service has stored the complete color state. These are
@@ -256,8 +255,8 @@ MIT
256
255
 
257
256
  ## NIP-5D event compatibility
258
257
 
259
- Current manifests use a direct artifact `x` hash, plain-text `content`, independent
260
- `z`/`i` routing declarations, and required `R` / optional `O` domains. Kehto also
258
+ Current manifests use a direct artifact `x` hash, plain-text `content`, role-matched
259
+ `z`/`i` intent declarations, and required `R` / optional `O` domains. Kehto also
261
260
  accepts legacy aggregate events through an isolated compatibility adapter.
262
261
  Existing `aggregateHash` host/cache/ACL fields carry the verified artifact hash
263
262
  for current events; legacy identities keep their original aggregate. Both paths
@@ -275,5 +274,16 @@ A throwing listener does not prevent delivery to other listeners.
275
274
  When no canonical listener is registered, matching legacy INC listeners can
276
275
  consume the delivery locally. This emits `KEHTO_COMPAT_INTENT_INC` once per
277
276
  iframe; a delivery is never replayed to both APIs. See [compatibility tracking](https://github.com/kehto/web/blob/main/docs/compatibility.md).
278
- This aligns delivery with NAP-INTENT at `25b29ee`; broader invocation/result
279
- changes and the packaged SDK upgrade remain deferred.
277
+ Delivery and URI invocation follow NAP-INTENT PR #106 at
278
+ `fc121fc264615482143eda86125863d2e1f741a2`; the packaged SDK still trails that
279
+ contract, as documented in the conformance policy.
280
+
281
+ ## Paja URL integration
282
+
283
+ The shell normalizer also powers Paja intent links. See the
284
+ [Paja guide](https://kehto.github.io/web/docs/packages/paja.html#nap-intent-links-and-lifecycle)
285
+ for outer URL encoding, review, routing, and verified launcher behavior.
286
+
287
+ ## GAMEPAD integration
288
+
289
+ This non-normative guidance defers to the living [NAP-GAMEPAD](https://github.com/napplet/naps/pull/108). Services export `createGamepadService` and `browserGamepadOptions`; shell exports `denyNappletControllerAccess`. Paja and the playground register one host reader and deny native gamepad/HID/USB paths before frame execution. Source-bound subscriptions receive immediate full snapshots; only the visible host's input owner gets live controls. Focus loss supplies neutral controls and timestamp zero; unsubscribe, window destruction, and service removal release polling. Non-browser or denied native readers report the proposal's unavailable reasons. See [Controller input](https://github.com/kehto/web/blob/main/docs/gamepad.md).
package/dist/index.d.ts CHANGED
@@ -327,7 +327,7 @@ interface UnroutedMessageInfo {
327
327
  /**
328
328
  * Static capability set sent to napplet iframes through the shell.ready /
329
329
  * shell.init handshake. Optional runtime domain presence is injected before
330
- * authored code, while mandatory NAP-SHELL caches this environment for local
330
+ * authored code, while optional NAP-SHELL caches this environment for local
331
331
  * capability queries.
332
332
  *
333
333
  * NAP-SHELL needs only a truthful set of bare domain names. The shim answers
@@ -584,6 +584,14 @@ interface ShellBridge {
584
584
  }
585
585
  declare function createShellBridge(hooks: ShellAdapter): ShellBridge;
586
586
 
587
+ /**
588
+ * Restrict native controller/device APIs before assigning a napplet document.
589
+ * @param frame Host-owned iframe, before its authored code executes.
590
+ * @returns Nothing; unrelated Permissions-Policy entries are retained.
591
+ * @example denyNappletControllerAccess(frame);
592
+ */
593
+ declare function denyNappletControllerAccess(frame: Pick<HTMLIFrameElement, 'getAttribute' | 'setAttribute'>): void;
594
+
587
595
  /**
588
596
  * The injected implementation must remain one self-contained function: the
589
597
  * renderer serializes it ahead of verified artifact scripts without changing
@@ -605,7 +613,7 @@ declare function createShellBridge(hooks: ShellAdapter): ShellBridge;
605
613
  interface NappletNamespacePreludeOptions {
606
614
  /**
607
615
  * Optional bare NAP domain names the shell exposes to this napplet.
608
- * Mandatory `shell` is injected even when omitted here.
616
+ * Shell is injected only when included in the exposed domains.
609
617
  */
610
618
  domains: readonly string[];
611
619
  }
@@ -639,6 +647,38 @@ declare function renderNappletNamespacePrelude(options: NappletNamespacePreludeO
639
647
  */
640
648
  declare function injectNappletNamespacePrelude(html: string, options: NappletNamespacePreludeOptions): string;
641
649
 
650
+ /** Canonical request fields produced from a NAP-INTENT convention URI. */
651
+ interface NormalizedIntentUri {
652
+ archetype: string;
653
+ action: string;
654
+ convention: string;
655
+ payload?: unknown;
656
+ handlerHint?: {
657
+ address: string;
658
+ relays?: string[];
659
+ };
660
+ handler?: string;
661
+ behavior?: {
662
+ focus?: boolean;
663
+ reuse?: boolean;
664
+ };
665
+ }
666
+ /**
667
+ * Normalize a NAP-INTENT convention URI.
668
+ *
669
+ * The host and injected NIP-5D binding use the same normalizer factory.
670
+ *
671
+ * @param uri - Complete NAP-INTENT convention URI.
672
+ * @param options - Optional payload, handler, recommendation, and behavior hints.
673
+ * @returns The canonical request fields for `intent.invoke`.
674
+ * @example
675
+ * ```ts
676
+ * normalizeIntentUri('napplet:profile/open?pubkey=abc%2B123');
677
+ * // { archetype: 'profile', action: 'open', convention: 'napplet:profile/open', payload: { pubkey: 'abc+123' } }
678
+ * ```
679
+ */
680
+ declare const normalizeIntentUri: (uri: unknown, options?: unknown) => NormalizedIntentUri;
681
+
642
682
  /** Source-list directives supported by the shell's meta-delivered CSP. */
643
683
  type NappletCspDirective = 'default-src' | 'script-src' | 'script-src-elem' | 'script-src-attr' | 'style-src' | 'style-src-elem' | 'style-src-attr' | 'img-src' | 'font-src' | 'connect-src' | 'worker-src' | 'child-src' | 'frame-src' | 'media-src' | 'object-src' | 'manifest-src' | 'base-uri' | 'form-action';
644
684
  /** Host replacements for individual CSP source lists; omitted directives retain defaults. */
@@ -1528,4 +1568,4 @@ type ResourceInbound = ResourceInfoRequest | ResourceBytesRequest | ResourceByte
1528
1568
  */
1529
1569
  type ResourceOutbound = ResourceInfoResult | ResourceInfoError | ResourceBytesResult | ResourceBytesError | ResourceBytesManyResult | ResourceBytesManyError;
1530
1570
 
1531
- 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 NappletCspDirective, type NappletCspDirectives, type NappletCspOptions, type NappletNamespacePreludeOptions, type NappletSrcdocOptions, 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 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, buildNappletCsp, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, injectNappletCsp, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, originRegistry, prepareNappletSrcdoc, renderNappletCspMeta, renderNappletNamespacePrelude, resolveShellEnvironment, sessionRegistry };
1571
+ 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 NappletCspDirective, type NappletCspDirectives, type NappletCspOptions, type NappletNamespacePreludeOptions, type NappletSrcdocOptions, type NormalizedIntentUri, 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 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, buildNappletCsp, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, denyNappletControllerAccess, injectNappletCsp, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, normalizeIntentUri, originRegistry, prepareNappletSrcdoc, renderNappletCspMeta, renderNappletNamespacePrelude, resolveShellEnvironment, sessionRegistry };