Initial Commit
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: network-plugin-topology (complete-network-plugins)
|
||||
|
||||
**Package**: `@suaveplan/network-plugin-topology`
|
||||
**Status**: PROPOSED
|
||||
|
||||
> Every requirement below carries a `**Verified by:**` line at authoring time.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: TopologyPlugin conforms to NetworkPlugin lifecycle
|
||||
|
||||
The package SHALL export `TopologyPlugin implements NetworkPlugin` and `TopologyPluginConfig`. The plugin SHALL manage peer-tier assignment and group membership on install, and tear down assigners and buses on uninstall.
|
||||
|
||||
#### Scenario: install / uninstall lifecycle
|
||||
|
||||
- **WHEN** a host calls install then uninstall
|
||||
- **THEN** the plugin reaches `INSTALLED` then `UNINSTALLED` and releases all timers
|
||||
|
||||
**Verified by:** `src/plugin/topology-plugin.spec-conformance.test.ts::"install / uninstall lifecycle is clean"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: LatencyAssigner buckets peers by measured latency
|
||||
|
||||
The package SHALL export `LatencyAssigner`, `LatencyAssignerConfig`, `LatencyBucket`, and `LatencyBus`. The assigner SHALL bucket peers into named latency tiers based on a configurable bucket schedule and SHALL emit bucket-change events on the `LatencyBus`.
|
||||
|
||||
#### Scenario: peer moves between buckets on RTT change
|
||||
|
||||
- **WHEN** a peer's measured RTT crosses a bucket boundary
|
||||
- **THEN** the assigner emits a `bucket-change` event on the bus with the old and new bucket
|
||||
|
||||
**Verified by:** `src/latency/latency-assigner.spec-conformance.test.ts::"emits bucket-change when RTT crosses boundary"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: LatencyAssigner validates config with typed errors
|
||||
|
||||
`LatencyAssigner` SHALL validate its config at construction time and throw `NetworkTopoError` with `code === "NET_TOPO.INVALID_LATENCY_CONFIG"` whenever the bucket schedule is empty, non-monotonic, or contains a non-finite boundary. The class SHALL NOT throw bare `Error`.
|
||||
|
||||
#### Scenario: empty bucket schedule
|
||||
|
||||
- **WHEN** `new LatencyAssigner({ buckets: [] })` is called
|
||||
- **THEN** the call throws `NetworkTopoError` with `code === "NET_TOPO.INVALID_LATENCY_CONFIG"` and `context.reason === "empty-buckets"`
|
||||
|
||||
#### Scenario: non-monotonic bucket boundaries
|
||||
|
||||
- **WHEN** the bucket schedule is `[100, 50, 200]`
|
||||
- **THEN** the call throws `NetworkTopoError` with `code === "NET_TOPO.INVALID_LATENCY_CONFIG"` and `context.reason === "non-monotonic"`
|
||||
|
||||
**Verified by:** `src/latency/latency-assigner.spec-conformance.test.ts::"throws INVALID_LATENCY_CONFIG on empty buckets"` AND `src/latency/latency-assigner.spec-conformance.test.ts::"throws INVALID_LATENCY_CONFIG on non-monotonic schedule"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: GroupManager exposes a typed group abstraction
|
||||
|
||||
The package SHALL export `GroupManager`, `Group`, `GroupBus`, and `GroupManagerConfig`. The manager SHALL track named groups of peers with add / remove operations and SHALL emit membership-change events on the `GroupBus`.
|
||||
|
||||
#### Scenario: add/remove emits membership events
|
||||
|
||||
- **WHEN** `groupManager.add(groupId, peerId)` is called for a peer not yet in the group
|
||||
- **THEN** a `member-added` event fires on the bus with `{ groupId, peerId }`
|
||||
|
||||
**Verified by:** `src/group/group-manager.spec-conformance.test.ts::"emits member-added on join"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Error-code registry is frozen and namespaced NET_TOPO
|
||||
|
||||
`NETWORK_TOPO_CODES` SHALL be frozen under the `NET_TOPO` namespace and SHALL include at minimum: `INVALID_TIER`, `PEER_NOT_FOUND`, `ALREADY_AT_TIER`, and the new `INVALID_LATENCY_CONFIG`. Every code SHALL be reachable from a production throw site.
|
||||
|
||||
#### Scenario: registry contains INVALID_LATENCY_CONFIG
|
||||
|
||||
- **WHEN** `NETWORK_TOPO_CODES` is inspected
|
||||
- **THEN** `INVALID_LATENCY_CONFIG` maps to `"NET_TOPO.INVALID_LATENCY_CONFIG"`
|
||||
|
||||
**Verified by:** `src/error-codes.spec-conformance.test.ts::"NETWORK_TOPO_CODES includes INVALID_LATENCY_CONFIG"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: No bare-Error throws in production code
|
||||
|
||||
The package SHALL NOT contain any `throw new (Error|TypeError|RangeError|SyntaxError)\(` site inside `src/` outside test files. Every production failure throws `NetworkTopoError` or a transitive `SuaveplanError` subclass.
|
||||
|
||||
#### Scenario: source grep returns zero hits
|
||||
|
||||
- **WHEN** `grep -rnE "throw new (Error|TypeError|RangeError|SyntaxError)\(" packages/network/network-plugin-topology/src/ --include="*.ts"` excluding tests
|
||||
- **THEN** the output is empty
|
||||
|
||||
**Verified by:** `tests/no-bare-throws.test.ts::"network-plugin-topology src/ has no bare Error throws"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: README is auto-docs idempotent
|
||||
|
||||
The package `README.md` SHALL contain exactly one balanced auto-docs block; the generator SHALL produce a byte-identical file on a second run.
|
||||
|
||||
#### Scenario: marker count is exactly one
|
||||
|
||||
- **WHEN** `grep -c "begin:auto-docs" packages/network/network-plugin-topology/README.md`
|
||||
- **THEN** output is `1`
|
||||
|
||||
**Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-topology"`
|
||||
Reference in New Issue
Block a user