94 lines
4.0 KiB
Markdown
94 lines
4.0 KiB
Markdown
# 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.
|