Skip to content

NIP-5D event schema migration ​

Kehto accepts current single-artifact events and legacy aggregate events. New playground and fixture builds use published @napplet/vite-plugin@0.15.0. Core/nap 0.32.0, shim 0.30.0, and SDK 0.28.0 remain the published runtime contracts; their versions did not change for this writer release.

Authority ​

Checked NIP-5D draft PR #2303 at 020cb8b, NAP-INTENT and NAP-SHELL at napplet/naps@a040914b4bbd3a5cd8a14b0f316a723c968ebfb2. The writer release source is napplet/web@831d3dd5056b84bc03982966279ed8b9167152f8. The current path conforms to this draft; legacy support is an explicit temporary compatibility policy, not the current protocol format.

Normalization boundary ​

ConcernCurrent eventLegacy event
IdentitySHA-256 of /index.html in one x tagNIP-5A aggregate over path tags; x has aggregate marker
DescriptionNonempty plain-text contentdescription tag
Required domainsRepeated RRepeated requires
Optional integrationsRepeated O, never load requirementsNo declaration
RoutingIndependent z and queryless i setsExplicit archetype role/convention pairs
IconOptional supported hash/MIME declarationGeneric artwork

parseNappletManifest selects one parser from the signed event's x marker. It never retries a malformed current manifest as legacy. The compatibility module packages/nip/src/5d/legacy-manifest.ts owns legacy tag interpretation and aggregate checks. Current manifests normalize to one /index.html path so the shared byte-verification and cache pipeline needs no schema-specific fetch logic.

ResolvedNapplet.artifactHash exposes the verified identity. Existing aggregateHash host, session, cache, and ACL fields retain their names and carry the same value. Legacy identities stay unchanged. Republishing identical HTML in the current format changes its identity from the aggregate to the artifact hash; permissions and cached coordinate metadata must be re-established normally. Do not copy legacy grants to the new identity automatically.

The parser preserves archetypeSlugs and intents with their parameter names. For intent consumers, archetypes preserves { slug, convention, params } only when the convention role matches an advertised z role. This follows NAP-INTENT PR #106 at fc121fc264615482143eda86125863d2e1f741a2. Parameter names remain ordered text hints, not types or requirements. Invalid advertisements are ignored. Legacy pairs retain empty parameter lists. A current event without matching declarations remains loadable but has no intent handler eligibility. catalogId separates named publisher/d-tag, root publisher, and snapshot event identities; it never replaces the existing artifact/cache identity.

Both hosts check required domains against their actual environment before execution. shell is mandatory. Optional domains never block loading or expand the injected namespace. Both host catalogs require the target's resolved intent domain; canonical delivery does not require an INC declaration or binding. Root and snapshot artifacts participate through their opaque catalog IDs when they advertise an eligible contract; no d-tag is invented for them.

Icons are not needed to load an artifact. Kehto retains generic artwork; merely parsing a supported icon declaration does not fetch or render it. Future display code must verify the blob hash and decode the declared supported image format. Snapshot a/A lineage is retained as metadata and never fetched on the snapshot's behalf. HTML metadata is only publisher input, not runtime authority.

Removing compatibility ​

Retire the explicit legacy selection branch and legacy-manifest.ts, then remove legacy fixtures and paired-schema tests. Keep the shared verification, cache, loaders, host injection, current schema tests, and NIP-5A utility package intact. Renaming the public aggregateHash alias is a separate API migration; it is not required to remove legacy event support.

While compatibility remains, tests cover both formats through signature/blob failure, cache reuse and corruption recovery, all three manifest kinds, Paja and playground resolution, host admission, and opaque srcdoc execution. Current producer tests verify the final bytes against x after metadata and inlining.

Successful legacy resolution emits KEHTO_COMPAT_LEGACY_MANIFEST once per resolver module lifetime. Migration and retirement criteria are tracked in the compatibility register.

URI invocation, accepted-result lifecycle, and catalog identity follow NAP-INTENT PR #106 at fc121fc264615482143eda86125863d2e1f741a2. Hosts use intent.deliver and buffered intent.onDelivery, with a warned local INC-listener adapter. Paja external links use a verified signed launcher for source identity. Native external-origin sender semantics remain a deferred upstream spec gap. The conformance policy records the checked authority and bounded packaged-type exception.