@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/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ServiceHandler, Signer, RelayEventResult } from '@kehto/runtime';
2
2
  import { IdentityGetProfileMessage, IdentityGetProfileResultMessage, IdentityGetFollowsMessage, IdentityGetFollowsResultMessage, IdentityGetListMessage, IdentityGetListResultMessage, IdentityGetZapsMessage, IdentityGetZapsResultMessage, IdentityGetMutesMessage, IdentityGetMutesResultMessage, IdentityGetBlockedMessage, IdentityGetBlockedResultMessage, IdentityGetBadgesMessage, IdentityGetBadgesResultMessage } from '@napplet/nap/identity/types';
3
- import { NostrFilter, NostrEvent, EventTemplate, LinkOpenOptions, LinkOpenResult, ListSupport, ListRef, ListItem, ListOptions, ListMutationResult, SerialOpenRequest, SerialOpenResult, BleEvent, BleOpenRequest, BleOpenResult, BleService, BleAttribute, BleWriteOptions, WebrtcEvent, WebrtcOpenRequest, WebrtcOpenResult, CommonProfileTarget, CommonProfileResult, CommonFollowsResult, CommonActionResult, CommonReaction, CommonReportTarget, CommonReportReason } from '@napplet/core';
3
+ import { NostrFilter, NostrEvent, EventTemplate, IntentRequest, IntentRejectedResult, IntentAcceptedResult, IntentAvailability, IntentContract, IntentDelivery, IntentBehavior, IntentCandidate, LinkOpenOptions, LinkOpenResult, ListSupport, ListRef, ListItem, ListOptions, ListMutationResult, SerialOpenRequest, SerialOpenResult, BleEvent, BleOpenRequest, BleOpenResult, BleService, BleAttribute, BleWriteOptions, WebrtcEvent, WebrtcOpenRequest, WebrtcOpenResult, CommonProfileTarget, CommonProfileResult, CommonFollowsResult, CommonActionResult, CommonReaction, CommonReportTarget, CommonReportReason } from '@napplet/core';
4
+ export { IntentAcceptedResult, IntentAvailability, IntentBehavior, IntentCandidate, IntentContract, IntentDelivery, IntentHandlerPreference, IntentInvokeOptions, IntentRejectedResult, IntentRequest, IntentResult } from '@napplet/core';
4
5
  import { MediaMetadata, MediaAction } from '@napplet/nap/media/types';
5
6
  export { MediaAction } from '@napplet/nap/media/types';
6
7
  import { NotifySendMessage } from '@napplet/nap/notify/types';
@@ -14,46 +15,6 @@ export { a as CvmCloseMessage, b as CvmCloseResultMessage, c as CvmDiscoverMessa
14
15
  * These types describe the internal state that services manage and expose
15
16
  * to the shell host via callbacks. They are NOT NIP-01 wire types.
16
17
  */
17
- /**
18
- * An active audio source registered by a napplet.
19
- *
20
- * @example
21
- * ```ts
22
- * const source: AudioSource = {
23
- * windowId: 'win-1',
24
- * nappletClass: 'music-player',
25
- * title: 'Now Playing',
26
- * muted: false,
27
- * };
28
- * ```
29
- */
30
- interface AudioSource {
31
- /** The napplet window that registered this audio source. */
32
- windowId: string;
33
- /** The napplet class/type (e.g., 'music-player'). */
34
- nappletClass: string;
35
- /** Human-readable title for the audio source. */
36
- title: string;
37
- /** Whether this source is currently muted. */
38
- muted: boolean;
39
- }
40
- /**
41
- * Options for creating an audio service via createAudioService().
42
- *
43
- * @example
44
- * ```ts
45
- * const audioService = createAudioService({
46
- * onChange: (sources) => console.log('Audio sources changed:', sources.size),
47
- * });
48
- * ```
49
- */
50
- interface AudioServiceOptions {
51
- /**
52
- * Called when the audio source registry changes (register, unregister,
53
- * mute, state update). The shell host uses this to update UI.
54
- */
55
- onChange?: (sources: ReadonlyMap<string, AudioSource>) => void;
56
- }
57
18
  /**
58
19
  * A notification created by a napplet.
59
20
  *
@@ -107,49 +68,13 @@ interface NotificationServiceOptions {
107
68
  maxPerWindow?: number;
108
69
  }
109
70
 
110
- /**
111
- * audio-service.ts — Audio source registry as a ServiceHandler.
112
- *
113
- * Tracks which napplet windows are producing audio. Shell hosts wire this
114
- * into the runtime via registerService('audio', createAudioService(opts)).
115
- * Browser-agnostic — no DOM, no window, no postMessage.
116
- */
117
-
118
- /**
119
- * Create an audio service handler.
120
- *
121
- * The audio service is a state registry that tracks active audio sources
122
- * per napplet window. Napplets announce audio state via `audio:*` topic
123
- * events; the service tracks sources and can relay mute commands back.
124
- *
125
- * @param options - Optional configuration (onChange callback for UI updates)
126
- * @returns A ServiceHandler to register with the runtime
127
- *
128
- * @example
129
- * ```ts
130
- * import { createAudioService } from '@kehto/services';
131
- *
132
- * const audio = createAudioService({
133
- * onChange: (sources) => {
134
- * // Update UI with current audio sources
135
- * for (const [windowId, source] of sources) {
136
- * console.log(`${source.title} (${source.muted ? 'muted' : 'playing'})`);
137
- * }
138
- * },
139
- * });
140
- *
141
- * runtime.registerService('audio', audio);
142
- * ```
143
- */
144
- declare function createAudioService(options?: AudioServiceOptions): ServiceHandler;
145
-
146
71
  /**
147
72
  * Create a notification service handler.
148
73
  *
149
74
  * The notification service is a state registry that tracks notifications
150
- * per napplet window. Napplets create and manage notifications via
151
- * `notifications:*` topic events; the shell host controls presentation
152
- * via the onChange callback.
75
+ * per napplet window. It accepts direct `notify.*` service envelopes; INC
76
+ * topics are opaque application data and never select a host service. The
77
+ * shell host controls presentation through the onChange callback.
153
78
  *
154
79
  * @param options - Optional configuration (onChange callback, maxPerWindow limit)
155
80
  * @returns A ServiceHandler to register with the runtime
@@ -166,7 +91,7 @@ declare function createAudioService(options?: AudioServiceOptions): ServiceHandl
166
91
  * maxPerWindow: 50,
167
92
  * });
168
93
  *
169
- * runtime.registerService('notifications', notifications);
94
+ * runtime.registerService('notify', notifications);
170
95
  * ```
171
96
  */
172
97
  declare function createNotificationService(options?: NotificationServiceOptions): ServiceHandler;
@@ -346,8 +271,9 @@ interface RelayPoolServiceOptions {
346
271
  * Publish an event to relays.
347
272
  *
348
273
  * @param event - The event to publish
274
+ * @returns Nothing, or a promise that settles when the publish request completes
349
275
  */
350
- publish(event: NostrEvent): void;
276
+ publish(event: NostrEvent): void | Promise<void>;
351
277
  /**
352
278
  * Select relay URLs appropriate for the given filters.
353
279
  *
@@ -892,11 +818,8 @@ declare function createBrowserMediaBridge(opts?: {
892
818
  * via bridge.setMetadata / bridge.setPlaybackState. When the active session is
893
819
  * destroyed, the next-most-recently-touched session is promoted automatically.
894
820
  *
895
- * Note: this is SEPARATE from packages/services/src/audio-service.ts, which
896
- * is the legacy inc-topic-based audio source registry (audio:* topic events
897
- * over inc.emit). media-service is the canonical @napplet/nap/media NIP-5D
898
- * path and they coexist — audio-service continues to track audio sources for
899
- * shell UI, while media-service handles the NAP protocol envelope surface.
821
+ * This is the canonical @napplet/nap/media NIP-5D path. It handles media
822
+ * protocol envelopes directly and does not depend on convention-topic routing.
900
823
  *
901
824
  * Shell -> Napplet push types (media.command) are emitted here when
902
825
  * bridge.onAction callbacks fire — this is the canonical Phase 27 real backend.
@@ -1104,14 +1027,12 @@ declare function createMediaService(options?: MediaServiceOptions): ServiceHandl
1104
1027
  * Host apps wire a real backend via
1105
1028
  * `runtime.registerService('notify', realHandler)`.
1106
1029
  *
1107
- * Coexistence note: this is SEPARATE from
1108
- * `packages/services/src/notification-service.ts`, which is the legacy
1109
- * inc-topic-based notification registry (operates on `inc.emit` topics
1110
- * under `notifications:*`). `notify-service.ts` is the canonical
1111
- * `@napplet/nap/notify` NIP-5D path and lives alongside the legacy module.
1030
+ * `notify-service.ts` is the canonical `@napplet/nap/notify` NIP-5D path.
1031
+ * It lives alongside the direct notification state registry in
1032
+ * `notification-service.ts`; neither service interprets an `inc.emit` topic.
1112
1033
  * If the host app registers this service via
1113
1034
  * `runtime.registerService('notify', ...)`, @napplet/nap/notify messages
1114
- * land here; the legacy inc-emit topic path remains untouched.
1035
+ * land here.
1115
1036
  *
1116
1037
  * Shell -> napplet push messages (`notify.action`, `notify.clicked`,
1117
1038
  * `notify.dismissed`, `notify.controls`) are not emitted by this stub —
@@ -2147,109 +2068,17 @@ interface HttpUploaderOptions {
2147
2068
  */
2148
2069
  declare function createHttpUploader(options: HttpUploaderOptions): Uploader;
2149
2070
 
2150
- /**
2151
- * intent-types.ts — NAP-INTENT (archetype intent dispatch) value types.
2152
- *
2153
- * Kehto-internal model for the NAP-INTENT wire contract (upstream draft:
2154
- * napplet/naps NAP-INTENT, namespace `window.napplet.intent`). The installed
2155
- * `@napplet/core` peer predates these types, so — as with {@link ./cvm-types} —
2156
- * kehto defines them here, wire-compatible with the upstream shapes, rather
2157
- * than redefining the generic NIP-5D envelope.
2158
- *
2159
- * NAP-INTENT standardizes the *envelope*, not the payload. `archetype` is the
2160
- * routing axis (which role, whose default), `protocol` is the parsing axis
2161
- * (which NAP-N wire format shapes `payload`); the two are orthogonal.
2162
- *
2163
- * @packageDocumentation
2164
- */
2165
- /**
2166
- * How the shell should pick the handling napplet for an intent.
2167
- *
2168
- * - `"default"` — route to the user's default handler for the archetype.
2169
- * - `"choose"` — prompt the user with an "open with…" chooser.
2170
- * - any other string — a specific napplet dTag (cross-napplet targeting; the
2171
- * shell SHOULD require the user to have authorized this for the caller).
2172
- */
2173
- type IntentHandlerPreference = 'default' | 'choose' | (string & {});
2174
- /** Window-behavior hints carried with an intent invoke. */
2175
- interface IntentBehavior {
2176
- /** Bring the handler window to the foreground. */
2177
- focus?: boolean;
2178
- /** Force a new window rather than reusing an existing handler instance. */
2179
- newWindow?: boolean;
2180
- /** Prefer reusing an already-open handler instance when one exists. */
2181
- reuse?: boolean;
2182
- }
2183
- /** A request to dispatch an action to a napplet of a given archetype. */
2184
- interface IntentRequest {
2185
- /** Role slug, e.g. `"note"` (see the archetype registry). */
2186
- archetype: string;
2187
- /** Verb, default `"open"` (e.g. `"open"` | `"edit"` | `"pick"` | `"share"`). */
2188
- action?: string;
2189
- /** NAP-N id shaping `payload`; omit to use the archetype's recommended default. */
2190
- protocol?: string;
2191
- /** Opaque payload, typed by `protocol`. */
2192
- payload?: unknown;
2193
- /** Handler-selection preference. */
2194
- handler?: IntentHandlerPreference;
2195
- /** Window-behavior hints. */
2196
- behavior?: IntentBehavior;
2197
- }
2198
- /** A napplet that can fulfill an archetype, sourced from the manifest catalog. */
2199
- interface IntentCandidate {
2200
- /** dTag of the napplet that can fulfill the archetype. */
2201
- dTag: string;
2202
- /** Human-readable title from the manifest. */
2203
- title?: string;
2204
- /** Verbs this candidate supports for the archetype. */
2205
- actions: string[];
2206
- /** NAP-N ids this candidate accepts for the archetype. */
2207
- protocols: string[];
2208
- /** Whether this candidate is the user/runtime default for the archetype. */
2209
- isDefault?: boolean;
2210
- }
2211
- /** Availability of an archetype, sourced from the installed-napplet catalog. */
2212
- interface IntentAvailability {
2213
- /** The archetype this availability describes. */
2214
- archetype: string;
2215
- /** True when at least one installed napplet fulfills the archetype. */
2216
- available: boolean;
2217
- /** Candidate napplets that fulfill the archetype (from manifests, not instances). */
2218
- candidates: IntentCandidate[];
2219
- /** True when a user/runtime default handler is set for the archetype. */
2220
- hasDefault: boolean;
2221
- }
2222
- /** The result of an intent invocation. */
2223
- interface IntentResult {
2224
- /** Whether the intent was dispatched successfully. */
2225
- ok: boolean;
2226
- /** The requested archetype, echoed back. */
2227
- archetype: string;
2228
- /** The resolved action (defaults to `"open"` when the request omits it). */
2229
- action: string;
2230
- /** True when a handler accepted the dispatch. */
2231
- handled: boolean;
2232
- /** dTag of the napplet that handled the intent, when one did. */
2233
- handler?: string;
2234
- /** Window id the handler was created or focused in. */
2235
- windowId?: string;
2236
- /** The wire format actually used to deliver `payload`. */
2237
- protocol?: string;
2238
- /** Error reason when the intent could not be fulfilled. */
2239
- error?: string;
2240
- }
2241
-
2242
2071
  /**
2243
2072
  * intent-service.ts — NAP-INTENT (archetype intent dispatch) reference service.
2244
2073
  *
2245
2074
  * Shell-side handler for the NAP-INTENT wire protocol. It is a pure envelope
2246
2075
  * router: it validates `intent.*` envelopes, delegates archetype resolution,
2247
- * default handling, window lifecycle, and payload delivery to an injected
2248
- * {@link IntentResolver}, and posts the correlated result / push messages
2249
- * (echoing the request `id`) back to the napplet.
2076
+ * default handling and retained target delivery to an injected
2077
+ * {@link IntentResolver}, then posts correlated result and push messages back
2078
+ * to the napplet.
2250
2079
  *
2251
2080
  * The resolver is injected (options-as-bridge) so this service has no shell or
2252
- * window-manager dependency and is fully unit-testable. A concrete
2081
+ * target-lifecycle dependency and is fully unit-testable. A concrete
2253
2082
  * catalog-backed resolver ships alongside as {@link createCatalogIntentResolver}.
2254
2083
  *
2255
2084
  * ──────────────────────────── Responsibilities ────────────────────────────
@@ -2258,15 +2087,15 @@ interface IntentResult {
2258
2087
  * intent.handlers.result, intent.changed
2259
2088
  *
2260
2089
  * The shell owns archetype→handler resolution, the user's default-handler
2261
- * preference, the "open with…" chooser, and window creation/focus — all behind
2262
- * the {@link IntentResolver}. This service only marshals the wire protocol and
2263
- * fans `intent.changed` pushes out to the napplets it has served.
2090
+ * preference, chooser, and retained target policy behind the
2091
+ * {@link IntentResolver}. This service only marshals the wire protocol and
2092
+ * fans `intent.changed` pushes out to eligible napplets.
2264
2093
  *
2265
2094
  * @example
2266
2095
  * ```ts
2267
2096
  * import { createIntentService, createCatalogIntentResolver } from '@kehto/services';
2268
2097
  *
2269
- * const resolver = createCatalogIntentResolver({ loadCatalog, windows });
2098
+ * const resolver = createCatalogIntentResolver({ loadCatalog, targets });
2270
2099
  * runtime.registerService('intent', createIntentService({ resolver }));
2271
2100
  * ```
2272
2101
  *
@@ -2275,22 +2104,53 @@ interface IntentResult {
2275
2104
 
2276
2105
  /** Context passed to {@link IntentResolver.invoke} for trust/attribution. */
2277
2106
  interface IntentResolverContext {
2278
- /** Window id of the napplet that issued the request. */
2279
- windowId: string;
2107
+ /** Runtime-attested dTag of the napplet that issued the request. */
2108
+ sender: string;
2109
+ }
2110
+ /**
2111
+ * Opaque runtime-owned delivery responsibility retained before acceptance.
2112
+ *
2113
+ * Starting the task may wait for target readiness and apply host retry,
2114
+ * replacement, or terminal-failure policy. It never produces a second source
2115
+ * result.
2116
+ */
2117
+ interface IntentRetainedDelivery {
2118
+ /**
2119
+ * Begin target lifecycle and eventual delivery policy.
2120
+ *
2121
+ * @returns Nothing, or a promise settled when controller policy completes.
2122
+ */
2123
+ start(): void | Promise<void>;
2124
+ }
2125
+ /** A resolver rejection before delivery responsibility was retained. */
2126
+ interface IntentRejectedResolverOutcome {
2127
+ /** Exact canonical pre-acceptance rejection. */
2128
+ result: IntentRejectedResult;
2129
+ }
2130
+ /** A resolver acceptance backed by already-retained delivery responsibility. */
2131
+ interface IntentAcceptedResolverOutcome {
2132
+ /** Exact canonical acceptance result. */
2133
+ result: IntentAcceptedResult;
2134
+ /** Opaque task that the service starts only after sending the source result. */
2135
+ retained: IntentRetainedDelivery;
2280
2136
  }
2137
+ /** Pre-acceptance rejection or accepted retained-delivery responsibility. */
2138
+ type IntentResolverOutcome = IntentRejectedResolverOutcome | IntentAcceptedResolverOutcome;
2281
2139
  /**
2282
2140
  * Abstract intent resolver. Implementors own the installed-napplet catalog,
2283
2141
  * archetype→handler resolution, the user's default-handler preference, the
2284
- * "open with…" chooser, window creation/focus, and payload delivery. The
2142
+ * chooser and retained target delivery policy. The
2285
2143
  * service translates wire envelopes into these calls and back.
2286
2144
  */
2287
2145
  interface IntentResolver {
2288
2146
  /**
2289
- * Resolve `request.archetype` to a handler, create or focus its window, and
2290
- * deliver `payload`. Returns once the handler is resolved and the window
2291
- * created; delivery MAY complete asynchronously.
2147
+ * Resolve the request and retain target delivery responsibility.
2148
+ *
2149
+ * @param request - Validated normalized intent request.
2150
+ * @param context - Runtime-attested source identity.
2151
+ * @returns A structured rejection, or an acceptance plus an unstarted task.
2292
2152
  */
2293
- invoke(request: IntentRequest, context: IntentResolverContext): IntentResult | Promise<IntentResult>;
2153
+ invoke(request: IntentRequest, context: IntentResolverContext): IntentResolverOutcome | Promise<IntentResolverOutcome>;
2294
2154
  /** Report whether the runtime can currently satisfy `archetype`, and how. */
2295
2155
  available(archetype: string): IntentAvailability | Promise<IntentAvailability>;
2296
2156
  /** Report availability for every archetype the runtime can currently satisfy. */
@@ -2320,35 +2180,32 @@ declare function createIntentService(options: IntentServiceOptions): ServiceHand
2320
2180
  /**
2321
2181
  * catalog-intent-resolver.ts — NAP-INTENT concrete {@link IntentResolver}.
2322
2182
  *
2323
- * A reference resolver that satisfies {@link IntentResolver} from an
2324
- * installed-napplet catalog plus host-supplied policy: the user's
2325
- * default-handler preference, an optional "open with…" chooser, the archetype's
2326
- * recommended default protocol, and a window controller that creates or focuses
2327
- * the handler window and delivers the payload.
2328
- *
2329
- * Resolution policy (mirrors an OS implicit-intent + default-app model):
2330
- * 1. Gather candidates for the archetype from the catalog.
2331
- * 2. Pick the handler — an explicit `handler` dTag, a user choice
2332
- * (`handler: "choose"`), the user's default, the sole candidate, or a
2333
- * deterministic first-candidate fallback.
2334
- * 3. Validate the resolved handler supports the requested `action` and
2335
- * `protocol` (or fall back to the archetype's recommended default protocol,
2336
- * then the candidate's first accepted protocol).
2337
- * 4. Open or focus the handler window and return its id.
2338
- *
2339
- * The catalog, defaults, chooser, and window controller are all injected, so
2340
- * this resolver carries no shell, manifest, or DOM dependency and is fully
2341
- * unit-testable.
2183
+ * A reference resolver backed by installed, verified NIP-5A manifest contracts
2184
+ * plus host-supplied user policy. Contract compatibility is exact complete
2185
+ * convention equality. Catalog order, payload contents, quick action indexes,
2186
+ * and event-kind metadata never select a handler.
2187
+ *
2188
+ * Selection policy:
2189
+ * 1. Filter installed candidates by exact manifest contract.
2190
+ * 2. Require positive host authorization for an explicit handler dTag.
2191
+ * 3. Otherwise use an explicit chooser, a compatible user default, the sole
2192
+ * compatible candidate, or an injected chooser.
2193
+ * 4. Reject ambiguity when no chooser policy exists.
2194
+ *
2195
+ * The catalog, defaults, chooser, authorization hook, and target controller are
2196
+ * injected, so this resolver has no shell, manifest, or DOM dependency.
2342
2197
  *
2343
2198
  * @packageDocumentation
2344
2199
  */
2345
2200
 
2346
- /** The actions/protocols a napplet fulfills for a single archetype. */
2201
+ /** The exact manifest-derived conventions a napplet fulfills for one archetype. */
2347
2202
  interface IntentArchetypeSupport {
2348
- /** Verbs this napplet supports for the archetype (e.g. `["open", "edit"]`). */
2203
+ /** Verbs derived from this napplet's accepted conventions. */
2349
2204
  actions: string[];
2350
- /** NAP-N protocol ids this napplet accepts for the archetype. */
2351
- protocols: string[];
2205
+ /** Stable queryless convention identities derived from {@link contracts}. */
2206
+ conventions: string[];
2207
+ /** Authoritative ordered contracts parsed from the installed manifest. */
2208
+ contracts: IntentContract[];
2352
2209
  }
2353
2210
  /**
2354
2211
  * One installed napplet's intent surface, derived from its signed NIP-5A
@@ -2360,57 +2217,60 @@ interface IntentCatalogEntry {
2360
2217
  dTag: string;
2361
2218
  /** Human-readable title from the manifest. */
2362
2219
  title?: string;
2363
- /** Archetype slug → the actions/protocols this napplet fulfills for it. */
2220
+ /** Archetype slug to exact manifest-derived support. */
2364
2221
  archetypes: Record<string, IntentArchetypeSupport>;
2365
2222
  }
2366
- /** Parameters handed to {@link IntentWindowController.open}. */
2367
- interface IntentOpenParams {
2368
- /** dTag of the resolved handler napplet. */
2369
- dTag: string;
2370
- /** The archetype being dispatched. */
2371
- archetype: string;
2372
- /** The resolved action (e.g. `"open"`). */
2373
- action: string;
2374
- /** The wire format the payload is delivered with, when one was resolved. */
2375
- protocol?: string;
2376
- /** The opaque payload to deliver. */
2377
- payload?: unknown;
2378
- /** Window-behavior hints from the request. */
2379
- behavior?: IntentBehavior;
2380
- /** Window id of the napplet that issued the intent. */
2381
- callerWindowId: string;
2382
- }
2383
- /** Creates or focuses the handler window and delivers the intent payload. */
2384
- interface IntentWindowController {
2385
- /**
2386
- * Create or focus the handler window and deliver `payload` via `protocol`.
2387
- * Returns the window id the handler was created or focused in.
2388
- */
2389
- open(params: IntentOpenParams): {
2390
- windowId: string;
2391
- } | Promise<{
2392
- windowId: string;
2393
- }>;
2223
+ /** Exact carrier-neutral values retained for one selected intent target. */
2224
+ interface IntentRetentionParams {
2225
+ /** Selected target napplet dTag. */
2226
+ readonly handler: string;
2227
+ /** Immutable canonical delivery retained independently of the source. */
2228
+ readonly delivery: Readonly<IntentDelivery>;
2229
+ /** Copied non-authoritative target lifecycle hints. */
2230
+ readonly behavior?: Readonly<IntentBehavior>;
2231
+ }
2232
+ /** Host controller that retains source-independent target delivery policy. */
2233
+ interface IntentTargetController {
2234
+ /**
2235
+ * Retain delivery responsibility without starting target policy.
2236
+ *
2237
+ * @param params - Immutable selected target and canonical delivery values.
2238
+ * @returns An opaque unstarted delivery task.
2239
+ */
2240
+ retain(params: IntentRetentionParams): IntentRetainedDelivery | Promise<IntentRetainedDelivery>;
2394
2241
  }
2395
2242
  /** Options for {@link createCatalogIntentResolver}. */
2396
2243
  interface CatalogIntentResolverOptions {
2397
- /** Return the installed-napplet catalog (signed NIP-5A manifests). Required. */
2244
+ /** Return the installed-napplet catalog sourced from signed manifests. */
2398
2245
  loadCatalog(): IntentCatalogEntry[] | Promise<IntentCatalogEntry[]>;
2399
- /** Window controller used to create/focus the resolved handler's window. Required. */
2400
- windows: IntentWindowController;
2246
+ /** Target controller that retains responsibility before resolver acceptance. */
2247
+ targets: IntentTargetController;
2401
2248
  /**
2402
- * The user's default handler dTag for an archetype, or `undefined` when none
2403
- * is set. Default-handler settings are user state — never set by napplets.
2249
+ * Return the user's default handler dTag for an archetype.
2250
+ *
2251
+ * @param archetype - Normalized archetype slug.
2252
+ * @returns The user-selected default dTag, or `undefined`.
2404
2253
  */
2405
2254
  getDefaultHandler?(archetype: string): string | undefined;
2406
2255
  /**
2407
- * Resolve a `handler: "choose"` prompt (or a no-default ambiguity) to a dTag.
2408
- * Returning `undefined` means the user cancelled. When omitted, ambiguous
2409
- * resolution falls back to the first candidate.
2256
+ * Ask user policy to select one exact-compatible candidate.
2257
+ *
2258
+ * @param archetype - Normalized archetype slug.
2259
+ * @param candidates - Only candidates with an exact matching contract.
2260
+ * @param sender - Runtime-attested source napplet dTag.
2261
+ * @returns A candidate dTag, or `undefined` when the user cancels.
2410
2262
  */
2411
- chooseHandler?(archetype: string, candidates: IntentCandidate[], callerWindowId: string): string | undefined | Promise<string | undefined>;
2412
- /** The archetype's recommended default protocol when the caller omits one. */
2413
- defaultProtocol?(archetype: string): string | undefined;
2263
+ chooseHandler?(archetype: string, candidates: IntentCandidate[], sender: string): string | undefined | Promise<string | undefined>;
2264
+ /**
2265
+ * Authorize a caller's explicit handler dTag preference.
2266
+ *
2267
+ * @param sender - Runtime-attested source napplet dTag.
2268
+ * @param handler - Explicit requested handler dTag.
2269
+ * @param request - Normalized intent request.
2270
+ * @param candidate - Installed exact-compatible candidate.
2271
+ * @returns `true` only when explicit targeting is user-authorized.
2272
+ */
2273
+ authorizeExplicitHandler?(sender: string, handler: string, request: IntentRequest, candidate: IntentCandidate): boolean | Promise<boolean>;
2414
2274
  }
2415
2275
  /**
2416
2276
  * A {@link IntentResolver} backed by a catalog, with a host hook to announce
@@ -2418,26 +2278,27 @@ interface CatalogIntentResolverOptions {
2418
2278
  */
2419
2279
  interface CatalogIntentResolver extends IntentResolver {
2420
2280
  /**
2421
- * Announce that the catalog or default handler for `archetype` changed. The
2422
- * resolver recomputes availability and notifies `onChanged` listeners, which
2423
- * the intent service forwards to napplets as `intent.changed` pushes.
2281
+ * Announce that the catalog or default handler for `archetype` changed.
2282
+ *
2283
+ * @param archetype - Changed archetype slug.
2284
+ * @returns Nothing.
2424
2285
  */
2425
2286
  notifyChanged(archetype: string): void;
2426
2287
  }
2427
2288
  /**
2428
2289
  * Create a catalog-backed NAP-INTENT resolver.
2429
2290
  *
2430
- * @param options - Catalog loader and window controller (required) plus
2431
- * optional default-handler, chooser, and default-protocol policy hooks.
2432
- * @returns A {@link CatalogIntentResolver} for `createIntentService({ resolver })`.
2433
- * @throws If `options.loadCatalog` or `options.windows` is missing.
2291
+ * @param options - Catalog loader and target controller plus optional user
2292
+ * default, chooser, and explicit-handler authorization hooks.
2293
+ * @returns A catalog-backed resolver.
2294
+ * @throws If required catalog or target-controller options are missing.
2434
2295
  *
2435
2296
  * @example
2436
2297
  * ```ts
2437
2298
  * const resolver = createCatalogIntentResolver({
2438
2299
  * loadCatalog: () => installedNapplets,
2439
- * windows: { open: ({ dTag }) => ({ windowId: openWindow(dTag) }) },
2440
- * getDefaultHandler: (a) => userDefaults[a],
2300
+ * targets: { retain: (params) => retainTargetDelivery(params) },
2301
+ * getDefaultHandler: (archetype) => userDefaults[archetype],
2441
2302
  * });
2442
2303
  * ```
2443
2304
  */
@@ -2471,22 +2332,22 @@ interface ManifestArchetypeInput {
2471
2332
  /** Optional human-readable title from the manifest. */
2472
2333
  title?: string;
2473
2334
  /**
2474
- * Archetype slugs this napplet fulfills, from the manifest's `archetype` tags;
2475
- * the optional `nap` is the recommended default wire protocol.
2335
+ * Ordered convention contracts from the manifest's `archetype` tags.
2476
2336
  */
2477
2337
  archetypes: Array<{
2478
2338
  slug: string;
2479
- nap?: string;
2339
+ convention: string;
2340
+ eventKinds?: number[];
2480
2341
  }>;
2481
2342
  }
2482
2343
  /**
2483
2344
  * Map a resolved napplet manifest's archetype data into an
2484
2345
  * {@link IntentCatalogEntry}.
2485
2346
  *
2486
- * Each archetype `{ slug, nap }` becomes a keyed support record where `actions`
2487
- * defaults to `['open']` (the NAP-INTENT default action — manifests do not
2488
- * enumerate actions in this phase) and `protocols` is `[nap]` when a NAP-N is
2489
- * present, else `[]`. Duplicate slugs keep the last occurrence.
2347
+ * Each manifest tag remains one ordered contract. Repeated slugs group into one
2348
+ * support record while repeated conventions remain distinct contracts; action
2349
+ * and convention arrays are stable, deduplicated indexes derived from those
2350
+ * contracts.
2490
2351
  *
2491
2352
  * @param manifest - A resolved manifest's structural archetype data.
2492
2353
  * @returns The `IntentCatalogEntry` for `createCatalogIntentResolver`.
@@ -2496,10 +2357,14 @@ interface ManifestArchetypeInput {
2496
2357
  * manifestToIntentCatalogEntry({
2497
2358
  * dTag: 'profile-viewer',
2498
2359
  * title: 'Profile',
2499
- * archetypes: [{ slug: 'profile', nap: 'NAP-1' }],
2360
+ * archetypes: [{ slug: 'profile', convention: 'napplet:profile/open' }],
2500
2361
  * });
2501
2362
  * // → { dTag: 'profile-viewer', title: 'Profile',
2502
- * // archetypes: { profile: { actions: ['open'], protocols: ['NAP-1'] } } }
2363
+ * // archetypes: { profile: {
2364
+ * // actions: ['open'],
2365
+ * // conventions: ['napplet:profile/open'],
2366
+ * // contracts: [{ convention: 'napplet:profile/open' }],
2367
+ * // } } }
2503
2368
  * ```
2504
2369
  */
2505
2370
  declare function manifestToIntentCatalogEntry(manifest: ManifestArchetypeInput): IntentCatalogEntry;
@@ -3009,4 +2874,4 @@ declare function createCordnRelayCoordinatorClient(options: CordnRelayCoordinato
3009
2874
  /** Create a Cordn/ContextVM-backed NAP-DM adapter. */
3010
2875
  declare function createCordnDmAdapter(options: CordnDmAdapterOptions): DmAdapter;
3011
2876
 
3012
- export { type AudioServiceOptions, type AudioSource, type BleServiceContext, type BleServiceOptions, type CacheServiceOptions, type CatalogIntentResolver, type CatalogIntentResolverOptions, type CommonServiceContext, type CommonServiceOptions, type ConfigSchemaValidation, type ConfigService, type ConfigServiceOptions, type CoordinatedRelayOptions, type CordnCodecResult, type CordnCoordinatorClient, type CordnCoordinatorSubscription, type CordnDmAdapterOptions, type CordnDmClient, type CordnGroupMessage, type CordnRelayCoordinatorOptions, type CountRequest, type CountResult, type CountServiceOptions, type DmAdapter, type DmConversation, type DmConversationPage, type DmConversationQuery, type DmHexPubkey, DmMemoryStore, type DmMessage, type DmMessagePage, type DmMessageQuery, type DmMessageStatus, type DmOk, type DmPeer, type DmRelayPool, type DmSendRequest, type DmSendResult, type DmService, type DmServiceOptions, type DmStatus, type DmSubscribeRequest, type DmSubscription, type DmTimestamp, type HostCacheBridge, type HostKeyEvent, type HostKeysBridge, type HostMediaBridge, type HttpUploaderOptions, type HttpUploaderRails, type IdentityServiceOptions, type IntentArchetypeSupport, type IntentAvailability, type IntentBehavior, type IntentCandidate, type IntentCatalogEntry, type IntentHandlerPreference, type IntentOpenParams, type IntentRequest, type IntentResolver, type IntentResolverContext, type IntentResult, type IntentServiceOptions, type IntentWindowController, type KeysServiceOptions, type LinkOpenContext, type LinkServiceOptions, type ListsServiceContext, type ListsServiceOptions, type ManifestArchetypeInput, type MaybePromise, type MediaMetadataLike, type MediaPlaybackOwner, type MediaServiceOptions, type MediaSessionCreateOptions, type MediaSessionTarget, type MediaSourceRef, type NdrDmAdapterOptions, type NdrRelayTransport, type NdrRelayTransportOptions, type NdrRumorLike, type NdrRuntimeLike, type Nip17DmAdapterOptions, type NostrTag, type Notification, type NotificationServiceOptions, type NotifyServiceOptions, type OutboxEventOptions, type OutboxEventResult, type OutboxPublishOptions, type OutboxPublishResult, type OutboxQueryOptions, type OutboxQueryStream, type OutboxQueryStreamSink, type OutboxRelayPlan, type OutboxRelayPool, type OutboxResult, type OutboxRouter, type OutboxRouterSubscription, type OutboxServiceOptions, type OutboxSubscribeOptions, type OutboxSubscriptionSink, type OutboxTarget, type RailServerConfig, type RelayListEntry, type RelayPoolOutboxRouterOptions, type RelayPoolServiceOptions, type ResourceInfo, type ResourceInfoContext, type ResourceInfoProvider, type ResourceSchemeInfo, type ResourceService, type ResourceServiceOptions, type SerialServiceContext, type SerialServiceOptions, type SignEvent, type StreamingOutboxRouter, type ThemeService, type ThemeServiceOptions, type UploadDimensions, type UploadInfo, type UploadInfoContext, type UploadInfoProvider, type UploadRail, type UploadRailInfo, type UploadRequest, type UploadResult, type UploadServiceOptions, type UploadState, type UploadStatus, type Uploader, type UploaderContext, type WebrtcServiceContext, type WebrtcServiceOptions, createAudioService, createBleService, createBrowserMediaBridge, createCacheService, createCatalogIntentResolver, createCommonService, createConfigService, createCoordinatedRelay, createCordnDmAdapter, createCordnRelayCoordinatorClient, createCountService, createDmService, createHttpUploader, createIdentityService, createIntentService, createKeysService, createLinkService, createListsService, createMediaService, createNdrDmAdapter, createNdrRelayTransport, createNip17DmAdapter, createNotificationService, createNotifyService, createOutboxService, createRelayPoolOutboxRouter, createRelayPoolService, createResourceService, createSerialService, createThemeService, createUploadService, createWebrtcService, manifestToIntentCatalogEntry };
2877
+ export { type BleServiceContext, type BleServiceOptions, type CacheServiceOptions, type CatalogIntentResolver, type CatalogIntentResolverOptions, type CommonServiceContext, type CommonServiceOptions, type ConfigSchemaValidation, type ConfigService, type ConfigServiceOptions, type CoordinatedRelayOptions, type CordnCodecResult, type CordnCoordinatorClient, type CordnCoordinatorSubscription, type CordnDmAdapterOptions, type CordnDmClient, type CordnGroupMessage, type CordnRelayCoordinatorOptions, type CountRequest, type CountResult, type CountServiceOptions, type DmAdapter, type DmConversation, type DmConversationPage, type DmConversationQuery, type DmHexPubkey, DmMemoryStore, type DmMessage, type DmMessagePage, type DmMessageQuery, type DmMessageStatus, type DmOk, type DmPeer, type DmRelayPool, type DmSendRequest, type DmSendResult, type DmService, type DmServiceOptions, type DmStatus, type DmSubscribeRequest, type DmSubscription, type DmTimestamp, type HostCacheBridge, type HostKeyEvent, type HostKeysBridge, type HostMediaBridge, type HttpUploaderOptions, type HttpUploaderRails, type IdentityServiceOptions, type IntentAcceptedResolverOutcome, type IntentArchetypeSupport, type IntentCatalogEntry, type IntentRejectedResolverOutcome, type IntentResolver, type IntentResolverContext, type IntentResolverOutcome, type IntentRetainedDelivery, type IntentRetentionParams, type IntentServiceOptions, type IntentTargetController, type KeysServiceOptions, type LinkOpenContext, type LinkServiceOptions, type ListsServiceContext, type ListsServiceOptions, type ManifestArchetypeInput, type MaybePromise, type MediaMetadataLike, type MediaPlaybackOwner, type MediaServiceOptions, type MediaSessionCreateOptions, type MediaSessionTarget, type MediaSourceRef, type NdrDmAdapterOptions, type NdrRelayTransport, type NdrRelayTransportOptions, type NdrRumorLike, type NdrRuntimeLike, type Nip17DmAdapterOptions, type NostrTag, type Notification, type NotificationServiceOptions, type NotifyServiceOptions, type OutboxEventOptions, type OutboxEventResult, type OutboxPublishOptions, type OutboxPublishResult, type OutboxQueryOptions, type OutboxQueryStream, type OutboxQueryStreamSink, type OutboxRelayPlan, type OutboxRelayPool, type OutboxResult, type OutboxRouter, type OutboxRouterSubscription, type OutboxServiceOptions, type OutboxSubscribeOptions, type OutboxSubscriptionSink, type OutboxTarget, type RailServerConfig, type RelayListEntry, type RelayPoolOutboxRouterOptions, type RelayPoolServiceOptions, type ResourceInfo, type ResourceInfoContext, type ResourceInfoProvider, type ResourceSchemeInfo, type ResourceService, type ResourceServiceOptions, type SerialServiceContext, type SerialServiceOptions, type SignEvent, type StreamingOutboxRouter, type ThemeService, type ThemeServiceOptions, type UploadDimensions, type UploadInfo, type UploadInfoContext, type UploadInfoProvider, type UploadRail, type UploadRailInfo, type UploadRequest, type UploadResult, type UploadServiceOptions, type UploadState, type UploadStatus, type Uploader, type UploaderContext, type WebrtcServiceContext, type WebrtcServiceOptions, createBleService, createBrowserMediaBridge, createCacheService, createCatalogIntentResolver, createCommonService, createConfigService, createCoordinatedRelay, createCordnDmAdapter, createCordnRelayCoordinatorClient, createCountService, createDmService, createHttpUploader, createIdentityService, createIntentService, createKeysService, createLinkService, createListsService, createMediaService, createNdrDmAdapter, createNdrRelayTransport, createNip17DmAdapter, createNotificationService, createNotifyService, createOutboxService, createRelayPoolOutboxRouter, createRelayPoolService, createResourceService, createSerialService, createThemeService, createUploadService, createWebrtcService, manifestToIntentCatalogEntry };