Appearance
Runtime Resource Policy Boundary
Kehto does not define a universal resource-network policy. It is a toolkit and protocol kernel: runtimes choose how URLs are resolved, which schemes they support, and which origin, redirect, privacy, integrity, MIME, and size policies fit their environment.
The protocol authority is draft NAP-RESOURCE at exact ref 9511232f69313aa7953d110e35d32cc28d506f66, with the server-hint semantics introduced by 75312589cdc5012be0ac09d7aa87e265564d3bf8. The package projection was merged in napplet/web#206 at 19e0029b228127769a0ebdcf0b6b2f30293bd284 and published from b007587afbefb0ce5592825d6ec1fc5b026c7b08 as @napplet/core and @napplet/nap 0.32.0, @napplet/shim 0.30.0, and @napplet/sdk 0.28.0. Merged NAP-IDENTITY at exact ref a040914b4bbd3a5cd8a14b0f316a723c968ebfb2 delegates profile picture and banner retrieval through NAP-RESOURCE. Those documents, together with NIP-5D, take precedence over this non-normative implementer guide.
Kehto's boundary
createResourceService() owns NAP request correlation, cancellation, bulk limits, per-resource request projection, and result/error envelopes. The runtime supplies the resolver through fetch(url, init). For blossom: only, init.servers carries the request's ordered advisory locations; other schemes never receive that metadata. init.windowId is authenticated runtime context, not napplet payload, and lets a resolver keep policy state scoped to the source window without extending the NAP wire.
The default Kehto path is permissive delegation:
- every syntactically valid URL is passed to the injected resolver;
resource.bytesManyaccepts canonical{ requests: [{ url, servers? }] }input and preserves per-entry metadata, order, and result length;resource.info.schemesis optional, advisory capability discovery and never an authorization gate;- resolver-returned bytes and MIME are carried on the NAP wire;
- napplet-side
resource.bytesandresource.bytesManycorrelation remains open until the runtime sends a terminal result or error; runtimes own fetch deadlines and callers own explicitAbortSignalcancellation, which emitsresource.canceland drops late terminal envelopes; - explicit
ResourceServiceErrorcodes are preserved; and - an unexpected resolver failure becomes the canonical
network-error.
Kehto also retains optional origin-grant tooling. A runtime that wants that policy supplies isOriginGranted, getConnectGrants, and resolveIdentity together. The service then checks the authenticated (dTag, aggregateHash) grant before invoking the resolver. A runtime that does not want origin grants omits all three hooks. Neither choice changes NAP-RESOURCE wire semantics.
Runtime-owned choices
The resolver is the policy boundary. Depending on its deployment, a runtime may choose browser fetch, a native HTTP stack, a backend proxy, content-addressed storage, or another scheme-specific implementation. The runtime decides, within the NAP contract:
- supported schemes and how unknown schemes fail;
- whether HTTP(S) origins require grants;
- credential and referrer handling;
- redirect and address rules;
- timeouts, response limits, and concurrency;
- Blossom hint validation, deduplication, caps, fallback order, and per-attempt network policy;
- integrity verification and cache partitioning; and
- byte-based MIME classification or transformations.
These are options Kehto enables runtimes to implement, not requirements Kehto imposes on every runtime.
Browser behavior
An image element and fetch() do not have the same CORS visibility. A browser may display a cross-origin image while preventing JavaScript from reading the same redirect response. A browser-only resolver cannot recover bytes the browser withholds. It should return bytes when its fetch can read them and report the canonical network-error when the browser rejects the fetch. Kehto does not invent a CORS-only NAP error or reinterpret that browser limitation as a ban on HTTP(S) resources.
Kehto reference surfaces
Paja is the reference developer runtime. It deliberately accepts arbitrary http: and https: resource origins, uses credentialless/no-referrer browser fetching, and lets browser CORS and mixed-content rules determine readability. It advertises data, https, http, and blossom, because a Blossom request may supply an accepted server without a host default. Its blossom: resolver accepts public-looking HTTPS origin hints, discards invalid/private literals, deduplicates and caps the combined candidate list at eight, tries accepted request hints before host defaults, refuses redirects, and verifies SHA-256. Configured loopback HTTP remains a Paja-only local-development default. As a browser-only developer runtime, Paja cannot independently pin DNS resolution; production resolvers still must perform NAP-RESOURCE's DNS-time private-address checks before connecting and on every redirect.
Paja also retains bounded per-window context for canonical Blossom references returned by outbox.getEvent, outbox.query, or outbox.subscribe. On a later byte request it orders event-local server hints before hinted authors' and the verified event publisher's newest BUD-03 kind-10063 lists, then the active shell user's BUD-03 list, followed by configured runtime fallbacks. Author, publisher, and user lists are read lazily through the same NIP-65-aware OUTBOX router, independently of upload mode, so reading events never prefetches their blobs. This is a runtime-default policy within NAP-RESOURCE's second tier, not a new wire field or an upload-mode dependency. It follows Blossom BUD-03 at exact ref b5bd2801d1763aa635fc8fea7a76597e0eb18990.
The playground is a visualization, not the reference runtime. It retains static origin grants and iframe CSP fixtures so implementers can see and test the optional grant-policy path. Those fixtures do not establish Kehto-wide policy.
Implementation references
packages/services/src/resource-service.ts— policy-neutral NAP lifecycle and optional origin-grant adapter.packages/paja/src/browser-resource.ts— Paja's concrete browser, data, and Blossom resolution choices.packages/paja/src/browser-blossom-events.ts— per-window OUTBOX resource context and author/publisher/user BUD-03 discovery.apps/playground/src/demo-hooks.ts— playground grant visualization.tests/e2e/nap-resource.spec.ts— browser evidence for image loading versus fetch-visible bytes and canonical failure.- NIP-5D conformance policy — envelope, provenance, and sandbox requirements shared by Kehto host implementations.