@kehto/services 0.16.5 → 0.17.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 +98 -18
- package/dist/index.d.ts +147 -282
- package/dist/index.js +392 -294
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @kehto/services
|
|
2
2
|
|
|
3
|
-
Reference service handlers for the napplet protocol —
|
|
3
|
+
Reference service handlers for the napplet protocol — identity, relay pool,
|
|
4
|
+
cache, keys, media, notify, theme, link, common, lists, serial, BLE, WebRTC,
|
|
5
|
+
and DM.
|
|
4
6
|
|
|
5
7
|
> **Alpha status:** Kehto is an early runtime implementation for a draft NIP-5D
|
|
6
8
|
> protocol. NAP contracts and service envelopes are not final; treat these
|
|
@@ -12,30 +14,79 @@ Reference service handlers for the napplet protocol — audio, notifications, id
|
|
|
12
14
|
pnpm add @kehto/services
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
## Published Napplet Compatibility
|
|
18
|
+
|
|
19
|
+
`@kehto/services` publishes against `@napplet/core` and `@napplet/nap`
|
|
20
|
+
`>=0.29.0 <0.30.0`. The exact installed contracts are core/nap 0.29.0 from
|
|
21
|
+
source `dd7b3a728eb9c838b7218fcec7bb7bb00e7cc88b` and release
|
|
22
|
+
`60889f1c2476e063500c7ab6624af6abe0dbcbe5`.
|
|
23
|
+
|
|
15
24
|
## Overview
|
|
16
25
|
|
|
17
|
-
`@kehto/services` ships the reference implementations of the `ServiceHandler`
|
|
26
|
+
`@kehto/services` ships the reference implementations of the `ServiceHandler`
|
|
27
|
+
contract defined by `@kehto/runtime`. Each factory returns an object that the
|
|
28
|
+
runtime routes NIP-5D envelopes to by the exact `message.type` domain (for
|
|
29
|
+
example, `notify.create` goes to the handler registered under `notify`).
|
|
18
30
|
|
|
19
31
|
Host apps wire services into the runtime via `runtime.registerService(name, handler)`. The services are browser-agnostic — they have no DOM dependency. Browser-specific behaviors (audio element pool, OS notifications) are delivered through host-supplied callbacks.
|
|
20
32
|
|
|
33
|
+
Services are selected only by the exact `message.type` domain. INC topics are
|
|
34
|
+
opaque, queryless identities matched only by exact equality, so their text must
|
|
35
|
+
not select a service handler. The runtime attaches the sender to delivered INC
|
|
36
|
+
events from the authenticated endpoint; services do not create INC events.
|
|
37
|
+
|
|
21
38
|
Current draft posture:
|
|
22
39
|
|
|
23
40
|
- The v1.1 signer service is deleted outright. Its responsibilities split into two: read-only identity lookups go through `createIdentityService` (`getPublicKey`, `getRelays`, `getProfile`, `getFollows`, `getList`, `getZaps`, `getMutes`, `getBlocked`, `getBadges`); signing happens inside the shell as part of `relay.publish` / `relay.publishEncrypted` and is never exposed to napplets.
|
|
24
41
|
- `createKeysService` and `createMediaService` ship real reference backends as of v1.4 (see the dedicated sections below). `createKeysService` attaches a document-level `keydown` listener by default and delivers `keys.action` push envelopes to registered napplets; `createMediaService` mirrors session metadata and playback state to `navigator.mediaSession` and emits `media.command` push envelopes on OS transport events. Both accept a host-bridge option (`HostKeysBridge` / `HostMediaBridge`) so Electron / Tauri / native shells can swap in OS-level backends without re-implementing the wire-protocol bookkeeping.
|
|
25
|
-
- `createNotifyService`
|
|
42
|
+
- `createNotifyService` handles direct `notify.*` envelopes. It is not an INC
|
|
43
|
+
topic handler.
|
|
26
44
|
- `createOutboxService` supports `outbox.getEvent` from draft NAP-OUTBOX. Single-event lookups run through shell-owned relay routing and only return events whose ID matches the request. The draft wire contract keeps `outbox.query` one-shot and `outbox.subscribe` streaming; Kehto's concrete `createRelayPoolOutboxRouter` additionally exposes host-side `queryStream()` so verified query events can arrive before asynchronous NIP-65 discovery completes.
|
|
27
|
-
- `createResourceService`
|
|
45
|
+
- `createResourceService` retains Kehto-local `resource.bytesMany` compatibility behavior. It is not presented as standalone NAP-RESOURCE wire authority; profile media authority is NAP-IDENTITY's delegated `resource.bytes` contract.
|
|
28
46
|
- `createUploadService` supports `upload.info` from draft NAP-UPLOAD. Hosts may expose configured rails, return URL forms, maximum bytes, and MIME type policy without requiring napplets to start an upload.
|
|
29
|
-
- `createResourceService`
|
|
47
|
+
- `createResourceService` retains `resource.info` and `resource.bytesMany` as Kehto-local compatibility behavior. They do not infer missing standalone NAP-RESOURCE wire semantics.
|
|
30
48
|
- `createDmService` keeps NAP-DM request correlation, subscriptions, and message normalization in runtime-owned code. Adapters cover concrete transports: NIP-17 gift wraps via `nostr-tools`, structural NDR runtimes with relay hooks, and Cordn/ContextVM coordinator clients. Kehto mirrors NAP-DM wire types locally until `@napplet/core` / `@napplet/nap` publish them.
|
|
31
49
|
|
|
50
|
+
## NAP-INTENT manifest resolver
|
|
51
|
+
|
|
52
|
+
Phase 104 follows the draft [NAP-INTENT PR #91 at
|
|
53
|
+
`a718915ddefa2f03a0126579601f59d8bd86f7c4`](https://github.com/napplet/naps/pull/91).
|
|
54
|
+
Callers invoke a stable, queryless `napplet:<archetype>/<action>` convention.
|
|
55
|
+
Installed verified manifest tags produce exact `{ convention, eventKinds? }`
|
|
56
|
+
contracts; numbered protocol names and payload inspection do not select a
|
|
57
|
+
handler.
|
|
58
|
+
|
|
59
|
+
- `manifestToIntentCatalogEntry()` converts resolved manifest
|
|
60
|
+
`{ dTag, title?, archetypes: [{ slug, convention, eventKinds? }] }` data into
|
|
61
|
+
exact candidates with `actions`, `conventions`, and `contracts`.
|
|
62
|
+
- `createCatalogIntentResolver()` filters by exact convention, applies the
|
|
63
|
+
user-owned default/chooser/explicit-authorization policy, and asks an
|
|
64
|
+
`IntentTargetController` to retain immutable delivery responsibility.
|
|
65
|
+
- `createIntentService()` validates source envelopes, uses the runtime-attested
|
|
66
|
+
sender, returns one immediate acceptance or rejection, starts an accepted
|
|
67
|
+
retained task only after the source result, and broadcasts catalog changes
|
|
68
|
+
through recipient-policy-aware runtime sends.
|
|
69
|
+
|
|
70
|
+
`ok: true` means responsibility was retained, not that the target handled the
|
|
71
|
+
intent. Once the target is ready it receives one no-ID `intent.deliver` with
|
|
72
|
+
`sender`, `archetype`, `action`, `convention`, and optional opaque `payload`.
|
|
73
|
+
Reuse, target windows, retries, replacement, persistence, and terminal reasons
|
|
74
|
+
remain private controller state and never appear in the result or delivery.
|
|
75
|
+
|
|
76
|
+
Paja currently exposes only an exact-contract development simulator, and the
|
|
77
|
+
playground currently exposes only a verified-manifest catalog builder. Phase
|
|
78
|
+
105 completed released `@napplet/*` package adoption plus the persistent live
|
|
79
|
+
catalog/controller and feed-to-profile flow. Its public `Intent*` types are
|
|
80
|
+
canonical releases from `@napplet/core` / `@napplet/nap`, not a local mirror;
|
|
81
|
+
successful acceptance retains host delivery responsibility before target start.
|
|
82
|
+
|
|
32
83
|
## Quick Start
|
|
33
84
|
|
|
34
85
|
```ts
|
|
35
86
|
import {
|
|
36
87
|
createIdentityService,
|
|
37
88
|
createListsService,
|
|
38
|
-
|
|
89
|
+
createNotifyService,
|
|
39
90
|
createBleService,
|
|
40
91
|
createDmService,
|
|
41
92
|
createNip17DmAdapter,
|
|
@@ -53,10 +104,10 @@ runtime.registerService(
|
|
|
53
104
|
}),
|
|
54
105
|
);
|
|
55
106
|
|
|
56
|
-
// Notification service —
|
|
107
|
+
// Notification service — direct NIP-5D notify.* envelopes.
|
|
57
108
|
runtime.registerService(
|
|
58
|
-
'
|
|
59
|
-
|
|
109
|
+
'notify',
|
|
110
|
+
createNotifyService({ onSend: (_windowId, message) => updateBadge(message) }),
|
|
60
111
|
);
|
|
61
112
|
|
|
62
113
|
// Lists service — shell-owned NIP-51 metadata and mutations.
|
|
@@ -460,13 +511,16 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
|
|
|
460
511
|
`createIdentityService` uses `getSigner()` for `identity.getPublicKey` and `identity.getRelays`. Hosts may also pass optional read-only provider hooks for `getProfile`, `getFollows`, `getList`, `getZaps`, `getMutes`, `getBlocked`, and `getBadges`. These hooks receive the current signer pubkey (or `""` when no signer is connected) and return the payload portion of the corresponding `.result` envelope. Kehto does not query relays itself; the hooks are for hosts that already maintain profile, contact-list, list, zap, moderation, or badge data.
|
|
461
512
|
|
|
462
513
|
### Notify NAP
|
|
463
|
-
- `createNotifyService` — canonical `notify.*` envelopes
|
|
464
|
-
- `createNotificationService` — legacy inc-emit `notifications:*` channel; coexists with `createNotifyService` until retired.
|
|
514
|
+
- `createNotifyService` — canonical direct `notify.*` envelopes.
|
|
465
515
|
|
|
466
516
|
### Relay NAP
|
|
467
|
-
- `createRelayPoolService` — `relay.publish`, `relay.publishEncrypted`,
|
|
517
|
+
- `createRelayPoolService` — `relay.publish`, `relay.publishEncrypted`,
|
|
518
|
+
`relay.subscribe` fan-out (`relay:read` / `relay:write`). Publish handlers
|
|
519
|
+
receive only runtime-signed events and settle with canonical
|
|
520
|
+
`{ ok, event, eventId }` or `{ ok: false, error }` result envelopes.
|
|
468
521
|
- `createCacheService` — offline event cache (`cache:read` / `cache:write`).
|
|
469
|
-
- `createCoordinatedRelay` — composite service that bundles relay-pool + cache
|
|
522
|
+
- `createCoordinatedRelay` — composite service that bundles relay-pool + cache
|
|
523
|
+
with read-through behavior and the same canonical publish result.
|
|
470
524
|
|
|
471
525
|
### Keys NAP
|
|
472
526
|
- `createKeysService` — `keys.registerAction` / `keys.unregisterAction` / `keys.forward` + `keys.bindings` / `keys.action` push envelopes (`keys:forward`). Document-level chord listener by default; implement the `HostKeysBridge` interface to swap in Electron / Tauri / OS-level backends. See [Keys Service](#keys-service) for the full contract.
|
|
@@ -487,13 +541,39 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
|
|
|
487
541
|
- `createCordnDmAdapter` / `createCordnRelayCoordinatorClient` — structural adapter for Cordn/ContextVM clients plus a relay-backed coordinator bridge for `PostGroupMessage`, `FetchGroupMessages`, and `SubscribeGroupMessages`.
|
|
488
542
|
|
|
489
543
|
### Theme NAP
|
|
490
|
-
- `createThemeService` — `theme.get`
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
544
|
+
- `createThemeService` — `theme.get` plus automatic `theme.changed` delivery
|
|
545
|
+
(`theme:read`). Returns a `ThemeService` with `publishTheme()` and
|
|
546
|
+
`getCurrentTheme()` for host-side updates.
|
|
547
|
+
|
|
548
|
+
### Intent NAP
|
|
549
|
+
- `createIntentService` — exact `intent.invoke`, `intent.available`, and
|
|
550
|
+
`intent.handlers` request/result handling plus recipient-gated
|
|
551
|
+
`intent.changed`.
|
|
552
|
+
- `manifestToIntentCatalogEntry` — verified manifest archetype contracts to
|
|
553
|
+
catalog entries.
|
|
554
|
+
- `createCatalogIntentResolver` — exact convention selection and retained
|
|
555
|
+
target-controller seam.
|
|
556
|
+
|
|
557
|
+
### Identity and theme wire guarantees
|
|
558
|
+
|
|
559
|
+
Against NAP-IDENTITY/NAP-THEME at `napplet/naps` master
|
|
560
|
+
`5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`,
|
|
561
|
+
`createIdentityService` is readonly: `identity.getPublicKey` always sends one
|
|
562
|
+
matching `.result` with `pubkey: ""` when a signer is absent or fails, and the
|
|
563
|
+
other supported reads retain their safe primary result fields. Unknown identity
|
|
564
|
+
actions are silent; identity changed values are host pushes, not request
|
|
565
|
+
retries or INC/intent traffic.
|
|
566
|
+
|
|
567
|
+
`createThemeService` accepts `theme.get` only and owns the current complete
|
|
568
|
+
three-color theme. `publishTheme()` normalizes and stores that state before it
|
|
569
|
+
invokes its one bridge callback, so an immediate `theme.get` observes the same
|
|
570
|
+
value as the automatic push. There is no theme subscribe/unsubscribe protocol.
|
|
571
|
+
For denied or unavailable runtime reads, Kehto uses the fixed non-sensitive
|
|
572
|
+
complete normal result without `error`: this explicit policy reconciles the
|
|
573
|
+
draft error-only example without a mixed theme/error extension.
|
|
494
574
|
|
|
495
575
|
### Types
|
|
496
|
-
`AudioSource`, `AudioServiceOptions`, `Notification`, `NotificationServiceOptions`, `IdentityServiceOptions`, `RelayPoolServiceOptions`, `CacheServiceOptions`, `CoordinatedRelayOptions`, `KeysServiceOptions`, `MediaServiceOptions`, `NotifyServiceOptions`, `ThemeServiceOptions`, `ThemeService`, `BleServiceOptions`, `BleServiceContext`, `WebrtcServiceOptions`, `WebrtcServiceContext`, `DmServiceOptions`, `DmAdapter`, `DmRelayPool`, `Nip17DmAdapterOptions`, `NdrDmAdapterOptions`, `CordnDmAdapterOptions`.
|
|
576
|
+
`AudioSource`, `AudioServiceOptions`, `Notification`, `NotificationServiceOptions`, `IdentityServiceOptions`, `RelayPoolServiceOptions`, `CacheServiceOptions`, `CoordinatedRelayOptions`, `KeysServiceOptions`, `MediaServiceOptions`, `NotifyServiceOptions`, `ThemeServiceOptions`, `ThemeService`, `IntentRequest`, `IntentResult`, `IntentDelivery`, `IntentContract`, `IntentCandidate`, `IntentAvailability`, `IntentResolver`, `IntentTargetController`, `BleServiceOptions`, `BleServiceContext`, `WebrtcServiceOptions`, `WebrtcServiceContext`, `DmServiceOptions`, `DmAdapter`, `DmRelayPool`, `Nip17DmAdapterOptions`, `NdrDmAdapterOptions`, `CordnDmAdapterOptions`.
|
|
497
577
|
|
|
498
578
|
## API Reference
|
|
499
579
|
|