Phase 02: Plugin System - Implementation decisions documented - Phase boundary established
4.4 KiB
4.4 KiB
Phase 2: Plugin System - Context
Gathered: 2026-02-04 Status: Ready for planning
## Phase BoundaryEstablish the plugin architecture that all other features build upon. This includes plugin discovery, manifest parsing, lifecycle management (register, boot, shutdown), dependency resolution, and a type-safe extension API for plugins to extend each other. Components, themes, auth, admin, content, and core plugins all depend on this foundation.
## Implementation DecisionsManifest Format
- Hybrid approach: YAML for metadata, Scala trait for code contracts
- YAML contains: vendor, name, version, description, author, homepage, license, tags, min Scala version, dependencies
- Scala trait contains: lifecycle hooks only (register, boot, shutdown)
- Dependencies: Semver ranges (e.g.,
golem15.blog:^1.2.0) - Soft dependencies: Supported via
optionalDeps— loads after if present, ignored if not - Vendor namespace: Explicitly declared in YAML (
vendor: golem15, name: blog) - Versioning: Standard semver — MAJOR.MINOR.PATCH, major bump = breaking change
- No conflict declarations — handle incompatibilities via dependency constraints
Lifecycle Hooks
- Three phases: register, boot, shutdown (like WinterCMS)
- Execution model: Hybrid — register is sync (pure data), boot/shutdown are async (ZIO effects)
- Boot failures: Graceful degradation — failed plugin disabled, dependents disabled, rest of app runs
- Boot ordering: Sequential by dependency order, then by numeric priority (higher boots first among peers)
- Circular dependencies: Error at discovery time (fail early)
- Enabled flag: Plugins can be disabled via config without removing from directory
- Migrations: Separate CLI command only, not during boot
- Hot reload: Supported in dev mode — file changes trigger plugin reload
- Logging: Minimal by default (errors/warnings only)
- Plugin context: Both PluginContext (simple access) and ZIO environment (advanced DI)
- Health checks: Optional health trait plugins can implement for /health endpoint
- State tracking: Full state machine (registered, booting, running, failed, disabled)
- Enable/disable control: Admin API only, plugins cannot control each other
Extension Mechanics
- Multi-pattern approach (like WinterCMS):
- Events for loose coupling (pub/sub)
- Traits for type-safe contracts
- Registration system for UI extensions (forms, navigation)
- Form/list extensions: Hybrid — simple extensions in YAML, complex logic in code
- Type safety: Compile-time where possible using Scala's type system
- Admin navigation: Both YAML for standard items, code for dynamic/conditional items
- Model extensions: Full API — plugins can add columns and relations to other plugins' models
- Route/controller interception: Middleware-style wrapping (before/after logic)
- Multiple extensions merge: Additive (like WinterCMS) — Plugin A and B can both extend Plugin C, extensions accumulate
- Extension conflicts: Actual conflicts (same field name) error, otherwise merge
- Granularity: Plugin-level only — disable plugin = disable all its extensions
Developer Experience
- Dependency errors: Console message with suggested fix (e.g., "try: install golem15.blog ^1.2.0")
- Plugin doctor: Full diagnostic command — manifests, dependencies, conflicts, health
- Dev mode debugging: Full tracing — verbose logs, timing, dependency graph visualization, event flow tracing
- API documentation: Auto-generated from traits, events, extension points
Claude's Discretion
- Shutdown timeout policy
- Event listener priority ordering
- Runtime error handling patterns (isolated vs propagated)
- Asset injection targeting (global vs page-specific)
- "Make it similar to WinterCMS" — multiple plugins extending the same target, extensions merge additively
- Events, traits, AND registration system — all three patterns available like WinterCMS
- Plugin B can extend Plugin A's backend forms and navigation
- Example: Golem15.Golem extending Blog with AI image generation AND Golem15.SEO extending Blog with SEO fields — both work simultaneously
None — discussion stayed within phase scope
Phase: 02-plugin-system Context gathered: 2026-02-04