Appearance
Packages
kernl has four packages. Each has two names: @kernlize/* on npm and @kernl/* on JSR, for the same code at the same version. Neither registry has a release yet (see Install). Three are pure contracts and engines with zero framework dependencies; one composes them with kehto and applesauce. The shell app at apps/web is not published.
| npm | Version | JSR | Role | Dependencies | Peer dependencies |
|---|---|---|---|---|---|
@kernlize/guard | 0.1.1 | @kernl/guard | Ingress flood control, visibility gate, focus-aware firewall, CSP profile, nested-frame lock, mitigation descriptions. | @kehto/firewall | @napplet/core |
@kernlize/messaging | 0.4.0 | @kernl/messaging | Messaging provider contract, registry, composite direct-message adapter, in-memory backend. | none | @napplet/core (the Dm* wire types) |
@kernlize/bridges | 0.2.1 | @kernl/bridges | Locator parsing, bridge contract, registry, HTTP bridge with SSRF policy. | none | none |
@kernlize/core | 0.8.0 | @kernl/core | Composition root over kehto and applesauce: adapters, applet resolution, mount plan, consent summaries, layouts, persistence. | the three above, @kehto/*, applesauce-*, rxjs | @napplet/core, @napplet/nap, @napplet/shim, nostr-tools (required by kehto and applesauce; never imported) |
Shared rules
- ESM only, TypeScript strict,
verbatimModuleSyntax. Each package shipsdist/index.jsanddist/index.d.tswithsideEffects: false. - Every public export has JSDoc with
@param,@returnsand@example, and appears in the API reference. - Streams in
@kernlize/coreare rxjsObservables (session$,guard.events$,grants.changes$,relays.changes$,AppletHandle.status$); unsubscribe theSubscriptionthey return.MessagingBackend.subscribereturns{ subscriptionId }, which you pass tounsubscribe. Thrown errors carry a stable prefixed reason:denied:,invalid:,unavailable:; the full list is in Error reasons. - No published package imports
nostr-toolsdirectly, and no published package depends on a UI framework.pnpm check:depsenforces both. - Behaviour is specified in Gherkin under each package's
features/and run by vitest with 100% coverage oversrc.
Versioning
All packages are 0.x. A breaking change is a minor bump; everything else is a patch. Releases are managed with changesets: one changeset per package whose shipped output changed. @kernlize/core depends on the other three with workspace:^, so a release of a leaf package produces a patch of core.
Install
Every package has an npm name and a JSR name. The code, the exports and the version are the same under both.
| Directory | npm | JSR |
|---|---|---|
packages/guard | @kernlize/guard | @kernl/guard |
packages/messaging | @kernlize/messaging | @kernl/messaging |
packages/bridges | @kernlize/bridges | @kernl/bridges |
packages/core | @kernlize/core | @kernl/core |
After the first release, install from either registry:
sh
npm install @kernlize/core
# or, with Deno or any JSR client
deno add jsr:@kernl/coreImport by the name of the registry you installed from. The examples in these docs use the npm names; with JSR, write @kernl/ where they write @kernlize/. That holds for subpaths too: @kernlize/core/wm on npm is @kernl/core/wm on JSR. npm ships JavaScript and declarations; JSR ships the TypeScript source. Publish packages covers release setup.
Neither registry has a release yet: npm install @kernlize/core and deno add jsr:@kernl/core both fail with a not-found error. During the alpha the source repository is private, and the packages are used from a clone of it:
bash
# in a clone of the kernl source repository
pnpm install && pnpm buildpnpm build writes each package's dist/, which is what main, types and exports point at. Then add your code as a workspace package (under packages/ or apps/, the globs in pnpm-workspace.yaml) and depend on what you need with the workspace protocol, as apps/web does:
json
{
"dependencies": {
"@kernlize/core": "workspace:^",
"@kernlize/guard": "workspace:^"
}
}Run pnpm install again after editing the manifest so pnpm links the workspace packages. @kernlize/core pulls the other three in. Install a leaf package alone when you want its contract without kehto and applesauce, for example @kernlize/guard to test an applet against the limits, or @kernlize/messaging to write a provider.