4.0 KiB
Proposal — game-server plugins (Wave C-1)
Why
The PluginManager shipped in Wave B exposes the EnginePlugin lifecycle
contract but ships no concrete plugins. Wave C-1 fills that gap with seven
production-grade plugins covering A/B testing, analytics, feature flags,
logging, persistence, rules, and workflows. All seven plugins extend a new
shared BasePlugin abstract base that implements the EnginePlugin
lifecycle template-method style.
The plugins are universal-tier (zero browser / React deps). External
integrations are routed through structural-type contracts from
@suaveplan/types (LoggerLike, StorageLike, Clock, IdGenerator,
Rng) so the package keeps its lean dep footprint.
What changes
ADDED BasePlugin
Abstract base for game-server plugins. Implements the EnginePlugin
contract (onInstall / onUninstall / onEnable / onDisable) and
forwards to protected template-method hooks. Tracks lifecycle state
(created → installed → enabled → disabled → destroyed) and rejects any
hook after destruction.
ADDED concrete plugins
ABTestPlugin— weighted, deterministic variant assignment via injectableRng; conversion log; per-variant summary stats.AnalyticsPlugin— subscribes toGameEventEmitter, accumulates per-session counters, dispatches structuredAnalyticsEventto an injectable sink.FeatureFlagPlugin— thin adapter over@suaveplan/feature-flagsFlagManager; per-player evaluation context; rolling evaluation log.LoggingPlugin— subscribes toGameEventEmitter, forwards events to aLoggerLikesink, retains a bounded ring buffer for inspection.PersistencePlugin— tracks per-session state from the emitter and persists via injectableStorageLike; explicitsave/load/delete.RulesPlugin— wraps@suaveplan/rulesRuleEngine; three rule slots (move / start / end); rolling evaluation history.WorkflowPlugin— id-keyedWorkflowEngineregistry;executerecords status + duration + error;canceldefers to engine.
ADDED error codes (extends GAME_SERVER.* registry)
PLUGIN_BASE_DESTROYEDINVALID_PLUGIN_OPTIONSAB_TEST_INVALID_VARIANTAB_TEST_EXPERIMENT_NOT_FOUNDPERSISTENCE_SAVE_FAILEDPERSISTENCE_LOAD_FAILEDWORKFLOW_NOT_FOUNDDUPLICATE_WORKFLOWINVALID_RULE_CONTEXT
ADDED dependencies
@suaveplan/feature-flags(workspace:^)@suaveplan/rules(workspace:^)@suaveplan/workflow(workspace:^)
Subpath exports
Each plugin module gets its own subpath:
./plugins/base-plugin./plugins/ab-test-plugin./plugins/analytics-plugin./plugins/feature-flag-plugin./plugins/logging-plugin./plugins/persistence-plugin./plugins/rules-plugin./plugins/workflow-plugin
Source mapping
| Requirement | Upstream | Notes |
|---|---|---|
| BasePlugin lifecycle | BasePlugin.ts (1-50) |
Adapted to genesis EnginePlugin contract; tracks state machine |
| AnalyticsPlugin per-session counters | AnalyticsPlugin.ts (35-280) |
Sink-based dispatch instead of OTel coupling |
| ABTestPlugin variant bucketing | ABTestPlugin.ts (28-190) |
Self-contained — no @suaveplan/ab-testing dep |
| FeatureFlagPlugin evaluation | FeatureFlagPlugin.ts (30-160) |
Wraps @suaveplan/feature-flags FlagManager |
| LoggingPlugin event forwarding | LoggingPlugin.ts (35-430) |
Bounded ring buffer; granular toggles |
| PersistencePlugin save/load | PersistencePlugin.ts (30-380) |
Zod-validated load; StorageLike injection |
| RulesPlugin evaluation | RulesPlugin.ts (28-195) |
Wraps @suaveplan/rules RuleEngine |
| WorkflowPlugin orchestration | WorkflowPlugin.ts (35-210) |
Id-keyed registry; history; cancel |
Scope guard
This change does NOT touch src/core/, src/engine/, src/state/,
src/network/, src/matchmaking/, src/performance/, src/types/, or
src/observability/. src/index.ts is also untouched — orchestrator
consolidation handles the unified barrel.