| English | 中文版 |
RFC ID: NPS-RFC-0006 Status: Proposed Version: 0.2 Date: 2026-06-12 Authors: Ori Lynn / INNO LOTUS PTY LTD Depends-On: NPS-1 (NCP) v0.7, NPS-3 (NIP) v0.9 Issue: GitHub NPS-Dev#45
NCP defines two transport modes: HTTP mode (NCP frames carried in HTTP bodies) and native
mode (direct TCP or QUIC connection). NCP v0.6 specified the connection preamble
(b"NPS/1.0\n", NPS-RFC-0001) and the HelloFrame/CapsFrame handshake but left QUIC stream
mapping, rekeying, and conformance requirements implementation-defined.
This RFC formalises the native mode transport binding for both TCP and QUIC, enabling interoperable implementations across all six reference SDKs.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHOULD”, “SHOULD NOT”, and “MAY” are used as per RFC 2119.
b"NPS/1.0\n" as the first bytes
(NPS-RFC-0001).0x06) immediately after the preamble, within 5 seconds.0x04) within 5 seconds of receiving HelloFrame,
or send an ErrorFrame and close the connection.NCP frames over TCP use a 5-byte length-prefixed framing:
[4 bytes: payload length, big-endian uint32]
[1 byte: frame-type byte (flags + type)]
[N bytes: frame payload]
Total frame size MUST NOT exceed the negotiated max_frame_payload (HelloFrame field).
If a frame exceeds this limit the receiver MUST return NCP-FRAME-TOO-LARGE and MAY
close the connection.
status = "closing" before closing the
TCP socket.NCP-NODE-UNAVAILABLE.NCP-over-QUIC uses ALPN identifier nps/1.0 (the suite-wide NPS native-mode ALPN token;
see §6.1). This supersedes the provisional ncp/1 used in v0.1 of this draft. IANA
registration is pending a follow-up RFC; implementations MUST use nps/1.0.
Frames over QUIC do not need length prefixing at the NCP layer because QUIC provides stream-level framing. The frame encoding is:
[1 byte: frame-type byte (flags + type)]
[N bytes: frame payload]
Each NCP frame occupies exactly one QUIC STREAM frame sequence (may span multiple QUIC packets but MUST be delivered atomically to the NCP layer).
Server or client closes the QUIC connection with CONNECTION_CLOSE frame, application
error code 0x00 for graceful close. Error code 0x01 indicates protocol violation.
HelloFrame over QUIC MUST set the transport field to "quic". Servers that do not
support QUIC MUST return an ErrorFrame with NCP-VERSION-INCOMPATIBLE when they detect
the ALPN negotiation has yielded nps/1.0 over QUIC unexpectedly.
When E2E encryption is active (NCP §7.4), implementations MUST rekey the session after:
whichever occurs first. Implementations SHOULD rekey at 2^32 - 65536 frames (slightly early) to avoid the limit being hit mid-frame.
The party initiating rekey sends a frame with the EXT header field rekey: true. The
receiving party MUST complete the current frame exchange, then perform key derivation using
the agreed KDF before sending the next frame.
If a peer continues sending encrypted frames past 2^32 frames without rekeying, the
receiver MUST send NCP-REKEY-REQUIRED and MUST close the connection.
max_concurrent_streams NegotiationHelloFrame carries max_concurrent_streams (uint16). The server echoes its own cap in the
CapsFrame. The effective limit is min(client_cap, server_cap) and applies bidirectionally.
Implementations MUST track the count of open streams and MUST reject new stream-opening
frames that would exceed the limit with NCP-STREAM-LIMIT-EXCEEDED. Streams that are
fully closed (both sides have sent terminal frames) MUST be released from the count.
Default: 32. Minimum: 1. Maximum: 65535.
This section standardizes the transport-security layer for native-mode NCP, resolving the prior open questions on ALPN and TLS framing (OQ-1, OQ-3).
Both native-mode transports advertise the suite-wide ALPN token nps/1.0:
nps/1.0.nps/1.0 is negotiated as part of the QUIC/TLS 1.3 handshake (§3.1).A server that does not recognise nps/1.0 MUST fail the TLS handshake with
no_application_protocol (TLS alert 120) rather than fall through to a default protocol.
Native-mode-over-TCP MUST use TLS-wrapped transport: TLS 1.3 is established first, and the
RFC-0001 preamble (b"NPS/1.0\n") plus all NCP frames travel inside the TLS session.
STARTTLS-style in-band upgrade is NOT permitted for native mode (it leaves the preamble and
HelloFrame in cleartext). The local-dev profile (NPS-4 §7.2) MAY run without TLS for
loopback testing only. QUIC’s TLS 1.3 is built in and satisfies this requirement intrinsically.
When the higher-layer profile requires authentication, native mode MUST use mutual TLS:
trust_anchors, NWP v0.13 §4.1) and bind the
certificate’s NID to the NCP session.IdentFrame (§2 of NPS-1 native handshake) remains the authority for
capabilities, scope, and assurance level; the mTLS certificate NID and the IdentFrame NID
MUST match, else the server MUST close with NCP-NID-MISMATCH.mTLS is the transport-layer admission gate that nps-ingress (L2) terminates; see the NPS-Node
Profile L2 requirements.
To reduce cold-start latency for repeated short-lived native connections, servers MAY issue a
session-resumption ticket (TLS 1.3 NewSessionTicket). Resumed sessions:
NCP-NID-MISMATCH.A native-mode conformant NCP implementation MUST:
max_concurrent_streamsnps/1.0 (§6.1–§6.2) in all non-local-dev profilesIdentFrame/certificate NID mismatch with NCP-NID-MISMATCH (§6.3)A native-mode conformant NCP implementation SHOULD:
status="closing")Native mode connections MUST use TLS 1.3 or QUIC’s built-in encryption in production
deployments (local-dev profile exempted per NPS-4 §7.2). The connection preamble
(b"NPS/1.0\n") travels in the clear before TLS negotiation only when the transport is
raw TCP without STARTTLS; implementations SHOULD use TLS from the first byte where
possible (i.e. TLS wrapping the NCP native connection, with preamble sent inside TLS).
E2E encryption at the NCP frame layer (§7.4) is a defense-in-depth mechanism and does not replace transport-layer TLS.
| ID | Question | Status |
|---|---|---|
| OQ-1 | IANA registration for ALPN nps/1.0 |
Resolved (value chosen, §6.1); IANA registration tracked in a follow-up RFC after the IETF Internet-Draft |
| OQ-2 | QUIC version: QUIC v1 (RFC 9000) only, or also QUIC v2? | Open — defer to Phase 3 |
| OQ-3 | STARTTLS vs. TLS-wrapped: mandate one? | Resolved (§6.2 — TLS-wrapped mandated for native mode; STARTTLS prohibited) |
| Version | Date | Changes |
|---|---|---|
| 0.2 | 2026-06-12 | Draft → Proposed. Added §6 TLS Binding & Mutual Authentication: suite-wide ALPN nps/1.0 (supersedes provisional ncp/1), TLS-wrapped framing mandated for native-mode-over-TCP (resolves OQ-3), mTLS with NIP certificates + session-NID binding (NCP-NID-MISMATCH), TLS 1.3 session-resumption tickets. Conformance §7 gains TLS/mTLS MUSTs. OQ-1/OQ-3 resolved. §7–§10 renumbered. |
| 0.1 | 2026-05-28 | Initial Draft |
Attribution: LabAcacia / INNO LOTUS PTY LTD · Apache 2.0