# Native Wire (LNW/1)

Lockwell Native Wire (LNW/1) is the deterministic binary transport for the native data plane. It is **experimental,
opt-in, and disabled by default** (`defaultEnabled: false`). The existing S3-compatible and HTTP-native JSON clients
remain supported choices while an LNW deployment completes its own qualification. LNW is a transport, not a fourth
authorization or storage surface: requests still enter the shared tenant, policy, quota, retention, object, metadata,
encryption, audit, and storage pipeline.

The normative protocol and registry are maintained in [`docs/native-wire-v1.md`](https://github.com/RusticStack/lockwell/blob/main/docs/native-wire-v1.md),
[`native-wire-v1.json`](/native-wire-v1.json), and the [wire reference](/reference/native-wire). The website pages are
generated as pre-rendered HTML and raw Markdown (`/guide/native-wire.md`) so the contract can be fetched without
JavaScript. Shared cross-language snippets and their security notes live in
[`/sdk-public-api-examples-v1.json`](/sdk-public-api-examples-v1.json).

## When to use it

Use LNW when a server-side application needs multiplexed, backpressured binary object I/O over a direct TLS connection
and can operate a qualified Node, Bun, or JVM runtime. Use the [S3 surface](/guide/the-three-surfaces#s3-data-plane-sigv4)
for existing S3 tools or genuine SSE-C. Use the [HTTP-native JSON surface](/guide/the-three-surfaces#native-json-data-plane-apiv1)
when a deployment has not enabled the binary listener. Use the [Admin API](/reference/admin-api) for provisioning,
quotas, and audit rather than an access-key data-plane connection.

LNW does not silently fall back to HTTP, JSON, XML, S3, or an object-store emulator. A refused capability, unsupported
runtime, failed handshake, or transport error is returned to the caller with a stable error; choose another surface
explicitly if that is the desired migration behavior.

## Architecture and wire shape

The listener owns framing and connection state only. It dispatches operation codes to the existing native handlers; it
never calls the storage backend directly. This keeps authorization and tenant isolation in one place:

```mermaid
flowchart LR
  C["Qualified client"] -->|TLS 1.3| L["LNW listener"]
  L -->|typed operation and FieldDocument| N["Native domain handlers"]
  N --> P["Policy, scope, quota, retention, audit"]
  P --> O["Object coordinator"]
  O --> S[("Tenant-qualified encrypted store")]
```

Every frame has a 40-byte big-endian header (`LKW1`, version, type, flags, direction sequence, request/stream IDs,
code, reserved bytes, metadata length, and payload length), followed by TLV metadata, payload, and a CRC32C. The CRC
detects corruption and framing mistakes; TLS supplies confidentiality and channel integrity. Metadata TLVs are sorted,
bounded, shortest-form UTF-8, NUL-free, and deterministic. Unknown optional fields are skipped; unknown critical fields,
duplicate singular fields, non-canonical order, and invalid UTF-8 fail closed. Nested values use deterministic
`FieldDocument`; JSON is never a wire fallback.

The default negotiated limits are 64 KiB metadata, 1 MiB payload per DATA frame, 1,114,156 bytes per frame, 128 streams
per connection, 1,024 connections, a 4 MiB stream window, and a 16 MiB connection window. Clients must apply the
negotiated minimum before allocating and must respect `WINDOW_UPDATE` credit. Only one reader and one writer goroutine
own a connection; independent streams may execute concurrently.

## TLS, mTLS, and authentication

Non-loopback LNW listeners require TLS 1.3. Hostname verification remains enabled. Configure a private CA on the client
when the certificate is not publicly trusted. Listener client authentication is `none`, `optional-mtls`, or
`required-mtls`; mTLS is a listener policy, not a capability negotiated in HELLO/WELCOME. The native clients require a
certificate and key together when mTLS is used. Plaintext is reserved for an explicit loopback test configuration.

The connection state machine is:

1. `HELLO` advertises the protocol range, capabilities, and receive limits.
2. `WELCOME` selects exactly one version and the capability intersection. There is no silent downgrade.
3. `AUTH` proves the access key with a timestamp, fresh 16-byte nonce, and HMAC-SHA-256 over the transcript.
4. `AUTH_OK` returns the tenant, session expiry, negotiated capabilities, and effective limits; `AUTH_ERROR` is bounded.
5. Odd client stream IDs carry one operation each (`REQUEST`, optional `DATA`, `END`); responses use `RESPONSE`,
   `DATA`, `END`, or a typed terminal `ERROR`.

Credential providers are evaluated for each new connection, so rotation and revocation do not require rebuilding a
client. The server rechecks credential expiry, revocation, tenant-disabled state, and scope before every new stream.
Authentication state is bounded per access-key principal: up to 256 unexpired nonces for each of 1,024 principals by
default. A duplicate nonce is `AUTH_REPLAY` (0x0103), non-retryable and without a hint. Per-principal capacity is
`RATE_LIMITED` (0x0300), retryable with an optional `retryAfterMillis` no greater than 600,000; the client discards the
connection, resolves credentials again, and opens a fresh TLS connection with a fresh proof. A direct-peer accept
limiter, when explicitly enabled, can close a socket before TLS and therefore emits no `AUTH_ERROR`.

## Streaming, cancellation, and failure semantics

`PUT_OBJECT` and `UPLOAD_PART` stream bytes under both flow-control windows and the process-wide
`security.max_concurrent_uploads` limit (default 128). `security.upload_idle_timeout` defaults to two minutes and
`security.upload_max_duration` to 24 hours per stream. Only successful body reads reset the idle timer; unrelated frames,
PINGs, or activity on another stream cannot extend it. Capacity errors are retryable. A deadline returns
`DEADLINE_EXCEEDED` and removes uncommitted object or part state. A client `CANCEL` stops work and returns `CANCELLED` if
no terminal frame has already been sent. A caller deadline may shorten, never extend, server limits.

Application retries are bounded and operation-aware. Reads and idempotent deletes may be retried. Buffered writes need an
idempotency key and a replayable body; one-shot streaming bodies are not replayed implicitly. A fresh connection is
required after authentication-capacity retry. There is no transparent byte-offset PUT/GET resume; after a conclusive
failure, callers use the committed multipart parts or an explicit idempotent operation.

Errors contain only a stable code, retryable bit, optional bounded retry hint, safe message, and request/audit
correlation. They never contain credentials, tokens, tenant secrets, payloads, filesystem paths, stacks, or peer
certificates. See [errors and retries](/guide/errors-and-retries) for the application-facing policy.

## Capabilities and data behavior

The effective Lockwell server mask advertises buckets, objects, pagination, multipart, versioning, Object Lock, tags,
signed capabilities, trace context, CORS, and webhook notifications. `SSE_C` is intentionally **not** advertised because
the native domain path has no server-enforced SSE-C operation. Use S3 for customer-provided AES-256 keys. The reserved
Admin capability bit and `0x1000`–`0x10ff` operation range are unimplemented and require a distinct authenticated
contract.

The shipping LNW clients preserve ordered duplicate user metadata as a user-owned namespace; typed internal SSE-C and
Object Lock state is separate and cannot be synthesized by metadata names. Object Lock retention and legal hold are
authorized and committed atomically with a new version. Governance bypass is not supported. Checksums, ranges, tags,
version/delete-marker listing, multipart completion/abort/resume discovery, batch delete, CORS, webhook configuration,
and signed GET/PUT capabilities follow the operation registry and negotiated capability bits. Webhook configuration
returns a signing secret once; use a credential-free HTTPS target and HMAC headers, never a token in the URL query.

## Enable a listener

Start with a loopback certificate or a private CA in a non-production environment. The server-side configuration is
under `[native_wire]` in [`examples/lockwell.toml`](https://github.com/RusticStack/lockwell/blob/main/examples/lockwell.toml):

```toml
[native_wire]
enabled = false                 # opt in explicitly
listen_addr = "127.0.0.1:9444"
tls_cert_file = "./certs/lockwell.crt"
tls_key_file = "./certs/lockwell.key"
tls_ca_file = "./certs/lockwell-ca.pem" # required for mTLS
client_auth = "none"            # none | optional-mtls | required-mtls
max_connections = 1024
max_streams_per_connection = 128
handshake_timeout = "10s"
idle_timeout = "2m"
```

For a public bind, use a certificate whose name matches the endpoint and set the client CA policy deliberately. Keep
`enabled = false` while rolling back: drain the listener, wait for admitted streams to finish, and remove the native-wire
client selection. S3 and HTTP-native JSON remain unchanged and no metadata migration is performed.

## Qualified clients and framework boundaries

The repository currently contains these implementation-backed LNW consumers:

| Consumer | Tested runtime floor | Entry point | Boundary |
| --- | --- | --- | --- |
| `@kelphect/sdk-native` 0.1.0 | Node 22+, Bun 1.4+ | `/node`, `/bun`, or root condition | Server-only raw TLS; browser/default imports throw |
| `github.com/RusticStack/lockwell-sdk-go/lockwellwire` | Go 1.27+ | package root | server-only; raw LNW/1 |
| `com.lockwell:lockwell-spring-boot-starter` 0.2.2 | JDK 25, Spring Boot 4.1.1 | `com.lockwell.sdk.springwire.*` | Opt-in starter; separate `--release 25` artifact |

These are source-shipped and test-qualified contracts, not a promise that a package has been published to your registry.
The Go, Node, and Java SDK pages document all three transports: S3, HTTP-native JSON, and each language's LNW/1 client
(`lockwellwire`, the package-root `NativeClient`, `LockwellNativeWireClient`). The Nuxt adapter remains pending its
open source-owner PR; see the [capability index](/reference/sdk-capabilities) for the exact boundary. Do not infer
support for .NET, Rust, PHP, or Ruby from this page until a reviewed, merged, tested source contract exists.

## Rollout checklist

Before enabling LNW for a tenant, reproduce the byte fixtures and malformed-frame tests, exercise auth/replay/downgrade/
scope/Object Lock denials, verify stream cancellation and upload bounds, run the language consumer tests, and record the
exact server/client commit and TLS policy. Keep a tested S3 or HTTP-native mode as an explicitly selected rollback
option, never as an exception handler that silently changes protocol. The [wire reference](/reference/native-wire),
[Bun/Node guide](/sdks/bun-native), [Go SDK](/sdks/go), and [Spring guide](/sdks/java-spring-wire)
link directly to runnable examples and source tests.
