# 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 injectable `Rng`; conversion log; per-variant summary stats. - `AnalyticsPlugin` — subscribes to `GameEventEmitter`, accumulates per-session counters, dispatches structured `AnalyticsEvent` to an injectable sink. - `FeatureFlagPlugin` — thin adapter over `@suaveplan/feature-flags` `FlagManager`; per-player evaluation context; rolling evaluation log. - `LoggingPlugin` — subscribes to `GameEventEmitter`, forwards events to a `LoggerLike` sink, retains a bounded ring buffer for inspection. - `PersistencePlugin` — tracks per-session state from the emitter and persists via injectable `StorageLike`; explicit `save`/`load`/`delete`. - `RulesPlugin` — wraps `@suaveplan/rules` `RuleEngine`; three rule slots (move / start / end); rolling evaluation history. - `WorkflowPlugin` — id-keyed `WorkflowEngine` registry; `execute` records status + duration + error; `cancel` defers to engine. ### ADDED error codes (extends `GAME_SERVER.*` registry) - `PLUGIN_BASE_DESTROYED` - `INVALID_PLUGIN_OPTIONS` - `AB_TEST_INVALID_VARIANT` - `AB_TEST_EXPERIMENT_NOT_FOUND` - `PERSISTENCE_SAVE_FAILED` - `PERSISTENCE_LOAD_FAILED` - `WORKFLOW_NOT_FOUND` - `DUPLICATE_WORKFLOW` - `INVALID_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.