[← All NAPs](https://napplet.run/protocol/)

NAP-CLASS-1 / PR #17

# Strict Baseline Class

Draft PRDeferred upstream

The registry marks NAP-CLASS as deferred. This proposal is dormant and should not be treated as an available protocol capability.

This is an unmerged proposal. Its API and scope may change during discussion. Participate on the pull request before depending on it.

Full specification from [the fetched upstream revision ↗](https://github.com/napplet/naps/blob/b9128e0cb61138680c0a76061174fb6d014c0d93/naps/NAP-CLASS-1.md). The document below is rendered from its original Markdown. [Follow the latest source on GitHub ↗](https://github.com/napplet/naps/pull/17/files).

## NAP-CLASS-1

### Strict Baseline Class

`draft`

**NAP ID:** NAP-CLASS-1 **Parent:** NAP-CLASS **Class number:** 1

### Description

NAP-CLASS-1 is the strict baseline posture for napplets that do not declare any class-contributing NAP capabilities. Shells emit a restrictive Content Security Policy with `connect-src 'none'`, show no consent prompt, and send `class.assigned` with `class: 1`. This is the default class for any napplet whose manifest lacks tags from NAPs that would promote it to a higher class.

### CSP Posture

```
connect-src 'none'
```

Shells emitting the NAP-CLASS-1 posture MUST include `connect-src 'none'` in the runtime CSP served with the napplet's HTML. The directive is the signal that the napplet has no user-approved direct-network origins. Other directives in the baseline CSP (e.g., `script-src`, `default-src`, `img-src`) are shell-policy concerns and are NOT specified by NAP-CLASS-1 — only the `connect-src` value is the class's defining characteristic.

### Manifest Prerequisites

NAP-CLASS-1 is the default posture. A napplet manifest reaches NAP-CLASS-1 when no other class-contributing NAP's trigger conditions are met. Future `NAP-CLASS-$N` entries (with `$N > 1`) MUST document their own trigger conditions; absence of all such triggers means the napplet is NAP-CLASS-1.

There is no consent state associated with NAP-CLASS-1 and therefore no user-consent prerequisite. A napplet resolves to this class at first load, at every subsequent load, and under every shell that implements the base protocol — independent of user action.

### Shell Responsibilities

-   Shell MUST emit a runtime CSP header containing `connect-src 'none'` for the napplet's HTML response.
-   Shell MUST NOT prompt the user for any network-access consent when serving a NAP-CLASS-1 napplet — there is nothing to consent to, and raising a prompt would mislead the user into believing a choice is available when none is.
-   Shell MUST send exactly one `class.assigned` envelope with payload `{ class: 1 }` at iframe-ready time per NAP-CLASS's wire-timing rules. A shell that implements `nap:class` MUST deliver the envelope even when the value is `1`; silence is not the same signal as explicit assignment.
-   Shell SHOULD treat residual `<meta http-equiv="Content-Security-Policy">` in NAP-CLASS-1 napplet HTML as harmless (CSP intersection of two `connect-src 'none'` values is still `'none'`), but MAY log a deployment warning to encourage napplet authors to migrate away from meta-CSP emission. Shells MUST NOT refuse-to-serve a NAP-CLASS-1 napplet solely on the basis of residual meta-CSP.
-   Shell MUST NOT add sandbox relaxations or CSP directives that would cause a NAP-CLASS-1 napplet to behave distinguishably from another NAP-CLASS-1 napplet. The posture is uniform across all napplets in this class.

### Security Considerations

#### Strictness floor, not a ceiling

NAP-CLASS-1 is the minimum-trust posture. It is appropriate for napplets with no network requirements, napplets that rely exclusively on shell-mediated resource fetching (via other NAPs that provide proxied resource access), or napplets in development/test environments where network egress is disabled by policy. A shell that wishes to apply a weaker posture than NAP-CLASS-1 cannot do so while claiming conformance to this class — the `connect-src 'none'` directive is not a default, it is a guarantee. A weaker posture is a different class and MUST be assigned a different integer.

#### CSP intersection

Because the browser enforces CSP as an intersection of header and meta directives, a NAP-CLASS-1 napplet that accidentally ships meta-CSP with `connect-src 'none'` will still behave correctly — the intersection of `'none'` and `'none'` is `'none'`. This is why shells treat residual meta-CSP as harmless in the NAP-CLASS-1 case but refuse-to-serve in higher classes: a meta-CSP with `connect-src 'none'` silently suppresses any header-level grant, which is catastrophic for classes that rely on granted origins but a no-op here.

#### No grant state

NAP-CLASS-1 has no persistent state — no consent decision, no origin list, no `(dTag, aggregateHash)` key. Every napplet resolving to NAP-CLASS-1 is indistinguishable from every other at the class level. This makes the class a safe default: a shell may assign it silently, without interrupting the user, without persisting any record that would outlive the session.

#### Compatibility with other NAPs

NAP-CLASS-1 is deliberately compatible with every other NAP a shell may choose to implement. A shell may grant a NAP-CLASS-1 napplet access to, for example, a shell-mediated storage NAP or a shell-mediated relay NAP; the class does not forbid this. What the class forbids is the napplet reaching external network origins directly from the frame — everything network-sourced MUST flow through a shell-mediated NAP's `postMessage` surface.

### References

-   `NAP-CLASS.md` — parent spec; defines the `class.assigned` envelope, the `window.napplet.class` runtime surface, and the authoring rules for track members including NAP-CLASS-1.
-   NIP-5D — Napplet wire format.

### Changelog

-   `71ad6a1` - Introduced NAP-CLASS-1 as the strict baseline posture sub-track.

[Join the discussion · PR #17 ↗](https://github.com/napplet/naps/pull/17)[Read proposed changes ↗](https://github.com/napplet/naps/pull/17/files)

On this pageSpecification metadata

Capability domain

`Not declared`

Repository state

Draft PR

Registry status

Deferred

Document marker

draft

Declared dependencies

None declared in the preamble

Source revision

`b9128e0cb611`

[View source on GitHub ↗](https://github.com/napplet/naps/pull/17/files)
