@kehto/services 0.16.5 → 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 CHANGED
@@ -1,6 +1,8 @@
1
1
  # @kehto/services
2
2
 
3
- Reference service handlers for the napplet protocol — audio, notifications, identity, relay pool, cache, keys, media, notify, theme, link, common, lists, serial, BLE, WebRTC, DM.
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,78 @@ 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.31.0 <0.32.0`. The exact installed contracts are core/nap 0.31.0 from
21
+ source `7b675622e13870628ce174833d7b2a33cf32a0ab` and release
22
+ `03ad65b66413e5798536ef48695ffc4c2508f2c3`.
23
+
15
24
  ## Overview
16
25
 
17
- `@kehto/services` ships the reference implementations of the `ServiceHandler` contract defined by `@kehto/runtime`. Each factory returns an object that the runtime routes NIP-5D envelopes to based on the domain prefix of the incoming message type (e.g., `identity.*` goes to the handler registered under `identity`).
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` (NIP-5D `notify.*` NAP) coexists with the legacy `createNotificationService` (inc-emit `notifications:*` channel). Both may be registered simultaneously while hosts migrate.
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` supports `resource.bytesMany` from draft NAP-RESOURCE. Bulk requests return ordered per-URL items and keep per-URL failures local while preserving legacy single-fetch fields for existing Kehto callers.
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` supports `resource.info` and `resource.bytesMany` from draft NAP-RESOURCE. `resource.info` returns advisory schemes and coarse limits; bulk requests return ordered per-URL items and keep per-URL failures local while preserving legacy single-fetch fields for existing Kehto callers.
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
+ Kehto follows merged [NAP-INTENT at
53
+ `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`](https://github.com/napplet/naps/blob/5ac0490461ca6fec2f0d2e45b4835cf9bc08de24/naps/NAP-INTENT.md).
54
+ Callers invoke a stable, queryless `napplet:<archetype>/<action>` convention.
55
+ Installed verified manifest tags produce exact `{ slug, convention }`
56
+ declarations; numbered protocol names, trailing metadata, and payload inspection
57
+ do not select a handler.
58
+
59
+ - `manifestToIntentCatalogEntry()` converts resolved manifest
60
+ `{ dTag, title?, archetypes: [{ slug, convention }] }` data into exact
61
+ candidates with `actions` and `conventions`.
62
+ - `createCatalogIntentResolver()` filters by exact convention, applies the
63
+ user-owned default/chooser/explicit-authorization policy, and asks an
64
+ `IntentTargetController` to create/focus a target and dispatch the selected
65
+ convention.
66
+ - `createIntentService()` validates source envelopes, uses the runtime-attested
67
+ sender, returns one final canonical `IntentResult`, and broadcasts catalog
68
+ changes through recipient-policy-aware runtime sends.
69
+
70
+ `ok: true` means the selected target was ready and the convention was dispatched.
71
+ The result includes `handled`, `handler`, `windowId`, and `convention`. The
72
+ target receives the convention and opaque payload through one runtime-attested
73
+ `inc.event`; there is no separate `intent.deliver` lifecycle.
74
+
75
+ Paja currently exposes only an exact-contract development simulator, and the
76
+ playground currently exposes only a verified-manifest catalog builder. Phase
77
+ 105 completed released `@napplet/*` package adoption plus the persistent live
78
+ catalog/controller and feed-to-profile flow. Its public `Intent*` types are
79
+ canonical releases from `@napplet/core` / `@napplet/nap`, not a local mirror;
80
+ successful results report completed target dispatch.
81
+
32
82
  ## Quick Start
33
83
 
34
84
  ```ts
35
85
  import {
36
86
  createIdentityService,
37
87
  createListsService,
38
- createNotificationService,
88
+ createNotifyService,
39
89
  createBleService,
40
90
  createDmService,
41
91
  createNip17DmAdapter,
@@ -53,10 +103,10 @@ runtime.registerService(
53
103
  }),
54
104
  );
55
105
 
56
- // Notification service — legacy inc-emit channel, browser badge fan-out.
106
+ // Notification service — direct NIP-5D notify.* envelopes.
57
107
  runtime.registerService(
58
- 'notifications',
59
- createNotificationService({ onChange: (list) => updateBadge(list) }),
108
+ 'notify',
109
+ createNotifyService({ onSend: (_windowId, message) => updateBadge(message) }),
60
110
  );
61
111
 
62
112
  // Lists service — shell-owned NIP-51 metadata and mutations.
@@ -460,13 +510,16 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
460
510
  `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
511
 
462
512
  ### Notify NAP
463
- - `createNotifyService` — canonical `notify.*` envelopes (`notify:send` / `notify:channel`).
464
- - `createNotificationService` — legacy inc-emit `notifications:*` channel; coexists with `createNotifyService` until retired.
513
+ - `createNotifyService` — canonical direct `notify.*` envelopes.
465
514
 
466
515
  ### Relay NAP
467
- - `createRelayPoolService` — `relay.publish`, `relay.publishEncrypted`, `relay.subscribe` fan-out (`relay:read` / `relay:write`).
516
+ - `createRelayPoolService` — `relay.publish`, `relay.publishEncrypted`,
517
+ `relay.subscribe` fan-out (`relay:read` / `relay:write`). Publish handlers
518
+ receive only runtime-signed events and settle with canonical
519
+ `{ ok, event, eventId }` or `{ ok: false, error }` result envelopes.
468
520
  - `createCacheService` — offline event cache (`cache:read` / `cache:write`).
469
- - `createCoordinatedRelay` — composite service that bundles relay-pool + cache with read-through behavior.
521
+ - `createCoordinatedRelay` — composite service that bundles relay-pool + cache
522
+ with read-through behavior and the same canonical publish result.
470
523
 
471
524
  ### Keys NAP
472
525
  - `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 +540,39 @@ Each factory returns a `ServiceHandler` registrable via `runtime.registerService
487
540
  - `createCordnDmAdapter` / `createCordnRelayCoordinatorClient` — structural adapter for Cordn/ContextVM clients plus a relay-backed coordinator bridge for `PostGroupMessage`, `FetchGroupMessages`, and `SubscribeGroupMessages`.
488
541
 
489
542
  ### Theme NAP
490
- - `createThemeService` — `theme.get` + `theme.changed` fan-out (`theme:read`). Returns a `ThemeService` with `publishTheme()` / `setTheme()` utilities for host-side updates.
491
-
492
- ### Audio (legacy inc-emit)
493
- - `createAudioService` — `audio:*` inc-emit topic handler. Browser-agnostic registry of per-window audio sources; host wires `onChange` to update transport UI.
543
+ - `createThemeService` — `theme.get` plus automatic `theme.changed` delivery
544
+ (`theme:read`). Returns a `ThemeService` with `publishTheme()` and
545
+ `getCurrentTheme()` for host-side updates.
546
+
547
+ ### Intent NAP
548
+ - `createIntentService` — exact `intent.invoke`, `intent.available`, and
549
+ `intent.handlers` request/result handling plus recipient-gated
550
+ `intent.changed`.
551
+ - `manifestToIntentCatalogEntry` — verified manifest archetype contracts to
552
+ catalog entries.
553
+ - `createCatalogIntentResolver` — exact convention selection and retained
554
+ target-controller seam.
555
+
556
+ ### Identity and theme wire guarantees
557
+
558
+ Against NAP-IDENTITY/NAP-THEME at `napplet/naps` master
559
+ `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`,
560
+ `createIdentityService` is readonly: `identity.getPublicKey` always sends one
561
+ matching `.result` with `pubkey: ""` when a signer is absent or fails, and the
562
+ other supported reads retain their safe primary result fields. Unknown identity
563
+ actions are silent; identity changed values are host pushes, not request
564
+ retries or INC/intent traffic.
565
+
566
+ `createThemeService` accepts `theme.get` only and owns the current complete
567
+ three-color theme. `publishTheme()` normalizes and stores that state before it
568
+ invokes its one bridge callback, so an immediate `theme.get` observes the same
569
+ value as the automatic push. There is no theme subscribe/unsubscribe protocol.
570
+ For denied or unavailable runtime reads, Kehto uses the fixed non-sensitive
571
+ complete normal result without `error`: this explicit policy reconciles the
572
+ draft error-only example without a mixed theme/error extension.
494
573
 
495
574
  ### 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`.
575
+ `AudioSource`, `AudioServiceOptions`, `Notification`, `NotificationServiceOptions`, `IdentityServiceOptions`, `RelayPoolServiceOptions`, `CacheServiceOptions`, `CoordinatedRelayOptions`, `KeysServiceOptions`, `MediaServiceOptions`, `NotifyServiceOptions`, `ThemeServiceOptions`, `ThemeService`, `IntentOpenOptions`, `IntentRequest`, `IntentResult`, `IntentCandidate`, `IntentAvailability`, `IntentResolver`, `IntentTargetController`, `IntentDispatchParams`, `IntentTargetDispatch`, `BleServiceOptions`, `BleServiceContext`, `WebrtcServiceOptions`, `WebrtcServiceContext`, `DmServiceOptions`, `DmAdapter`, `DmRelayPool`, `Nip17DmAdapterOptions`, `NdrDmAdapterOptions`, `CordnDmAdapterOptions`.
497
576
 
498
577
  ## API Reference
499
578