Initial Commit
This commit is contained in:
@@ -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"`
|
||||
Reference in New Issue
Block a user