Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: network-plugin-protocol (complete-network-plugins)
**Package**: `@suaveplan/network-plugin-protocol`
**Status**: PROPOSED
> Every requirement below carries a `**Verified by:**` line at authoring time.
## ADDED Requirements
### Requirement: BinaryProtocol header carries version and routing metadata
The package SHALL export a `BinaryProtocol` class together with the constants `PROTOCOL_VERSION` and `HEADER_SIZE` defining the fixed-width header used on the wire. Headers SHALL be opaque to consumers and addressed only through the encoder / decoder pair.
#### Scenario: header round-trips through encoder / decoder
- **WHEN** a `MessageEnvelope` is encoded with `MessageEncoder` and decoded with `MessageDecoder`
- **THEN** the round-trip produces a structurally-equal envelope and the decoded header carries the same `PROTOCOL_VERSION` constant
**Verified by:** `src/protocol/protocol.spec-conformance.test.ts::"BinaryProtocol round-trips an envelope"`
---
### Requirement: MessageDecoder throws structured errors on malformed input
`MessageDecoder` SHALL throw `NetworkProtoError` (subclass of `SuaveplanError`) with `code === "NET_PROTO.DESERIALIZATION_FAILED"` and a `context` payload identifying the failure cause whenever the input buffer is too short, the header is invalid, or deserialization fails. The package SHALL NOT throw bare `Error` / `TypeError` / `RangeError` from any production code path.
#### Scenario: incomplete buffer raises typed error
- **WHEN** `MessageDecoder.decode` is called with a buffer whose length is less than `HEADER_SIZE`
- **THEN** the call throws `NetworkProtoError` with `code === "NET_PROTO.DESERIALIZATION_FAILED"` and `context.reason === "incomplete-message"`
**Verified by:** `src/decoder/decoder.spec-conformance.test.ts::"throws NetworkProtoError on incomplete buffer"`
---
### Requirement: ProtocolPipeline composes ordered stages with backpressure
The package SHALL export `ProtocolPipeline` with a `PipelineStage` interface that consumers register in order. The pipeline SHALL invoke stages in registration order on encode and in reverse on decode.
#### Scenario: stages run in registration order on encode and reverse on decode
- **WHEN** stages `A`, `B` are registered in that order and a message flows through encode-then-decode
- **THEN** the observed call sequence is `A.encode`, `B.encode`, `B.decode`, `A.decode`
**Verified by:** `src/pipeline/pipeline.spec-conformance.test.ts::"runs stages in declared order"`
---
### Requirement: PriorityMessageQueue rejects overflow with QUEUE_FULL
The package SHALL export `PriorityMessageQueue` and `MessageBatcher`. The queue SHALL throw `NetworkProtoError(QUEUE_FULL)` when an insert would exceed the configured capacity.
#### Scenario: insert beyond capacity raises QUEUE_FULL
- **WHEN** the queue holds `capacity` messages and a further `enqueue` is attempted
- **THEN** the call throws `NetworkProtoError` with `code === "NET_PROTO.QUEUE_FULL"`
**Verified by:** `src/queue/queue.spec-conformance.test.ts::"throws QUEUE_FULL on overflow"`
---
### Requirement: ProtocolPlugin conforms to NetworkPlugin lifecycle
The package SHALL export `ProtocolPlugin implements NetworkPlugin` and a `ProtocolPluginOptions` type. The plugin SHALL register itself against the host on `install`, register pluggable serializers via the options object, and tear down state on `uninstall`.
#### Scenario: install registers the plugin and exposes encoder/decoder via the host
- **WHEN** a host calls `await plugin.install(host)` followed by `await plugin.uninstall(host)`
- **THEN** the plugin enters `INSTALLED` then `UNINSTALLED` lifecycle states and does not leak resources
**Verified by:** `src/protocol/protocol-plugin.spec-conformance.test.ts::"install / uninstall lifecycle is clean"`
---
### Requirement: Error-code registry is frozen and namespaced NET_PROTO
`NETWORK_PROTO_CODES` SHALL be a frozen registry under the `NET_PROTO` namespace exporting at minimum: `INVALID_HEADER`, `PAYLOAD_TOO_LARGE`, `SERIALIZATION_FAILED`, `DESERIALIZATION_FAILED`, `UNSUPPORTED_SERIALIZER`, `QUEUE_FULL`, `TTL_EXPIRED`, `LOOP_DETECTED`, `DUPLICATE_MESSAGE`. Every code SHALL be reachable from at least one production throw site.
#### Scenario: registry membership
- **WHEN** `NETWORK_PROTO_CODES` is inspected
- **THEN** every key maps to a value of the form `"NET_PROTO.<KEY>"`
**Verified by:** `src/error-codes.spec-conformance.test.ts::"NETWORK_PROTO_CODES is frozen and prefixed NET_PROTO"`
---
### Requirement: No bare-Error throws in production code
The package SHALL NOT contain any `throw new Error(...)`, `throw new TypeError(...)`, `throw new RangeError(...)`, or `throw new SyntaxError(...)` statement inside `src/` (excluding `*.test.ts` and `*.spec-conformance.test.ts`). Every production failure path SHALL throw `NetworkProtoError` (or a `SuaveplanError` subclass from a transitive dependency).
#### Scenario: source grep returns zero hits
- **WHEN** `grep -rnE "throw new (Error|TypeError|RangeError|SyntaxError)\(" packages/network/network-plugin-protocol/src/ --include="*.ts"` is run, excluding `*.test.ts`
- **THEN** the output is empty
**Verified by:** `tests/no-bare-throws.test.ts::"network-plugin-protocol src/ has no bare Error throws"`
---
### Requirement: README is auto-docs idempotent
The package `README.md` SHALL contain exactly one balanced `<!-- begin:auto-docs --> … <!-- end:auto-docs -->` block. Re-running `bun scripts/generate-package-module-tree.ts` SHALL produce a byte-identical file.
#### Scenario: marker count is exactly one
- **WHEN** `grep -c "begin:auto-docs" packages/network/network-plugin-protocol/README.md` is run
- **THEN** the output is `1`
**Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-protocol"`