6.4 KiB
OpenSpec Change: network-plugin-qos
- Change ID: network-plugin-qos
- Package:
@suaveplan/network-plugin-qos(new) - Status: PROPOSED
- Date: 2026-05-01
Summary
Implement bandwidth management and quality-of-service (QoS) controls for the mesh. network-plugin-transport-manager provides 5 priority tiers for message routing, but there is no per-mesh bandwidth quota enforcement, no control-plane message prioritization that bypasses normal queues, and no cross-mesh relay bandwidth throttling. This plugin adds the policy layer on top of the transport manager's mechanics.
Why
Current state: network-plugin-webrtc has bufferedAmount backpressure. network-plugin-transport-manager has 5 priority tiers. @suaveplan/rate-limiter exists as a standalone package but is not integrated into the mesh.
What's missing:
- Per-mesh bandwidth quota enforcement
- Message priority classes (control vs data vs bulk) with quota-aware scheduling
- QoS: urgent messages (election, failover) bypass normal queue when mesh is saturated
- Cross-mesh relay bandwidth throttling (prevent Tier 0 host saturation)
Core components
1. BandwidthQuotaEnforcer
Tracks and enforces per-mesh and per-peer bandwidth quotas.
class BandwidthQuotaEnforcer {
constructor(options: {
meshId: string;
meshQuotaBps: number; // bytes per second for entire mesh
peerQuotaBps: number; // bytes per second per peer
relayQuotaBps: number; // bytes per second for cross-mesh relay
windowMs: number; // default 1000
});
recordSend(bytes: number, isRelay: boolean): void;
canSend(bytes: number, isRelay: boolean): boolean;
getMeshUtilization(): number; // 0.0 – 1.0
getPeerUtilization(peerId: string): number;
on(event: "quota:exceeded", handler: (scope: string) => void): void;
}
Uses a sliding window (default 1 second). When quota is exceeded, sends are delayed or rejected based on message priority.
2. MessagePriorityClassifier
Assigns a QoSClass to every message based on its type and payload size.
enum QoSClass {
CONTROL_PLANE = 0, // elections, failover, heartbeats — never dropped
REALTIME = 1, // game state, audio — low latency, may drop
RELIABLE = 2, // file transfers, chat — guaranteed delivery
BULK = 3, // backups, logs — best effort
SCAVENGER = 4, // prefetch, analytics — first to drop
}
class MessagePriorityClassifier {
classify(envelope: MessageEnvelope): QoSClass;
registerRule(type: string, qosClass: QoSClass): void;
registerSizeRule(maxBytes: number, qosClass: QoSClass): void;
}
Default rules:
election:*,failover:*,heartbeat:*→CONTROL_PLANEgame:state,audio:*→REALTIMEchat:*,file:chunk→RELIABLEbackup:*,log:*→BULKprefetch:*,analytics:*→SCAVENGER
3. QoSRouter
Integrates with network-plugin-transport-manager to apply QoS policy.
class QoSRouter {
constructor(options: {
classifier: MessagePriorityClassifier;
enforcer: BandwidthQuotaEnforcer;
transportManager: TransportManager; // from network-plugin-transport-manager
});
send(envelope: MessageEnvelope, targetPeerId: string): Promise<void>;
}
Routing behaviour:
- Classify message →
QoSClass. - If
CONTROL_PLANE→ bypass quota check, send immediately via highest-priority transport. - If mesh quota exceeded:
REALTIME→ drop (application is notified).RELIABLE→ queue with timeout; retry when quota available.BULK/SCAVENGER→ drop or defer to off-peak window.
- If relay quota exceeded:
- Cross-mesh messages are throttled;
SCAVENGERrelay traffic is dropped first.
- Cross-mesh messages are throttled;
4. CongestionMonitor
Monitors mesh congestion and emits alerts.
class CongestionMonitor {
constructor(options: {
enforcer: BandwidthQuotaEnforcer;
alertThreshold: number; // default 0.90
sustainedPeriodMs: number; // default 5000
});
start(): void;
stop(): void;
getCongestionLevel(): "none" | "mild" | "severe" | "critical";
}
Emits qos:congestion events on the NetworkBus with level and recommended actions (e.g. "pause prefetch", "reduce broadcast frequency").
Error codes
const QOS_CODES = defineCodes("QOS", [
"QUOTA_EXCEEDED",
"RELAY_QUOTA_EXCEEDED",
"MESSAGE_DROPPED",
"CONGESTION_ALERT",
"INVALID_QOS_CLASS",
] as const);
QosError extends SuaveplanError<QosErrorCode>.
Dependencies
- Consumes:
@suaveplan/network(NetworkNode,NetworkBus,MessageEnvelope),@suaveplan/network-plugin-transport-manager(TransportManager, priority routing),@suaveplan/network-plugin-relay(cross-mesh relay paths),@suaveplan/error,@suaveplan/types,@opentelemetry/api. - Blocked on:
network-core(shipped),network-plugin-transport-manager.
Verification approach
src/enforcer/enforcer.spec-conformance.test.ts— pins sliding window, quota enforcement, utilization math.src/classifier/classifier.spec-conformance.test.ts— pins default rules, custom rules, size-based rules.src/router/qos-router.spec-conformance.test.ts— pins CONTROL_PLANE bypass, drop/queue/defer logic.src/monitor/congestion-monitor.spec-conformance.test.ts— pins alert thresholds, sustained period, level calculation.- 100/100/100/100 Istanbul coverage.
Conformance requirements (proposed)
NET-91—BandwidthQuotaEnforcertracks per-mesh, per-peer, and per-relay bandwidth using a sliding window.NET-92—MessagePriorityClassifierassignsQoSClassbased on message type and size.NET-93—CONTROL_PLANEmessages bypass quota checks and are sent immediately.NET-94—REALTIMEmessages are dropped when mesh quota is exceeded.NET-95—RELIABLEmessages are queued with timeout when mesh quota is exceeded.NET-96—BULKandSCAVENGERmessages are dropped or deferred when mesh quota is exceeded.NET-97— Cross-mesh relay traffic is throttled independently;SCAVENGERrelay traffic is dropped first.NET-98—CongestionMonitoremitsqos:congestionevents when utilization exceedsalertThresholdforsustainedPeriodMs.
Out of scope
- Deep packet inspection → v2; v1 uses message type and size only.
- Per-application QoS → v2; v1 is mesh-wide.
- Traffic shaping via token bucket →
@suaveplan/rate-limitermay be integrated in v2; v1 uses sliding windows.