@kehto/paja 0.17.1 → 0.19.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,9 +1,10 @@
1
- import { P as PajaRawOptions, b as PajaHostConfig } from './server-Ia5n1Bqv.js';
2
- export { D as DEFAULT_PAJA_AGGREGATE_HASH, c as DEFAULT_PAJA_DTAG, d as DEFAULT_PAJA_HOST, e as DEFAULT_PAJA_PORT, f as DEFAULT_PAJA_RUNTIME_WAIT_MS, g as DEFAULT_PAJA_WINDOW_ID, h as DEFAULT_READY_TIMEOUT_MS, J as JsonPrimitive, i as JsonRecord, j as JsonValue, k as PAJA_SIMULATION_DOMAINS, l as PajaCapabilityDomain, a as PajaCommand, m as PajaHmrStrategy, n as PajaOptions, o as PajaOptionsError, p as PajaPointerRuntimeConfig, q as PajaServer, r as PajaServerOptions, t as PajaSimulation, u as PajaSimulationError, v as PajaSimulationRawOptions, x as PajaTargetMode, R as ReadinessError, y as ReadinessFetch, W as WaitForTargetUrlOptions, z as createPajaHostConfig, A as createPajaRuntimeHostConfig, B as formatPajaUrl, C as normalizePajaOptions, E as normalizePajaSimulation, s as startPajaServer, F as summarizePajaSimulation, w as waitForTargetUrl } from './server-Ia5n1Bqv.js';
1
+ import { P as PajaRawOptions, b as PajaHostConfig } from './server-5j5uoy2Z.js';
2
+ export { D as DEFAULT_PAJA_AGGREGATE_HASH, c as DEFAULT_PAJA_DTAG, d as DEFAULT_PAJA_HOST, e as DEFAULT_PAJA_PORT, f as DEFAULT_PAJA_RUNTIME_WAIT_MS, g as DEFAULT_PAJA_WINDOW_ID, h as DEFAULT_READY_TIMEOUT_MS, J as JsonPrimitive, i as JsonRecord, j as JsonValue, k as PAJA_SIMULATION_DOMAINS, l as PajaCapabilityDomain, a as PajaCommand, m as PajaHmrStrategy, n as PajaOptions, o as PajaOptionsError, p as PajaPointerRuntimeConfig, q as PajaServer, r as PajaServerOptions, t as PajaSimulation, u as PajaSimulationError, v as PajaSimulationRawOptions, x as PajaTargetMode, R as ReadinessError, y as ReadinessFetch, W as WaitForTargetUrlOptions, z as createPajaHostConfig, A as createPajaRuntimeHostConfig, B as formatPajaUrl, C as normalizePajaOptions, E as normalizePajaSimulation, s as startPajaServer, F as summarizePajaSimulation, w as waitForTargetUrl } from './server-5j5uoy2Z.js';
3
3
  import { NostrEvent } from 'nostr-tools';
4
4
  import { Filter } from 'nostr-tools/filter';
5
5
  import { ResolvedNapplet } from '@kehto/nip/5d';
6
6
  import { ShellCapabilities } from '@kehto/shell';
7
+ export { NappletCspDirective, NappletCspDirectives, NappletCspOptions } from '@kehto/shell';
7
8
  import { IntentCatalogEntry, IntentTargetController, IntentDispatchParams, IntentTargetDispatch } from '@kehto/services';
8
9
 
9
10
  /**
@@ -69,7 +70,7 @@ interface PajaResolvedPointer {
69
70
  readonly blossomServers: readonly string[];
70
71
  /** Resolved manifest `d` tag. */
71
72
  readonly dTag: string;
72
- /** Verified NIP-5A aggregate hash. */
73
+ /** Verified content identity: current artifact hash or legacy NIP-5A aggregate. */
73
74
  readonly aggregateHash: string;
74
75
  /** Verified target `/index.html` content. */
75
76
  readonly indexHtml: string;
@@ -127,8 +128,7 @@ declare function decodePajaPointer(value: string): PajaDecodedPointer;
127
128
  declare function resolvePajaPointer(value: string, options?: ResolvePajaPointerOptions): Promise<PajaResolvedPointer>;
128
129
  /**
129
130
  * Inject Kehto's Class-1 CSP for verified runtime-pointer srcdoc output.
130
- * NIP-5D mandates the verified srcdoc and opaque sandbox, but this baseline CSP
131
- * is Kehto policy rather than a protocol requirement.
131
+ * Delegates to the shell policy, which enforces NIP-5D CSP recommendations.
132
132
  *
133
133
  * @param html - Verified target HTML.
134
134
  * @param origins - Origins the resolved target may connect to.
@@ -164,6 +164,127 @@ declare function getMissingAdvertisedDomains(capabilities: ShellCapabilities): s
164
164
  */
165
165
  declare function getMissingServices(services: readonly string[]): string[];
166
166
 
167
+ /**
168
+ * A napplet opened from a local `index.html` file in Paja runtime-pointer mode.
169
+ *
170
+ * Spec-gap decision: NIP-5D's Identity section resolves a signed manifest,
171
+ * fetches the artifact from Blossom, and verifies its hash before it creates
172
+ * the iframe. A local file has no manifest or signature, so it never takes that
173
+ * path. Paja treats local files as an unsigned development target. Identity is
174
+ * still computed from the file's own bytes (never taken from the host), the
175
+ * file loads through the same sandboxed `srcdoc` + CSP + `window.napplet`
176
+ * prelude path as verified pointers, and it never enters the installed
177
+ * napplet catalog. See `docs/policies/NIP-5D-CONFORMANCE.md`.
178
+ */
179
+ interface PajaLocalTarget {
180
+ /** Discriminant separating local files from relay/Blossom-resolved pointers. */
181
+ readonly source: 'local';
182
+ /** File name as reported by the browser file picker or drop event. */
183
+ readonly fileName: string;
184
+ /** `<meta name="napplet-id">` value, or `local-<file stem>` when absent. */
185
+ readonly dTag: string;
186
+ /** NIP-5A aggregate hash over the single `/index.html` path entry. */
187
+ readonly aggregateHash: string;
188
+ /** sha256 of the exact file bytes, lowercase hex. */
189
+ readonly sha256: string;
190
+ /** Decoded file content assigned to `srcdoc` after CSP and prelude injection. */
191
+ readonly indexHtml: string;
192
+ /** Always empty: a local file carries no relay hints. */
193
+ readonly relays: readonly string[];
194
+ /** Always empty: a local file carries no Blossom hints. */
195
+ readonly blossomServers: readonly string[];
196
+ /** Relative `src`/`href` references that cannot load from `srcdoc`. */
197
+ readonly relativeAssets: readonly string[];
198
+ }
199
+ /** Either a verified pointer target or a local development file target. */
200
+ type PajaRuntimeTarget = PajaResolvedPointer | PajaLocalTarget;
201
+ /**
202
+ * File input accepted by {@link createPajaLocalTarget}. A browser `File`
203
+ * satisfies the first shape; tests and tools may pass text directly.
204
+ */
205
+ type PajaLocalFileInput = {
206
+ readonly name: string;
207
+ readonly type?: string;
208
+ arrayBuffer(): Promise<ArrayBuffer>;
209
+ } | {
210
+ readonly name: string;
211
+ readonly type?: string;
212
+ readonly text: string;
213
+ };
214
+ /** Hint appended to local-file errors and relative-asset warnings. */
215
+ declare const PAJA_LOCAL_SINGLE_FILE_HINT = "Paja opens self-contained single-file index.html only; relative scripts, styles, and images do not load.";
216
+ /**
217
+ * Return whether a runtime target was opened from a local file.
218
+ *
219
+ * @param target - Runtime target, or any object carrying a `source` field.
220
+ * @returns `true` for {@link PajaLocalTarget} values.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * if (isPajaLocalTarget(tab.resolvedTarget)) console.log(tab.resolvedTarget.fileName);
225
+ * ```
226
+ */
227
+ declare function isPajaLocalTarget(target: object | null | undefined): target is PajaLocalTarget;
228
+ /**
229
+ * Return whether a file name or MIME type identifies an HTML document.
230
+ *
231
+ * @param file - File name and optional MIME type.
232
+ * @returns `true` for `.html`/`.htm` names or a `text/html` type.
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * isPajaLocalHtmlFile({ name: 'index.html' }); // true
237
+ * ```
238
+ */
239
+ declare function isPajaLocalHtmlFile(file: {
240
+ readonly name: string;
241
+ readonly type?: string;
242
+ }): boolean;
243
+ /**
244
+ * Build a local runtime target from an `index.html` file.
245
+ *
246
+ * The identity is computed from the file bytes: `sha256` is the digest of the
247
+ * exact bytes and `aggregateHash` is the NIP-5A aggregate over
248
+ * `[{ path: '/index.html', sha256 }]`, the same derivation Paja's resolver
249
+ * verifies for a published single-file napplet. Editing the file gives it a
250
+ * new identity.
251
+ *
252
+ * @param file - Browser `File` or `{ name, text }`.
253
+ * @returns The local target.
254
+ * @throws Error when the file is not HTML or is empty.
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * const target = await createPajaLocalTarget({ name: 'index.html', text: '<!doctype html>…' });
259
+ * target.dTag; // 'local-index'
260
+ * ```
261
+ */
262
+ declare function createPajaLocalTarget(file: PajaLocalFileInput): Promise<PajaLocalTarget>;
263
+ /**
264
+ * Read the NIP-5D publishing metadata `<meta name="napplet-id" content="…">`.
265
+ *
266
+ * @param html - HTML document text.
267
+ * @returns The trimmed id, or `undefined` when absent or blank.
268
+ *
269
+ * @example
270
+ * ```ts
271
+ * readNappletIdMeta('<meta name="napplet-id" content="feed">'); // 'feed'
272
+ * ```
273
+ */
274
+ declare function readNappletIdMeta(html: string): string | undefined;
275
+ /**
276
+ * List relative `src`/`href` references that a `srcdoc` document cannot load.
277
+ *
278
+ * @param html - HTML document text.
279
+ * @returns Up to eight distinct relative references, in document order.
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * findRelativeAssetReferences('<script src="./main.js"></script>'); // ['./main.js']
284
+ * ```
285
+ */
286
+ declare function findRelativeAssetReferences(html: string): string[];
287
+
167
288
  /**
168
289
  * Persistent Paja catalog of resolver-verified napplet installations.
169
290
  *
@@ -186,6 +307,8 @@ interface InstalledNappletRecord {
186
307
  readonly title?: string;
187
308
  /** Verified NAP domains required by the artifact. */
188
309
  readonly requires: readonly string[];
310
+ /** Optional integrations; declarations do not grant capabilities. */
311
+ readonly optional?: readonly string[];
189
312
  /** Exact manifest convention contracts used for intent eligibility. */
190
313
  readonly archetypes: readonly {
191
314
  readonly slug: string;
@@ -223,8 +346,13 @@ declare class InstalledNappletCatalog {
223
346
  * token, so even a same-identity replacement cannot pass this check.
224
347
  */
225
348
  validateCurrent(selected: InstalledNappletRecord, target: Pick<InstalledNappletRecord, 'dTag' | 'aggregateHash'>): InstalledNappletRecord | null;
226
- /** Return exact handler candidates derived only from installed manifests. */
227
- intentCatalog(): IntentCatalogEntry[];
349
+ /**
350
+ * Return declared handlers whose host environment can receive intent delivery.
351
+ * @param canReceiveIntent - Resolve intent availability for each verified identity;
352
+ * without host policy, return declared candidates for the host to filter.
353
+ * @returns Named intent candidates usable under the supplied host policy.
354
+ */
355
+ intentCatalog(canReceiveIntent?: (record: InstalledNappletRecord) => boolean): IntentCatalogEntry[];
228
356
  /** Subscribe to explicit install and artifact-removal changes. */
229
357
  onChanged(listener: InstalledNappletCatalogListener): () => void;
230
358
  private notify;
@@ -343,4 +471,4 @@ type PajaTargetCorsFetch = (input: string, init: {
343
471
  */
344
472
  declare function probeTargetCors(targetUrl: string, fetchImpl?: PajaTargetCorsFetch): Promise<PajaTargetCorsDiagnostic>;
345
473
 
346
- export { BrowserIntentController, type BrowserIntentControllerOptions, type BrowserIntentGeneration, type BrowserIntentTerminalReason, InstalledNappletCatalog, type InstalledNappletCatalogListener, type InstalledNappletRecord, PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_NAPPLET_MANIFEST_KIND, PAJA_NAPPLET_MANIFEST_KINDS, PAJA_REQUIRED_SERVICES, PAJA_TARGET_CORS_HINT, PAJA_UPSTREAM_WEB_DOMAINS, type PajaDecodedPointer, PajaHostConfig, type PajaPointerRelayPool, PajaRawOptions, type PajaResolvedPointer, type PajaTargetCorsDiagnostic, type PajaTargetCorsFetch, type PajaTargetCorsStatus, type ResolvePajaPointerOptions, classifyTargetCors, decodePajaPointer, getMissingAdvertisedDomains, getMissingServices, injectPajaRuntimeCsp, loadPajaConfigFile, mergePajaRawOptions, probeTargetCors, renderPajaHtml, resolvePajaPointer, resolvePajaRawOptions };
474
+ export { BrowserIntentController, type BrowserIntentControllerOptions, type BrowserIntentGeneration, type BrowserIntentTerminalReason, InstalledNappletCatalog, type InstalledNappletCatalogListener, type InstalledNappletRecord, PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_LOCAL_SINGLE_FILE_HINT, PAJA_NAPPLET_MANIFEST_KIND, PAJA_NAPPLET_MANIFEST_KINDS, PAJA_REQUIRED_SERVICES, PAJA_TARGET_CORS_HINT, PAJA_UPSTREAM_WEB_DOMAINS, type PajaDecodedPointer, PajaHostConfig, type PajaLocalFileInput, type PajaLocalTarget, type PajaPointerRelayPool, PajaRawOptions, type PajaResolvedPointer, type PajaRuntimeTarget, type PajaTargetCorsDiagnostic, type PajaTargetCorsFetch, type PajaTargetCorsStatus, type ResolvePajaPointerOptions, classifyTargetCors, createPajaLocalTarget, decodePajaPointer, findRelativeAssetReferences, getMissingAdvertisedDomains, getMissingServices, injectPajaRuntimeCsp, isPajaLocalHtmlFile, isPajaLocalTarget, loadPajaConfigFile, mergePajaRawOptions, probeTargetCors, readNappletIdMeta, renderPajaHtml, resolvePajaPointer, resolvePajaRawOptions };
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  PAJA_ADVERTISED_DOMAINS,
12
12
  PAJA_COMPATIBILITY_ALIASES,
13
13
  PAJA_HANDSHAKE_DOMAINS,
14
+ PAJA_LOCAL_SINGLE_FILE_HINT,
14
15
  PAJA_NAPPLET_MANIFEST_KIND,
15
16
  PAJA_NAPPLET_MANIFEST_KINDS,
16
17
  PAJA_REQUIRED_SERVICES,
@@ -22,24 +23,29 @@ import {
22
23
  ReadinessError,
23
24
  classifyTargetCors,
24
25
  createPajaHostConfig,
26
+ createPajaLocalTarget,
25
27
  createPajaRuntimeHostConfig,
26
28
  decodePajaPointer,
29
+ findRelativeAssetReferences,
27
30
  formatPajaUrl,
28
31
  getMissingAdvertisedDomains,
29
32
  getMissingServices,
30
33
  injectPajaRuntimeCsp,
34
+ isPajaLocalHtmlFile,
35
+ isPajaLocalTarget,
31
36
  loadPajaConfigFile,
32
37
  mergePajaRawOptions,
33
38
  normalizePajaOptions,
34
39
  normalizePajaSimulation,
35
40
  probeTargetCors,
41
+ readNappletIdMeta,
36
42
  renderPajaHtml,
37
43
  resolvePajaPointer,
38
44
  resolvePajaRawOptions,
39
45
  startPajaServer,
40
46
  summarizePajaSimulation,
41
47
  waitForTargetUrl
42
- } from "./chunk-ESE55K3Q.js";
48
+ } from "./chunk-GY5ET3PC.js";
43
49
  export {
44
50
  BrowserIntentController,
45
51
  DEFAULT_PAJA_AGGREGATE_HASH,
@@ -53,6 +59,7 @@ export {
53
59
  PAJA_ADVERTISED_DOMAINS,
54
60
  PAJA_COMPATIBILITY_ALIASES,
55
61
  PAJA_HANDSHAKE_DOMAINS,
62
+ PAJA_LOCAL_SINGLE_FILE_HINT,
56
63
  PAJA_NAPPLET_MANIFEST_KIND,
57
64
  PAJA_NAPPLET_MANIFEST_KINDS,
58
65
  PAJA_REQUIRED_SERVICES,
@@ -64,17 +71,22 @@ export {
64
71
  ReadinessError,
65
72
  classifyTargetCors,
66
73
  createPajaHostConfig,
74
+ createPajaLocalTarget,
67
75
  createPajaRuntimeHostConfig,
68
76
  decodePajaPointer,
77
+ findRelativeAssetReferences,
69
78
  formatPajaUrl,
70
79
  getMissingAdvertisedDomains,
71
80
  getMissingServices,
72
81
  injectPajaRuntimeCsp,
82
+ isPajaLocalHtmlFile,
83
+ isPajaLocalTarget,
73
84
  loadPajaConfigFile,
74
85
  mergePajaRawOptions,
75
86
  normalizePajaOptions,
76
87
  normalizePajaSimulation,
77
88
  probeTargetCors,
89
+ readNappletIdMeta,
78
90
  renderPajaHtml,
79
91
  resolvePajaPointer,
80
92
  resolvePajaRawOptions,
@@ -1,3 +1,5 @@
1
+ import { NappletCspOptions } from '@kehto/shell';
2
+
1
3
  /** JSON primitive accepted in Paja simulation config values. */
2
4
  type JsonPrimitive = string | number | boolean | null;
3
5
  /** JSON value accepted in Paja simulation config values. */
@@ -208,6 +210,8 @@ interface PajaOptions {
208
210
  }
209
211
  /** Serialized host-page config served to the browser runtime. */
210
212
  interface PajaHostConfig {
213
+ /** Host CSP overrides for verified runtime-pointer documents, validated by shell. */
214
+ readonly csp?: NappletCspOptions;
211
215
  /** Config schema version. */
212
216
  readonly version: 1;
213
217
  /** Window identity used for the development target. */
@@ -279,6 +283,7 @@ declare function createPajaHostConfig(options: PajaOptions, now?: Date): PajaHos
279
283
  * @returns Serializable host-page config.
280
284
  */
281
285
  declare function createPajaRuntimeHostConfig(options?: {
286
+ readonly csp?: NappletCspOptions;
282
287
  readonly pointer?: string;
283
288
  readonly relays?: readonly string[];
284
289
  readonly blossomServers?: readonly string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kehto/paja",
3
- "version": "0.17.1",
3
+ "version": "0.19.0",
4
4
  "description": "Paja local authoring workshop for hosting napplets in a real Kehto iframe during development",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,12 +26,12 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@kehto/acl": "^0.19.0",
29
+ "@kehto/nip": "^0.6.0",
29
30
  "@kehto/firewall": "^0.6.0",
30
- "@kehto/nip": "^0.5.2",
31
31
  "@kehto/runtime": "^0.24.0",
32
- "@kehto/services": "^0.22.0",
33
- "@kehto/shell": "^0.21.2",
34
- "@kehto/wm": "^0.0.2"
32
+ "@kehto/services": "^0.22.1",
33
+ "@kehto/wm": "^0.0.2",
34
+ "@kehto/shell": "^0.22.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@napplet/core": ">=0.32.0 <0.33.0",