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,117 @@
<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: network-plugin-circuit-breaker (complete-network-plugins)
**Package**: `@suaveplan/network-plugin-circuit-breaker`
**Status**: PROPOSED
> Every requirement below carries a `**Verified by:**` line at authoring time. First canonical spec for this package.
## ADDED Requirements
### Requirement: MeshCircuitBreaker implements three-state breaker FSM
The package SHALL export `MeshCircuitBreaker`, `MeshCircuitBreakerOptions`, a `CircuitBreakerState` union `"CLOSED" | "OPEN" | "HALF_OPEN"`, and a `StateChangeListener` type. State transitions SHALL follow CLOSED→OPEN on failure threshold, OPEN→HALF_OPEN after cooldown, HALF_OPEN→CLOSED on success or HALF_OPEN→OPEN on failure. Illegal transitions SHALL throw `CircuitBreakerError(INVALID_TRANSITION)`.
#### Scenario: failure threshold opens the breaker
- **WHEN** the configured number of consecutive failures is recorded
- **THEN** the breaker transitions to `OPEN` and notifies registered `StateChangeListener`s
#### Scenario: cooldown elapsed transitions to HALF_OPEN
- **WHEN** the breaker is `OPEN` and `cooldownMs` has elapsed
- **THEN** the next probe transitions to `HALF_OPEN`
**Verified by:** `src/breaker/breaker.spec-conformance.test.ts::"opens after failure threshold"` AND `src/breaker/breaker.spec-conformance.test.ts::"transitions to HALF_OPEN after cooldown"`
---
### Requirement: Calls through an open path throw PATH_OPEN
The breaker SHALL throw `CircuitBreakerError(PATH_OPEN)` when a call is attempted through a path that is in the `OPEN` state.
#### Scenario: call through open path
- **WHEN** `breaker.run(fn)` is called while state is `OPEN`
- **THEN** the call throws `CircuitBreakerError` with `code === "CB.PATH_OPEN"` and `fn` is NOT invoked
**Verified by:** `src/breaker/breaker.spec-conformance.test.ts::"throws PATH_OPEN when path is open"`
---
### Requirement: createCircuitBreakerMiddleware integrates with the relay path
The package SHALL export `createCircuitBreakerMiddleware`, `CircuitBreakerMiddlewareOptions`, `RelayNext`, and a `PathIdBuilder` type. The middleware SHALL wrap each relay call in the breaker associated with the resolved path id.
#### Scenario: middleware short-circuits an open path
- **WHEN** the breaker for the resolved path id is `OPEN` and the middleware is invoked
- **THEN** `next()` is NOT awaited and the middleware throws `CircuitBreakerError(PATH_OPEN)`
**Verified by:** `src/middleware/middleware.spec-conformance.test.ts::"short-circuits open path"`
---
### Requirement: HalfOpenProbe scouts recovery before reopening the path
The package SHALL export `HalfOpenProbe`, `HalfOpenProbeOptions`, and a `ProbeSender` type. The probe SHALL send a minimal canary message via the `ProbeSender` and SHALL transition the breaker to `CLOSED` only when the canary succeeds.
#### Scenario: canary succeeds
- **WHEN** the half-open probe runs and the `ProbeSender` resolves
- **THEN** the breaker transitions to `CLOSED`
**Verified by:** `src/probe/probe.spec-conformance.test.ts::"closes breaker on canary success"`
---
### Requirement: CircuitBreakerRegistry manages per-path breaker instances
The package SHALL export `CircuitBreakerRegistry` and `CircuitBreakerRegistryOptions`. The registry SHALL lazily create a breaker per path id and SHALL surface stable lookup semantics.
#### Scenario: registry returns the same instance for the same path id
- **WHEN** `registry.for(pathId)` is called twice with the same id
- **THEN** the same `MeshCircuitBreaker` instance is returned both times
**Verified by:** `src/registry/registry.spec-conformance.test.ts::"returns same instance for same path id"`
---
### Requirement: Error-code registry is frozen and namespaced CB
`CB_CODES` SHALL be frozen under the `CB` namespace and SHALL include exactly: `PATH_OPEN`, `INVALID_TRANSITION`. Every code SHALL be reachable from a production throw site.
#### Scenario: registry membership
- **WHEN** `CB_CODES` is inspected
- **THEN** every key maps to a value of the form `"CB.<KEY>"`
**Verified by:** `src/error-codes.spec-conformance.test.ts::"CB_CODES is frozen and prefixed CB"`
---
### 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-circuit-breaker 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-circuit-breaker/README.md`
- **THEN** output is `1`
**Verified by:** `scripts/generate-package-module-tree.test.ts::"README regen is idempotent for network-plugin-circuit-breaker"`