@kehto/shell 0.19.2 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -7
- package/dist/index.d.ts +9 -2
- package/dist/index.js +30 -5
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Browser adapter over @kehto/runtime — ShellBridge and domain proxies.
|
|
4
4
|
|
|
5
|
-
> **Alpha status:** Kehto is an early runtime
|
|
5
|
+
> **Alpha status:** Kehto is an early runtime toolkit for a draft NIP-5D
|
|
6
6
|
> protocol. NAP contracts and injected-domain behavior are still draft; treat
|
|
7
7
|
> this package as current implementation guidance.
|
|
8
8
|
|
|
@@ -15,9 +15,11 @@ pnpm add @kehto/shell
|
|
|
15
15
|
## Published Napplet Compatibility
|
|
16
16
|
|
|
17
17
|
`@kehto/shell` publishes against `@napplet/core` and `@napplet/nap`
|
|
18
|
-
`>=0.31.0 <0.32.0`. The installed core/nap 0.31.
|
|
19
|
-
`
|
|
20
|
-
`
|
|
18
|
+
`>=0.31.0 <0.32.0`. The installed core 0.31.1 / nap 0.31.2 contracts follow
|
|
19
|
+
NAP-INTENT authority `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`, napplet/web#199
|
|
20
|
+
source `3037200c932488f14f7f369b8583c39c9c16510a` / merge
|
|
21
|
+
`b3f0007867eac109fa4917fac9c285d3b7cc6155`, and Version Packages #198 release
|
|
22
|
+
source `dc1d24153c759152b6ba31a6ec9bea967798f2df`.
|
|
21
23
|
|
|
22
24
|
## Overview
|
|
23
25
|
|
|
@@ -28,11 +30,15 @@ The primary entry point is `createShellBridge()` — it owns the postMessage lis
|
|
|
28
30
|
Current draft behaviors this package enforces:
|
|
29
31
|
|
|
30
32
|
- The shell does not inject a host-provided nostr object into napplets — NIP-5D explicitly forbids napplet-visible signing. Napplets call `relay.publish` / `relay.publishEncrypted` and the shell mediates the signing flow internally (NIP-44 default, NIP-04 opt-in for encrypted envelopes).
|
|
31
|
-
- `
|
|
33
|
+
- `AuthHooks.getSigner(windowId?)` receives the originating iframe window ID
|
|
34
|
+
when the runtime can identify it. The shell forwards this optional context
|
|
35
|
+
without imposing a consent policy; host runtimes may ignore it or use it to
|
|
36
|
+
resolve their own identity-scoped signer decisions.
|
|
37
|
+
- `injectNappletNamespacePrelude()` implements the NIP-5D injected-domain bootstrap and mandatory NAP-SHELL shim: hosts prepend it to `srcdoc` outside verified artifact bytes, install the parent-bound `shell.init` receiver, emit one `shell.ready`, and expose callable NAP interfaces before authored scripts run. Optional namespaces are filtered to the bare-domain allowlist; `shell` is always retained. Published core 0.31.1 and shim 0.29.2 omit generic mandatory shell, so Kehto retains this host-owned prelude under NAP-SHELL `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24` until an upstream correction is reviewed.
|
|
32
38
|
- `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.
|
|
33
39
|
- 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.
|
|
34
40
|
- `keys.forward` is napplet-to-shell only. Active napplets suppress locally-bound keys from `keys.bindings` before forwarding; shell-initiated action triggers use `keys.action`.
|
|
35
|
-
- `buildShellCapabilities()` advertises only live domains
|
|
41
|
+
- `buildShellCapabilities()` advertises only live domains. Registered `dm` and `fs` services are injected only when their handlers exist; disabled domains are absent from the delivered `domains` and named services snapshots.
|
|
36
42
|
|
|
37
43
|
### NAP-INC binding and channel contract
|
|
38
44
|
|
|
@@ -54,7 +60,7 @@ dispatch, and does not infer payload kinds. Runtime delivery supplies the
|
|
|
54
60
|
**runtime-attested dTag**; no caller sender is accepted, topic source exclusion
|
|
55
61
|
is runtime-owned, and IDs and payloads are opaque.
|
|
56
62
|
|
|
57
|
-
Merged NAP-INC and released `@napplet/nap@0.31.
|
|
63
|
+
Merged NAP-INC and released `@napplet/nap@0.31.2` both deliver one `IncEvent`
|
|
58
64
|
to `on(topic, callback)`.
|
|
59
65
|
|
|
60
66
|
For channels, runtime ACL checks are open-only rather than per-message. The
|
package/dist/index.d.ts
CHANGED
|
@@ -132,8 +132,15 @@ interface WindowManagerHooks {
|
|
|
132
132
|
interface AuthHooks {
|
|
133
133
|
/** Get the current user's pubkey, or null if not logged in. */
|
|
134
134
|
getUserPubkey(): string | null;
|
|
135
|
-
/**
|
|
136
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Get the NIP-07 compatible signer, or null if unavailable.
|
|
137
|
+
*
|
|
138
|
+
* The optional window ID lets a shell bind its own signer policy to the
|
|
139
|
+
* requesting napplet without imposing that policy in Kehto.
|
|
140
|
+
*
|
|
141
|
+
* @param windowId - Originating napplet window, when available
|
|
142
|
+
*/
|
|
143
|
+
getSigner(windowId?: string): any | null;
|
|
137
144
|
}
|
|
138
145
|
/** Hook for config. */
|
|
139
146
|
interface ConfigHooks {
|
package/dist/index.js
CHANGED
|
@@ -88,8 +88,8 @@ function createAuthAdapter(shellHooks) {
|
|
|
88
88
|
getUserPubkey() {
|
|
89
89
|
return shellHooks.auth.getUserPubkey();
|
|
90
90
|
},
|
|
91
|
-
getSigner() {
|
|
92
|
-
return shellHooks.auth.getSigner();
|
|
91
|
+
getSigner(windowId) {
|
|
92
|
+
return shellHooks.auth.getSigner(windowId);
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
}
|
|
@@ -999,7 +999,8 @@ var SERVICE_ONLY_DOMAINS = [
|
|
|
999
999
|
"ble",
|
|
1000
1000
|
"webrtc",
|
|
1001
1001
|
"dm",
|
|
1002
|
-
"count"
|
|
1002
|
+
"count",
|
|
1003
|
+
"fs"
|
|
1003
1004
|
];
|
|
1004
1005
|
function buildShellCapabilities(hooks) {
|
|
1005
1006
|
const disabled = new Set(hooks.capabilities?.disabledDomains ?? []);
|
|
@@ -1046,8 +1047,6 @@ function isServiceDomainLive(hooks, domain) {
|
|
|
1046
1047
|
return hooks.ble?.isAvailable() === true;
|
|
1047
1048
|
case "webrtc":
|
|
1048
1049
|
return hooks.webrtc?.isAvailable() === true;
|
|
1049
|
-
case "dm":
|
|
1050
|
-
return hooks.dm !== void 0;
|
|
1051
1050
|
default:
|
|
1052
1051
|
return true;
|
|
1053
1052
|
}
|
|
@@ -2433,6 +2432,30 @@ function nappletNamespacePrelude(domains) {
|
|
|
2433
2432
|
}
|
|
2434
2433
|
};
|
|
2435
2434
|
}
|
|
2435
|
+
function makeFs() {
|
|
2436
|
+
const withOptions = (payload, options) => {
|
|
2437
|
+
if (options !== void 0) payload.options = options;
|
|
2438
|
+
return payload;
|
|
2439
|
+
};
|
|
2440
|
+
const req = (action, payload, map) => request({ type: `fs.${action}`, ...payload }, `fs.${action}.result`, map);
|
|
2441
|
+
return {
|
|
2442
|
+
info: () => req("info", {}, (msg) => fieldOrThrow(msg, "info", "fs.info.result missing info")),
|
|
2443
|
+
pickFile: (options) => req("pickFile", withOptions({}, options), (msg) => fieldOrThrow(msg, "result", "fs.pickFile.result missing result")),
|
|
2444
|
+
pickFiles: (options) => req("pickFiles", withOptions({}, options), (msg) => fieldOrThrow(msg, "result", "fs.pickFiles.result missing result")),
|
|
2445
|
+
pickDirectory: (options) => req("pickDirectory", withOptions({}, options), (msg) => fieldOrThrow(msg, "result", "fs.pickDirectory.result missing result")),
|
|
2446
|
+
pickSaveFile: (options) => req("pickSaveFile", withOptions({}, options), (msg) => fieldOrThrow(msg, "result", "fs.pickSaveFile.result missing result")),
|
|
2447
|
+
stat: (path) => req("stat", { path }, (msg) => fieldOrThrow(msg, "metadata", "fs.stat.result missing metadata")),
|
|
2448
|
+
list: (path) => req("list", { path }, (msg) => fieldOrThrow(msg, "entries", "fs.list.result missing entries")),
|
|
2449
|
+
read: (path, options) => req("read", withOptions({ path }, options), (msg) => fieldOrThrow(msg, "result", "fs.read.result missing result")),
|
|
2450
|
+
write: (path, data, options) => req("write", withOptions({ path, data }, options), (msg) => fieldOrThrow(msg, "result", "fs.write.result missing result")),
|
|
2451
|
+
mkdir: (path, options) => req("mkdir", withOptions({ path }, options), (msg) => voidResult(msg, "fs mkdir failed")),
|
|
2452
|
+
remove: (path, recursive) => req("remove", { path, ...recursive === void 0 ? {} : { recursive } }, (msg) => voidResult(msg, "fs remove failed")),
|
|
2453
|
+
move: (fromPath, toPath) => req("move", { fromPath, toPath }, (msg) => voidResult(msg, "fs move failed")),
|
|
2454
|
+
watch: (path, options) => req("watch", withOptions({ path }, options), (msg) => fieldOrThrow(msg, "watchId", "fs.watch.result missing watchId")),
|
|
2455
|
+
unwatch: (watchId) => req("unwatch", { watchId }, (msg) => voidResult(msg, "fs unwatch failed")),
|
|
2456
|
+
onChanged: (callback) => domainEventHandle("fs.changed", callback, (msg) => msg.change)
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2436
2459
|
const shell = makeShell();
|
|
2437
2460
|
let inc;
|
|
2438
2461
|
let identity;
|
|
@@ -2502,6 +2525,8 @@ function nappletNamespacePrelude(domains) {
|
|
|
2502
2525
|
return makeSerial();
|
|
2503
2526
|
case "dm":
|
|
2504
2527
|
return makeDm();
|
|
2528
|
+
case "fs":
|
|
2529
|
+
return makeFs();
|
|
2505
2530
|
default:
|
|
2506
2531
|
return {};
|
|
2507
2532
|
}
|