Initial Commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: network-plugin-partition (complete-network-plugins)
|
||||
|
||||
**Package**: `@suaveplan/network-plugin-partition`
|
||||
**Status**: PROPOSED
|
||||
|
||||
> Every requirement below carries a `**Verified by:**` line at authoring time. First canonical spec for this package.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: PartitionDetector identifies split-brain network conditions
|
||||
|
||||
The package SHALL export `PartitionDetector`, `PartitionDetectorConfig`, and `PartitionView`. The detector SHALL emit a `split-brain` view when the observed peer graph splits into two or more disjoint components and SHALL throw `PartitionError(SPLIT_BRAIN_DETECTED)` from any operation that depends on a unified view while the split persists.
|
||||
|
||||
#### Scenario: graph splits into two components
|
||||
|
||||
- **WHEN** the detector observes two disjoint reachability components for at least `confirmationMs`
|
||||
- **THEN** the next `view()` call returns a `PartitionView` with `kind === "split-brain"` and two component sets
|
||||
|
||||
**Verified by:** `src/detector/detector.spec-conformance.test.ts::"detects split-brain when graph splits"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: QuorumResolver picks a winning component under configurable strategy
|
||||
|
||||
The package SHALL export `QuorumResolver`, `QuorumResolverConfig`, and a `QuorumStrategy` union `"size" | "performance" | "age" | "hybrid"`. The resolver SHALL return a single winning component per split, deterministically, given the same inputs. If no component qualifies, the resolver SHALL throw `PartitionError(QUORUM_UNRESOLVED)`.
|
||||
|
||||
#### Scenario: size strategy prefers larger component
|
||||
|
||||
- **WHEN** strategy is `"size"` and components have sizes 5 and 3
|
||||
- **THEN** the resolver returns the 5-node component as the winner
|
||||
|
||||
#### Scenario: no component qualifies
|
||||
|
||||
- **WHEN** no component meets the configured threshold
|
||||
- **THEN** the call throws `PartitionError(QUORUM_UNRESOLVED)`
|
||||
|
||||
**Verified by:** `src/quorum/quorum.spec-conformance.test.ts::"size strategy returns larger component"` AND `src/quorum/quorum.spec-conformance.test.ts::"throws QUORUM_UNRESOLVED when no component qualifies"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: MergeProtocol reconciles divergent component states
|
||||
|
||||
The package SHALL export `MergeProtocol`, `MergeProtocolConfig`, `MergeResult`, and a generic `Reconciler<T>` interface. The protocol SHALL invoke the registered reconciler per state key during a heal event and SHALL throw `PartitionError(MERGE_FAILED)` when the reconciler reports an unresolvable conflict.
|
||||
|
||||
#### Scenario: reconciler reports unresolvable conflict
|
||||
|
||||
- **WHEN** a reconciler returns a conflict indicator for a key during merge
|
||||
- **THEN** the call throws `PartitionError(MERGE_FAILED)` with `context.key` populated
|
||||
|
||||
**Verified by:** `src/merge/merge.spec-conformance.test.ts::"throws MERGE_FAILED on unresolvable conflict"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Error-code registry is frozen and namespaced NET_PART
|
||||
|
||||
`PARTITION_CODES` SHALL be frozen under the `NET_PART` namespace and SHALL include exactly: `SPLIT_BRAIN_DETECTED`, `QUORUM_UNRESOLVED`, `MERGE_FAILED`. Every code SHALL be reachable from a production throw site.
|
||||
|
||||
#### Scenario: registry membership
|
||||
|
||||
- **WHEN** `PARTITION_CODES` is inspected
|
||||
- **THEN** every key maps to a value of the form `"NET_PART.<KEY>"`
|
||||
|
||||
**Verified by:** `src/error-codes.spec-conformance.test.ts::"PARTITION_CODES is frozen and prefixed NET_PART"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: No bare-Error throws in production code
|
||||
|
||||
`src/` SHALL contain zero bare `throw new (Error|TypeError|RangeError|SyntaxError)\(` sites outside test files.
|
||||
|
||||
#### Scenario: source grep returns zero hits
|
||||
|
||||
- **WHEN** the grep is run
|
||||
- **THEN** the output is empty
|
||||
|
||||
**Verified by:** `tests/no-bare-throws.test.ts::"network-plugin-partition 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-partition/README.md`
|
||||
- **THEN** output is `1`
|
||||
|
||||
**Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-partition"`
|
||||
Reference in New Issue
Block a user