@kehto/services 0.19.0 → 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/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { ServiceHandler, Signer, RelayEventResult, ServiceRuntimeContext } 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, IntentRequest, IntentResult, IntentAvailability, 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 { IntentAvailability, IntentBehavior, IntentCandidate, IntentHandlerPreference, IntentOpenOptions, IntentRequest, IntentResult } from '@napplet/core';
3
+ import { NostrFilter, NostrEvent, EventTemplate, IntentRequest, IntentResult, IntentAvailability, IntentBehavior, IntentCandidate, LinkOpenOptions, LinkOpenResult, ListSupport, ListRef, ListItem, ListOptions, ListMutationResult, SerialEvent, SerialOpenRequest, SerialOpenResult, BleEvent, BleOpenRequest, BleOpenResult, BleService, BleAttribute, BleWriteOptions, WebrtcEvent, WebrtcOpenRequest, WebrtcOpenResult, CommonProfileTarget, CommonProfileResult, CommonFollowsResult, CommonActionResult, CommonReaction, CommonReportTarget, CommonReportReason, DmStatus, DmConversationQuery, DmConversationPage, DmMessageQuery, DmMessagePage, DmSendRequest, DmSendResult, DmSubscribeRequest, DmMessage, DmSubscription, DmOk, DmHexPubkey, FsInfo, FsPickOptions, FsPickResult, FsMetadata, FsDirectoryEntry, FsReadOptions, FsReadResult, FsWriteOptions, FsWriteResult, FsMkdirOptions, FsWatchOptions, FsChange, FsError } from '@napplet/core';
4
+ export { DmConversation, DmConversationPage, DmConversationQuery, DmHexPubkey, DmMessage, DmMessagePage, DmMessageQuery, DmMessageStatus, DmOk, DmPeer, DmSendRequest, DmSendResult, DmStatus, DmSubscribeRequest, DmSubscription, DmTimestamp, IntentAvailability, IntentBehavior, IntentCandidate, IntentHandlerPreference, IntentOpenOptions, IntentRequest, IntentResult } from '@napplet/core';
5
5
  import { MediaMetadata, MediaAction } from '@napplet/nap/media/types';
6
6
  export { MediaAction } from '@napplet/nap/media/types';
7
- import { NotifySendMessage } from '@napplet/nap/notify/types';
7
+ import { NotifyActionMessage, NotifyClickedMessage, NotifyDismissedMessage, NotifySendMessage, NotifyChannelRegisterMessage, NotifyControl } from '@napplet/nap/notify/types';
8
8
  import { Theme, ThemeChangedMessage } from '@napplet/nap/theme/types';
9
- import { ConfigSchemaErrorCode, ConfigValues, NappletConfigSchema } from '@napplet/nap/config/types';
10
- export { a as CvmCloseMessage, b as CvmCloseResultMessage, c as CvmDiscoverMessage, d as CvmDiscoverQuery, e as CvmDiscoverResultMessage, f as CvmEventMessage, g as CvmInboundMessage, h as CvmOutboundMessage, i as CvmRequestMessage, j as CvmRequestOptions, k as CvmRequestResultMessage, l as CvmServer, m as CvmServerRef, n as CvmService, o as CvmServiceOptions, C as CvmTransport, p as CvmTransportError, M as McpContentBlock, q as McpMessage, r as McpTool, s as McpToolResult, t as createCvmService } from './cvm-service-DKIzbiDw.js';
9
+ import { ConfigSchemaErrorCode, NappletConfigSchema, ConfigValues } from '@napplet/nap/config/types';
10
+ export { a as CvmCloseMessage, b as CvmCloseResultMessage, c as CvmDiscoverMessage, d as CvmDiscoverQuery, e as CvmDiscoverResultMessage, f as CvmEventMessage, g as CvmInboundMessage, h as CvmOutboundMessage, i as CvmRequestMessage, j as CvmRequestOptions, k as CvmRequestResultMessage, l as CvmServer, m as CvmServerRef, n as CvmService, o as CvmServiceOptions, C as CvmTransport, p as CvmTransportError, M as McpContentBlock, q as McpMessage, r as McpTool, s as McpToolResult, t as createCvmService } from './cvm-service-t5syG4tU.js';
11
11
 
12
12
  /**
13
13
  * @kehto/services — Shared types for reference service implementations.
@@ -260,11 +260,11 @@ interface RelayPoolServiceOptions {
260
260
  * Subscribe to events matching filters. Returns handle with unsubscribe().
261
261
  *
262
262
  * @param filters - NIP-01 filter objects
263
- * @param callback - Receives matching events or 'EOSE'
263
+ * @param callback - Receives matching events or 'EOSE' plus optional observed relay URLs
264
264
  * @param relayUrls - Optional relay URL hints
265
265
  * @returns Handle to cancel the subscription
266
266
  */
267
- subscribe(filters: NostrFilter[], callback: (item: NostrEvent | 'EOSE') => void, relayUrls?: string[]): {
267
+ subscribe(filters: NostrFilter[], callback: (item: NostrEvent | 'EOSE', observedRelayUrls?: string[]) => void, relayUrls?: string[]): {
268
268
  unsubscribe(): void;
269
269
  };
270
270
  /**
@@ -1014,81 +1014,62 @@ declare function createMediaService(options?: MediaServiceOptions): ServiceHandl
1014
1014
  };
1015
1015
 
1016
1016
  /**
1017
- * notify-service.ts — NIP-5D notify NAP reference service (stub-level).
1018
- *
1019
- * Handles the 5 napplet -> shell request types from `@napplet/nap/notify`:
1020
- * - `notify.send` -> `notify.send.result` (shell-assigned id)
1021
- * - `notify.dismiss` -> fire-and-forget
1022
- * - `notify.badge` -> fire-and-forget
1023
- * - `notify.channel.register` -> fire-and-forget
1024
- * - `notify.permission.request` -> `notify.permission.result { granted }`
1025
- *
1026
- * Stub-level: no real Notification API calls, no real channel registry.
1027
- * Host apps wire a real backend via
1028
- * `runtime.registerService('notify', realHandler)`.
1017
+ * NAP-NOTIFY reference service.
1029
1018
  *
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.
1033
- * If the host app registers this service via
1034
- * `runtime.registerService('notify', ...)`, @napplet/nap/notify messages
1035
- * land here.
1036
- *
1037
- * Shell -> napplet push messages (`notify.action`, `notify.clicked`,
1038
- * `notify.dismissed`, `notify.controls`) are not emitted by this stub —
1039
- * they are the host app's responsibility and are deferred to a future plan.
1019
+ * The service owns protocol correlation and per-window lifecycle while a host
1020
+ * backend owns presentation, permission, badges, and channels.
1040
1021
  */
1041
1022
 
1042
- /**
1043
- * Optional configuration for `createNotifyService`.
1044
- *
1045
- * @example
1046
- * ```ts
1047
- * const notify = createNotifyService({
1048
- * generateId: () => crypto.randomUUID(),
1049
- * defaultGrant: false,
1050
- * onSend: (windowId, msg) => console.log(`napplet ${windowId} sent ${msg.title}`),
1051
- * });
1052
- * runtime.registerService('notify', notify);
1053
- * ```
1054
- */
1023
+ /** User-interaction events emitted by a host notification presentation. */
1024
+ type NotifyInteractionMessage = NotifyActionMessage | NotifyClickedMessage | NotifyDismissedMessage;
1025
+ /** Host presentation request for one accepted notification. */
1026
+ interface NotifyPresentation {
1027
+ /** Window that requested the notification. */
1028
+ readonly windowId: string;
1029
+ /** Shell-assigned notification identifier. */
1030
+ readonly notificationId: string;
1031
+ /** Original, untrusted notification payload. */
1032
+ readonly message: NotifySendMessage;
1033
+ /** Route a host-side user interaction back to the requesting napplet. */
1034
+ readonly emit: (message: NotifyInteractionMessage) => void;
1035
+ }
1036
+ /** Host hooks required to turn NAP-NOTIFY messages into observable behavior. */
1055
1037
  interface NotifyServiceOptions {
1056
- /**
1057
- * Generate a shell-assigned notification ID for `notify.send.result`.
1058
- * Default: a monotonically increasing `shell-<n>` counter.
1059
- */
1038
+ /** Generate a shell-assigned notification identifier. */
1060
1039
  generateId?: () => string;
1061
- /**
1062
- * Default permission grant for `notify.permission.request`.
1063
- * Host apps that want real permission prompts should replace this
1064
- * service with a real backend via `runtime.registerService`.
1065
- * Default: `true`.
1066
- */
1067
- defaultGrant?: boolean;
1068
- /**
1069
- * Called synchronously when a napplet dispatches `notify.send`.
1070
- * Intended for host-app plumbing (UI toast, logging, etc.) without
1071
- * requiring a full backend replacement.
1072
- */
1073
- onSend?: (windowId: string, payload: NotifySendMessage) => void;
1074
- }
1075
- /**
1076
- * Create a stub-level notify service handler.
1077
- *
1078
- * Answers the 5 napplet->shell request types from `@napplet/nap/notify`.
1079
- * Does NOT implement a real backend (no DOM Notification API, no channel
1080
- * registry, no permission prompt). Host apps replace this via
1081
- * `runtime.registerService('notify', realHandler)` when a real backend is
1082
- * needed.
1083
- *
1084
- * @param options - Optional service configuration (see NotifyServiceOptions)
1085
- * @returns A ServiceHandler to register with the runtime under domain `notify`
1040
+ /** Render or otherwise deliver a notification. Missing backends fail closed. */
1041
+ present?: (presentation: NotifyPresentation) => void | Promise<void>;
1042
+ /** Remove an active notification from host presentation. */
1043
+ dismiss?: (windowId: string, notificationId: string) => void | Promise<void>;
1044
+ /** Display or clear the requesting napplet's badge count. */
1045
+ setBadge?: (windowId: string, count: number) => void | Promise<void>;
1046
+ /** Persist a channel registration in host-owned state. */
1047
+ registerChannel?: (windowId: string, channel: NotifyChannelRegisterMessage) => void | Promise<void>;
1048
+ /** Apply policy or prompt the user for notification permission. */
1049
+ requestPermission?: (windowId: string, channel?: string) => boolean | Promise<boolean>;
1050
+ /** Release host-owned state when the runtime destroys a napplet window. */
1051
+ destroyWindow?: (windowId: string) => void | Promise<void>;
1052
+ /** Notification controls implemented by the host backend. */
1053
+ controls?: readonly NotifyControl[];
1054
+ /** Observe asynchronous fire-and-forget backend failures. */
1055
+ onError?: (error: unknown) => void;
1056
+ }
1057
+ /**
1058
+ * Create a NAP-NOTIFY service backed by host-owned notification behavior.
1059
+ *
1060
+ * A backendless instance is safe to register for conformance testing: send
1061
+ * requests return an error and permission requests return `granted: false`
1062
+ * instead of manufacturing successful delivery.
1063
+ *
1064
+ * @param options - Host presentation, policy, and lifecycle hooks.
1065
+ * @returns Runtime service handler for the `notify` domain.
1086
1066
  *
1087
1067
  * @example
1088
1068
  * ```ts
1089
- * import { createNotifyService } from '@kehto/services';
1090
- *
1091
- * const notify = createNotifyService();
1069
+ * const notify = createNotifyService({
1070
+ * present: ({ message }) => showToast(message.title, message.body),
1071
+ * requestPermission: () => promptUser(),
1072
+ * });
1092
1073
  * runtime.registerService('notify', notify);
1093
1074
  * ```
1094
1075
  */
@@ -1198,6 +1179,19 @@ interface ThemeService {
1198
1179
  */
1199
1180
  declare function createThemeService(options?: ThemeServiceOptions): ThemeService;
1200
1181
 
1182
+ /** Result of validating a NAP-CONFIG Core Subset schema. */
1183
+ type ConfigSchemaValidation = {
1184
+ ok: true;
1185
+ } | {
1186
+ ok: false;
1187
+ code: ConfigSchemaErrorCode;
1188
+ error: string;
1189
+ };
1190
+ /** Validate the complete bounded NAP-CONFIG Core Subset recursively. */
1191
+ declare function validateConfigSchema(schema: unknown): ConfigSchemaValidation;
1192
+ /** Apply schema defaults and drop values that do not validate. */
1193
+ declare function resolveConfigValues(schema: NappletConfigSchema, values: ConfigValues): ConfigValues;
1194
+
1201
1195
  /**
1202
1196
  * config-service.ts — NAP-CONFIG reference service (9th NAP domain, v1.7 Phase 39).
1203
1197
  *
@@ -1219,44 +1213,29 @@ declare function createThemeService(options?: ThemeServiceOptions): ThemeService
1219
1213
  * (H-07 in PITFALLS.md) — such state belongs in NAP-STORAGE.
1220
1214
  * ──────────────────────────────────────────────────────────────────────────────────
1221
1215
  *
1222
- * Host integration: provide `getValues()` returning the current
1223
- * `ConfigValues` snapshot. Call the returned `publishValues(newValues)`
1224
- * whenever the configuration changes — the service fans the new snapshot
1225
- * out to every napplet that has an active `config.subscribe`.
1216
+ * Host integration: provide `getValues(windowId)` and `saveValues(windowId,
1217
+ * values)` backed by storage scoped to the source window's napplet identity.
1218
+ * The service validates and defaults every snapshot before delivery.
1226
1219
  *
1227
- * Optional: provide `registerSchema` to accept napplet-declared schemas at
1228
- * runtime (the ref impl does a minimal shape check using the Core Subset
1229
- * validator; use `ajv` in host impls that need strict draft-07 conformance).
1230
- * Provide `openSettings` to open a shell-side UI for the napplet (no
1231
- * response envelope — fire-and-forget UI hook).
1220
+ * Provide `openSettings` to render the shell-owned settings UI. Optional
1221
+ * hooks may add host policy around schema acceptance and lifecycle cleanup.
1232
1222
  *
1233
1223
  * @example
1234
1224
  * ```ts
1235
1225
  * import { createConfigService } from '@kehto/services';
1236
1226
  *
1237
- * const configFixtures = { theme: 'dark', density: 'compact', recentSearches: [] };
1227
+ * const configFixtures = new Map<string, ConfigValues>();
1238
1228
  * const config = createConfigService({
1239
- * getValues: () => ({ ...configFixtures }),
1229
+ * getValues: (windowId) => ({ ...configFixtures.get(windowId) }),
1230
+ * saveValues: (windowId, values) => configFixtures.set(windowId, values),
1240
1231
  * });
1241
1232
  * runtime.registerService('config', config.handler);
1242
1233
  *
1243
1234
  * // Later, when shell-side values change:
1244
- * configFixtures.theme = 'light';
1245
- * config.publishValues({ ...configFixtures });
1235
+ * config.publishValues({ theme: 'light' }, 'window-1');
1246
1236
  * ```
1247
1237
  */
1248
1238
 
1249
- /**
1250
- * Shape returned by a successful `registerSchema` result (ok=true) or a
1251
- * rejection (ok=false + code + error). Mirrors the wire envelope fields.
1252
- */
1253
- type ConfigSchemaValidation = {
1254
- ok: true;
1255
- } | {
1256
- ok: false;
1257
- code: ConfigSchemaErrorCode;
1258
- error: string;
1259
- };
1260
1239
  /**
1261
1240
  * Configuration options for `createConfigService` (options-as-bridge
1262
1241
  * per v1.6 Decision 18).
@@ -1264,8 +1243,9 @@ type ConfigSchemaValidation = {
1264
1243
  * @example
1265
1244
  * ```ts
1266
1245
  * const config = createConfigService({
1267
- * getValues: () => ({ theme: 'dark', density: 'compact' }),
1268
- * openSettings: (windowId, section) => showSettingsPanel(windowId, section),
1246
+ * getValues: (windowId) => loadScopedValues(windowId),
1247
+ * saveValues: (windowId, values) => saveScopedValues(windowId, values),
1248
+ * openSettings: (windowId, section, context) => showSettingsPanel(windowId, section, context),
1269
1249
  * });
1270
1250
  * ```
1271
1251
  */
@@ -1275,7 +1255,9 @@ interface ConfigServiceOptions {
1275
1255
  * Called on every `config.get` and at every `config.subscribe` initial push.
1276
1256
  * Implementations should return a fresh object (not a mutable reference).
1277
1257
  */
1278
- getValues(): ConfigValues;
1258
+ getValues(windowId: string): ConfigValues;
1259
+ /** Persist one shell-validated full snapshot after settings UI commit. */
1260
+ saveValues?: (windowId: string, values: ConfigValues) => void;
1279
1261
  /**
1280
1262
  * Optional: receive notification when a napplet subscribes to config updates.
1281
1263
  * Fire-and-forget — the service tracks the subscription internally regardless.
@@ -1288,9 +1270,9 @@ interface ConfigServiceOptions {
1288
1270
  /**
1289
1271
  * Optional: validate and store a napplet-provided schema.
1290
1272
  *
1291
- * If omitted, the ref impl runs its own Core Subset check (hand-coded
1292
- * validator; 30-50 lines) and returns ok/reject. Hosts that need strict
1293
- * draft-07 conformance should provide an ajv-backed implementation.
1273
+ * The reference implementation always runs its complete bounded Core Subset
1274
+ * validator first. This hook may add host policy such as version acceptance
1275
+ * or durable schema persistence, but cannot weaken protocol validation.
1294
1276
  *
1295
1277
  * Return shape mirrors `config.registerSchema.result` wire envelope
1296
1278
  * (minus the `id` — the dispatch layer correlates).
@@ -1299,10 +1281,21 @@ interface ConfigServiceOptions {
1299
1281
  /**
1300
1282
  * Optional: open the shell-side settings UI for this napplet.
1301
1283
  * Fire-and-forget — no response envelope per the wire spec.
1302
- * If omitted, `config.openSettings` is silently dropped (D10 allows
1303
- * the config-demo napplet to function without a settings UI).
1284
+ * If omitted, `config.openSettings` is silently dropped. A conformant host
1285
+ * must supply this hook before advertising the CONFIG domain.
1304
1286
  */
1305
- openSettings?: (windowId: string, section: string | undefined) => void;
1287
+ openSettings?: (windowId: string, section: string | undefined, context: ConfigSettingsContext) => void;
1288
+ /** Release host-owned transient UI or state for a destroyed window. */
1289
+ onWindowDestroyed?: (windowId: string) => void;
1290
+ }
1291
+ /** Shell-owned settings state and commit boundary passed to host UI code. */
1292
+ interface ConfigSettingsContext {
1293
+ /** Accepted schema for this live napplet window. */
1294
+ readonly schema: NappletConfigSchema;
1295
+ /** Current validated/defaulted values. */
1296
+ readonly values: ConfigValues;
1297
+ /** Validate, persist, and publish a full settings snapshot. */
1298
+ commit(values: ConfigValues): ConfigValues;
1306
1299
  }
1307
1300
  /**
1308
1301
  * NAP-CONFIG reference service bundle — `handler` to register with the
@@ -1319,8 +1312,14 @@ interface ConfigService {
1319
1312
  * push from correlated `config.get` response).
1320
1313
  *
1321
1314
  * @param values - The new configuration snapshot (full object, not a diff)
1315
+ * @param windowId - Optional source window scope. Omit only for a host-wide
1316
+ * update that should be independently validated for every subscriber.
1322
1317
  */
1323
- publishValues(values: ConfigValues): void;
1318
+ publishValues(values: ConfigValues, windowId?: string): void;
1319
+ /** Return the accepted schema for one live window, or null. */
1320
+ getSchema(windowId: string): NappletConfigSchema | null;
1321
+ /** Return the current validated/defaulted values for one live window, or null. */
1322
+ getValues(windowId: string): ConfigValues | null;
1324
1323
  }
1325
1324
  /**
1326
1325
  * Create a NAP-CONFIG reference service.
@@ -1348,13 +1347,14 @@ interface ConfigService {
1348
1347
  * import { createConfigService } from '@kehto/services';
1349
1348
  *
1350
1349
  * const config = createConfigService({
1351
- * getValues: () => ({ theme: 'dark', density: 'compact' }),
1352
- * openSettings: (windowId, section) => openSettingsUI(section),
1350
+ * getValues: (windowId) => loadScopedValues(windowId),
1351
+ * saveValues: (windowId, values) => saveScopedValues(windowId, values),
1352
+ * openSettings: (windowId, section, context) => openSettingsUI(section, context),
1353
1353
  * });
1354
1354
  * runtime.registerService('config', config.handler);
1355
1355
  *
1356
- * // Push a live update to all subscribers:
1357
- * config.publishValues({ theme: 'light', density: 'compact' });
1356
+ * // Push one externally-originated scoped update:
1357
+ * config.publishValues({ theme: 'light', density: 'compact' }, 'window-1');
1358
1358
  * ```
1359
1359
  */
1360
1360
  declare function createConfigService(options: ConfigServiceOptions): ConfigService;
@@ -1364,8 +1364,7 @@ declare function createConfigService(options: ConfigServiceOptions): ConfigServi
1364
1364
  *
1365
1365
  * Shell-side reference implementation for the canonical NAP-RESOURCE wire
1366
1366
  * protocol (`internal-resource.ts` in @kehto/shell/src/types; kehto-internal
1367
- * model per PROJECT.md Decision #31. Kehto keeps legacy single-fetch fields
1368
- * for existing callers and also emits the current NAP-RESOURCE fields.
1367
+ * model per PROJECT.md Decision #31.
1369
1368
  * Handles:
1370
1369
  * Inbound: resource.info, resource.bytes, resource.bytesMany, resource.cancel
1371
1370
  * Outbound: resource.info.result, resource.info.error,
@@ -1373,22 +1372,18 @@ declare function createConfigService(options: ConfigServiceOptions): ConfigServi
1373
1372
  * resource.bytesMany.result, resource.bytesMany.error
1374
1373
  *
1375
1374
  * ──────────────────────── SCOPE BOUNDARY (RESOURCE-01) ────────────────────────
1376
- * NAP-RESOURCE is an **authenticated fetch proxy** — read-only, atomic.
1377
- *
1378
- * This service is NOT responsible for:
1379
- * - Streaming / chunked responses (host-app concern)
1380
- * - Response caching / conditional requests (host-app concern)
1381
- * - Upload / POST body construction (NAP-RESOURCE v1.7 is read-only)
1382
- * - Redirect limits, MIME sniffing, SVG rasterization (host-fetch concern)
1383
- * - Private-IP blocking, SSRF mitigation (host-provided-fetch responsibility)
1384
- *
1385
- * These belong to the host-app's `fetch` implementation per D7 and
1386
- * SHELL-RESOURCE-POLICY.md (Phase 40 Plan 40-03). Kehto ships a reference
1387
- * service; production hardening is the host app's concern.
1375
+ * NAP-RESOURCE is a runtime-mediated byte resolver — read-only, atomic.
1376
+ *
1377
+ * Kehto owns neutral wire lifecycle, cancellation, result projection, and
1378
+ * policy tooling. The runtime supplies the resolver and decides whether to use
1379
+ * the origin-grant hooks, which schemes to resolve, and which limits to expose.
1380
+ * Advisory `resource.info` scheme disclosure never authorizes or blocks a byte
1381
+ * request.
1388
1382
  * ──────────────────────────────────────────────────────────────────────────────
1389
1383
  *
1390
- * Host integration: provide `fetch`, `isOriginGranted`, `getConnectGrants`,
1391
- * and `resolveIdentity`. ALL FOUR are required from day one (H-03 prevention).
1384
+ * Runtime integration requires only `fetch`. A runtime MAY also install the
1385
+ * optional origin-policy adapter (`isOriginGranted`, `getConnectGrants`, and
1386
+ * `resolveIdentity` together).
1392
1387
  *
1393
1388
  * @example
1394
1389
  * ```ts
@@ -1396,11 +1391,18 @@ declare function createConfigService(options: ConfigServiceOptions): ConfigServi
1396
1391
  *
1397
1392
  * const resourceSvc = createResourceService({
1398
1393
  * fetch: (url, init) => globalThis.fetch(url, init),
1394
+ * });
1395
+ * runtime.registerService('resource', resourceSvc);
1396
+ * ```
1397
+ *
1398
+ * @example
1399
+ * ```ts
1400
+ * const resourceSvc = createResourceService({
1401
+ * fetch: (url, init) => runtimeResources.resolve(url, init),
1399
1402
  * isOriginGranted: (origin, grants) => grants.includes(origin),
1400
1403
  * getConnectGrants: (dTag, hash) => myOriginGrantStore.getOrigins(dTag, hash),
1401
1404
  * resolveIdentity: (windowId) => sessionRegistry.getEntryByWindowId(windowId) ?? null,
1402
1405
  * });
1403
- * runtime.registerService('resource', resourceSvc);
1404
1406
  * ```
1405
1407
  */
1406
1408
 
@@ -1428,24 +1430,22 @@ type ResourceInfoProvider = ResourceInfo | ((context: ResourceInfoContext) => Re
1428
1430
  /**
1429
1431
  * Options for `createResourceService` (options-as-bridge per v1.6 Decision 18).
1430
1432
  *
1431
- * ALL FOUR fields are required. The factory throws at construction if any is
1432
- * missing — H-03 prevention: the grants source (`getConnectGrants`) MUST be
1433
- * wired from day one so there is no window where resource requests bypass the
1434
- * grant check.
1435
- *
1436
- * @see PITFALLS.md:228 (H-03) — grants-source coupling must be present at construction
1433
+ * `fetch` is the only required field. Kehto does not select a runtime's scheme
1434
+ * or origin policy. The optional origin-policy fields form one adapter and must
1435
+ * therefore be supplied together when a runtime chooses to use it.
1437
1436
  */
1438
1437
  interface ResourceServiceOptions {
1439
1438
  /**
1440
- * Host-supplied fetch implementation. Receives the URL, a partial init
1441
- * (method, headers, signal), and must return a `Response`-compatible promise.
1439
+ * Runtime-supplied resource resolver. Receives the requested URL and returns
1440
+ * a byte-classified `Response`.
1442
1441
  *
1443
- * The host's `fetch` is the ONLY place to implement redirect limits, MIME
1444
- * sniffing, SVG rasterization, private-IP / SSRF blocking, etc.
1445
- * This service does NOT filter: it proxies transparently.
1442
+ * The runtime owns scheme dispatch and every NAP-RESOURCE policy decision.
1443
+ * The returned `content-type` must describe the runtime-classified bytes, not
1444
+ * an untrusted upstream header. Throw `ResourceServiceError` to preserve a
1445
+ * canonical protocol error classification.
1446
1446
  *
1447
1447
  * @param url - The URL from the resource.bytes request
1448
- * @param init - Method, headers (from napplet), and an AbortSignal
1448
+ * @param init - Read-only method and request-scoped AbortSignal
1449
1449
  */
1450
1450
  fetch(url: string, init: {
1451
1451
  method?: string;
@@ -1455,6 +1455,8 @@ interface ResourceServiceOptions {
1455
1455
  /**
1456
1456
  * Returns true if `origin` is present in `grants` (the list returned by
1457
1457
  * `getConnectGrants` for the napplet's dTag + aggregateHash).
1458
+ * Optional: when omitted with `getConnectGrants`, Kehto delegates directly
1459
+ * to the runtime resolver without an origin-grant decision.
1458
1460
  *
1459
1461
  * The reference implementation is simply `grants.includes(origin)`. Host apps
1460
1462
  * may provide normalized-origin comparison if needed.
@@ -1462,21 +1464,19 @@ interface ResourceServiceOptions {
1462
1464
  * @param origin - Parsed origin of the requested URL (scheme + host + port)
1463
1465
  * @param grants - Readonly list from getConnectGrants for this napplet identity
1464
1466
  */
1465
- isOriginGranted(origin: string, grants: readonly string[]): boolean;
1467
+ isOriginGranted?(origin: string, grants: readonly string[]): boolean;
1466
1468
  /**
1467
1469
  * Returns the list of allowed fetch origins for the given napplet identity.
1468
1470
  * Called on every `resource.bytes` request — must be synchronous and fast.
1471
+ * Optional and paired with `isOriginGranted` plus `resolveIdentity`.
1469
1472
  *
1470
1473
  * Host-supplied grant source (e.g. a static per-dTag allowlist map, or any
1471
1474
  * other host-controlled policy). Returns an empty array to deny all origins.
1472
1475
  *
1473
- * H-03 prevention: REQUIRED from day one — factory throws on construction
1474
- * if omitted.
1475
- *
1476
1476
  * @param dTag - The napplet's d-tag (from session registry)
1477
1477
  * @param aggregateHash - The napplet's aggregate hash (from session registry)
1478
1478
  */
1479
- getConnectGrants(dTag: string, aggregateHash: string): readonly string[];
1479
+ getConnectGrants?(dTag: string, aggregateHash: string): readonly string[];
1480
1480
  /**
1481
1481
  * Resolve a windowId to the napplet's identity (dTag + aggregateHash).
1482
1482
  * Returns null if the window is not in the session registry.
@@ -1485,7 +1485,7 @@ interface ResourceServiceOptions {
1485
1485
  *
1486
1486
  * @param windowId - The iframe window identifier
1487
1487
  */
1488
- resolveIdentity(windowId: string): {
1488
+ resolveIdentity?(windowId: string): {
1489
1489
  dTag: string;
1490
1490
  aggregateHash: string;
1491
1491
  } | null;
@@ -1493,8 +1493,8 @@ interface ResourceServiceOptions {
1493
1493
  * Advisory NAP-RESOURCE introspection exposed through `resource.info`.
1494
1494
  *
1495
1495
  * Provide a static snapshot or a resolver when the shell wants to disclose
1496
- * configured schemes and coarse limits. Omit to expose the reference
1497
- * service's conservative default (`https` enabled, no numeric limits).
1496
+ * configured schemes and coarse limits. Scheme disclosure is advisory and is
1497
+ * never used as fetch authorization. Omit to disclose no schemes or limits.
1498
1498
  */
1499
1499
  resourceInfo?: ResourceInfoProvider;
1500
1500
  }
@@ -1503,6 +1503,16 @@ interface ResourceServiceOptions {
1503
1503
  * Exported for host apps that need to type-annotate the handler reference.
1504
1504
  */
1505
1505
  type ResourceService = ServiceHandler;
1506
+ type ResourceErrorCode = 'invalid-request' | 'not-found' | 'blocked-by-policy' | 'timeout' | 'too-large' | 'unsupported-scheme' | 'decode-failed' | 'network-error' | 'quota-exceeded';
1507
+ /** A runtime resolver failure with a stable NAP-RESOURCE error classification. */
1508
+ declare class ResourceServiceError extends Error {
1509
+ readonly code: ResourceErrorCode;
1510
+ /**
1511
+ * @param code - Canonical NAP-RESOURCE error code.
1512
+ * @param message - Diagnostic detail safe to return to the napplet.
1513
+ */
1514
+ constructor(code: ResourceErrorCode, message: string);
1515
+ }
1506
1516
  /**
1507
1517
  * Create a NAP-RESOURCE reference service.
1508
1518
  *
@@ -1510,15 +1520,14 @@ type ResourceService = ServiceHandler;
1510
1520
  * `resource.bytes`, `resource.bytesMany`, `resource.cancel`, and their
1511
1521
  * result/error envelopes.
1512
1522
  *
1513
- * On-construction guard (H-03 prevention): all four options are validated at
1514
- * factory call time. If any is missing, the factory throws immediately with a
1515
- * message containing `[RESOURCE-01 / H-03]` so misconfigured shell apps fail
1516
- * loudly at startup rather than silently at first dispatch.
1523
+ * The runtime resolver is validated at construction. Runtime implementers may
1524
+ * additionally install the origin-grant adapter; Kehto provides and enforces
1525
+ * the hook contract without selecting the grants or requiring that policy.
1517
1526
  *
1518
1527
  * Returns a `ServiceHandler` (no `publishValues`-style surface — resource has
1519
1528
  * no shell-initiated push beyond the response/error path).
1520
1529
  *
1521
- * @param options - REQUIRED: fetch, isOriginGranted, getConnectGrants, resolveIdentity
1530
+ * @param options - Runtime resolver plus optional runtime-owned policy helpers
1522
1531
  * @returns ServiceHandler to register via `runtime.registerService('resource', handler)`
1523
1532
  *
1524
1533
  * @example
@@ -1526,7 +1535,7 @@ type ResourceService = ServiceHandler;
1526
1535
  * import { createResourceService } from '@kehto/services';
1527
1536
  *
1528
1537
  * const svc = createResourceService({
1529
- * fetch: (url, init) => globalThis.fetch(url, init),
1538
+ * fetch: (url, init) => runtimeResources.resolve(url, init),
1530
1539
  * isOriginGranted: (origin, grants) => grants.includes(origin),
1531
1540
  * getConnectGrants: (dTag, hash) => myOriginGrantStore.getOrigins(dTag, hash),
1532
1541
  * resolveIdentity: (windowId) => sessionRegistry.getEntryByWindowId(windowId) ?? null,
@@ -2445,6 +2454,8 @@ declare function createListsService(options?: ListsServiceOptions): ServiceHandl
2445
2454
  interface SerialServiceContext {
2446
2455
  /** Window id of the requesting napplet. */
2447
2456
  windowId: string;
2457
+ /** Emit a runtime-owned serial event back to the requesting napplet. */
2458
+ emit(event: SerialEvent): void;
2448
2459
  }
2449
2460
  /** Options for {@link createSerialService}. */
2450
2461
  interface SerialServiceOptions {
@@ -2575,94 +2586,14 @@ interface CommonServiceOptions {
2575
2586
  */
2576
2587
  declare function createCommonService(options?: CommonServiceOptions): ServiceHandler;
2577
2588
 
2578
- /** Hex Nostr public key. */
2579
- type DmHexPubkey = string;
2580
- /** Unix timestamp in seconds. */
2581
- type DmTimestamp = number;
2582
- /** Current runtime direct-message availability. */
2583
- interface DmStatus {
2584
- available: boolean;
2585
- ownerPubkey?: DmHexPubkey;
2586
- implementations: string[];
2587
- capabilities: string[];
2588
- }
2589
- /** Query parameters for normalized DM conversation summaries. */
2590
- interface DmConversationQuery {
2591
- cursor?: string;
2592
- limit?: number;
2593
- }
2594
- /** Public peer metadata safe for napplet display. */
2595
- interface DmPeer {
2596
- pubkey: DmHexPubkey;
2597
- label?: string;
2598
- avatar?: string;
2599
- }
2600
- /** A normalized direct or group conversation summary. */
2601
- interface DmConversation {
2602
- id: string;
2603
- kind: 'direct' | 'group';
2604
- participants: DmPeer[];
2605
- subject?: string;
2606
- unread: number;
2607
- updatedAt?: DmTimestamp;
2608
- }
2609
- /** Page of normalized conversation summaries. */
2610
- interface DmConversationPage {
2611
- conversations: DmConversation[];
2612
- cursor?: string;
2613
- }
2614
- /** Query parameters for message history within one conversation. */
2615
- interface DmMessageQuery {
2616
- conversationId: string;
2617
- cursor?: string;
2618
- limit?: number;
2619
- }
2620
- /** Runtime-normalized delivery state for a DM message. */
2621
- type DmMessageStatus = 'sent' | 'delivered' | 'received' | 'failed';
2622
- /** Normalized cleartext message visible to the napplet by runtime policy. */
2623
- interface DmMessage {
2624
- id: string;
2625
- conversationId: string;
2626
- senderPubkey: DmHexPubkey;
2627
- createdAt: DmTimestamp;
2628
- content: string;
2629
- status: DmMessageStatus;
2630
- }
2631
- /** Page of normalized messages for one conversation. */
2632
- interface DmMessagePage {
2633
- messages: DmMessage[];
2634
- cursor?: string;
2635
- }
2636
- /** Request to send a direct message. */
2637
- interface DmSendRequest {
2638
- conversationId?: string;
2639
- recipients: DmHexPubkey[];
2640
- content: string;
2641
- clientMessageId?: string;
2642
- }
2643
- /** Result of a runtime-mediated send. */
2644
- interface DmSendResult {
2645
- ok: boolean;
2646
- message: DmMessage;
2647
- }
2648
- /** Request to start live DM delivery. */
2649
- interface DmSubscribeRequest {
2650
- conversationId?: string;
2651
- }
2652
- /** Runtime-assigned live subscription identity. */
2653
- interface DmSubscription {
2654
- subscriptionId: string;
2655
- }
2656
- /** Generic boolean acknowledgement used by `dm.unsubscribe`. */
2657
- interface DmOk {
2658
- ok: boolean;
2659
- }
2660
2589
  /** Relay pool contract for DM adapters. */
2661
2590
  interface DmRelayPool {
2662
2591
  subscribe(filters: NostrFilter[], callback: (item: NostrEvent | 'EOSE') => void, relayUrls?: string[]): {
2663
2592
  unsubscribe(): void;
2664
2593
  };
2665
2594
  publish(event: NostrEvent): void | Promise<void>;
2595
+ /** Query persisted encrypted messages before serving normalized history. */
2596
+ query?(filters: NostrFilter[], relayUrls?: string[]): Promise<NostrEvent[]>;
2666
2597
  selectRelayTier(filters: NostrFilter[]): string[];
2667
2598
  isAvailable(): boolean;
2668
2599
  }
@@ -2730,6 +2661,8 @@ interface Nip17DmAdapterOptions {
2730
2661
  relays?: string[];
2731
2662
  /** Optional normalized message store. Defaults to an in-memory store. */
2732
2663
  store?: DmMemoryStore;
2664
+ /** Runtime policy invoked once before encrypted relay publication. */
2665
+ authorizeSend?(request: DmSendRequest): boolean | Promise<boolean>;
2733
2666
  }
2734
2667
  /**
2735
2668
  * Create a concrete NIP-17 NAP-DM adapter.
@@ -2860,4 +2793,60 @@ declare function createCordnRelayCoordinatorClient(options: CordnRelayCoordinato
2860
2793
  /** Create a Cordn/ContextVM-backed NAP-DM adapter. */
2861
2794
  declare function createCordnDmAdapter(options: CordnDmAdapterOptions): DmAdapter;
2862
2795
 
2863
- 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 IntentArchetypeSupport, type IntentCatalogEntry, type IntentDispatchParams, type IntentResolver, type IntentResolverContext, type IntentServiceOptions, type IntentTargetController, type IntentTargetDispatch, 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 };
2796
+ /**
2797
+ * NAP-FS service boundary for runtime-owned virtual filesystems.
2798
+ *
2799
+ * The service owns wire correlation and per-window watch identity. Backends own
2800
+ * virtual-path policy, authorization, persistence, picker mediation, and I/O.
2801
+ */
2802
+
2803
+ /** Change details emitted by a backend before the service adds its scoped watch id. */
2804
+ type FsBackendChange = Omit<FsChange, 'watchId'>;
2805
+ /** Active backend watch handle. */
2806
+ interface FsBackendWatch {
2807
+ /** Stop the backing watch. Must be idempotent. */
2808
+ close(): void | Promise<void>;
2809
+ }
2810
+ /** Filesystem operations supplied to the NAP-FS service. */
2811
+ interface FsBackend {
2812
+ info(windowId: string): FsInfo | Promise<FsInfo>;
2813
+ pickFile(windowId: string, options?: FsPickOptions): FsPickResult | Promise<FsPickResult>;
2814
+ pickFiles(windowId: string, options?: FsPickOptions): FsPickResult | Promise<FsPickResult>;
2815
+ pickDirectory(windowId: string, options?: FsPickOptions): FsPickResult | Promise<FsPickResult>;
2816
+ pickSaveFile(windowId: string, options?: FsPickOptions): FsPickResult | Promise<FsPickResult>;
2817
+ stat(windowId: string, path: string): FsMetadata | Promise<FsMetadata>;
2818
+ list(windowId: string, path: string): FsDirectoryEntry[] | Promise<FsDirectoryEntry[]>;
2819
+ read(windowId: string, path: string, options?: FsReadOptions): FsReadResult | Promise<FsReadResult>;
2820
+ write(windowId: string, path: string, data: string, options?: FsWriteOptions): FsWriteResult | Promise<FsWriteResult>;
2821
+ mkdir(windowId: string, path: string, options?: FsMkdirOptions): void | Promise<void>;
2822
+ remove(windowId: string, path: string, recursive?: boolean): void | Promise<void>;
2823
+ move(windowId: string, fromPath: string, toPath: string): void | Promise<void>;
2824
+ watch(windowId: string, path: string, options: FsWatchOptions | undefined, onChange: (change: FsBackendChange) => void): FsBackendWatch | Promise<FsBackendWatch>;
2825
+ /** Release session-scoped backend state for a destroyed runtime window. */
2826
+ onWindowDestroyed?(windowId: string): void;
2827
+ /** Release all backend resources. */
2828
+ close?(): void;
2829
+ }
2830
+ /** Error with a closed NAP-FS wire reason. */
2831
+ declare class FsServiceError extends Error {
2832
+ readonly code: FsError;
2833
+ constructor(code: FsError, message?: FsError);
2834
+ }
2835
+ /** Options for {@link createFsService}. */
2836
+ interface FsServiceOptions {
2837
+ backend: FsBackend;
2838
+ }
2839
+ /** Created NAP-FS service. */
2840
+ interface FsService extends ServiceHandler {
2841
+ /** Close watches and backend resources. */
2842
+ dispose(): void;
2843
+ }
2844
+ /**
2845
+ * Create a NAP-FS wire service over a runtime-owned backend.
2846
+ *
2847
+ * @param options - Filesystem backend.
2848
+ * @returns Service handler for `runtime.registerService('fs', handler)`.
2849
+ */
2850
+ declare function createFsService(options: FsServiceOptions): FsService;
2851
+
2852
+ export { type BleServiceContext, type BleServiceOptions, type CacheServiceOptions, type CatalogIntentResolver, type CatalogIntentResolverOptions, type CommonServiceContext, type CommonServiceOptions, type ConfigSchemaValidation, type ConfigService, type ConfigServiceOptions, type ConfigSettingsContext, type CoordinatedRelayOptions, type CordnCodecResult, type CordnCoordinatorClient, type CordnCoordinatorSubscription, type CordnDmAdapterOptions, type CordnDmClient, type CordnGroupMessage, type CordnRelayCoordinatorOptions, type CountRequest, type CountResult, type CountServiceOptions, type DmAdapter, DmMemoryStore, type DmRelayPool, type DmService, type DmServiceOptions, type FsBackend, type FsBackendChange, type FsBackendWatch, type FsService, FsServiceError, type FsServiceOptions, type HostCacheBridge, type HostKeyEvent, type HostKeysBridge, type HostMediaBridge, type HttpUploaderOptions, type HttpUploaderRails, type IdentityServiceOptions, type IntentArchetypeSupport, type IntentCatalogEntry, type IntentDispatchParams, type IntentResolver, type IntentResolverContext, type IntentServiceOptions, type IntentTargetController, type IntentTargetDispatch, 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 NotifyInteractionMessage, type NotifyPresentation, 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 ResourceErrorCode, type ResourceInfo, type ResourceInfoContext, type ResourceInfoProvider, type ResourceSchemeInfo, type ResourceService, ResourceServiceError, 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, createFsService, createHttpUploader, createIdentityService, createIntentService, createKeysService, createLinkService, createListsService, createMediaService, createNdrDmAdapter, createNdrRelayTransport, createNip17DmAdapter, createNotificationService, createNotifyService, createOutboxService, createRelayPoolOutboxRouter, createRelayPoolService, createResourceService, createSerialService, createThemeService, createUploadService, createWebrtcService, manifestToIntentCatalogEntry, resolveConfigValues, validateConfigSchema };