# Architecture: V3 Schema Refactor
## Design Principles
1. **Tool Separation**: Docker operations (flux) separated from SSH operations (scout)
2. **O(1) Validation**: Discriminated unions for constant-time schema validation
3. **Auto-Generated Help**: Schema introspection for documentation
4. **No Backward Compatibility**: Clean break from V2 unified tool
5. **Dependency Injection**: Services resolved through `ServiceContainer` (no global singletons)
## Schema Architecture
### Flux Tool
Uses **nested discriminator** pattern:
- Top-level routing by `action`
- Per-action `z.discriminatedUnion("subaction", [...])`
- 43 supported operations across 5 action groups (including help)
### Scout Tool
Uses **primary discriminator** pattern:
- Discriminator key: `action`
- Nested discriminators for `zfs` and `logs` actions
- 12 top-level actions, 19 total discriminator keys
## Dependency Injection Architecture
`ServiceContainer` in `src/services/container.ts` is the composition root for
runtime services.
Core behaviors:
- Lazy initialization of services on first access
- Explicit getter/setter methods for test overrides
- Lifecycle management (`CREATED` → `INITIALIZING` → `READY` → `SHUTTING_DOWN` → `SHUTDOWN`)
- Dependency wiring (including compose discovery circular-dependency break via `setDiscovery`)
Key dependency chain:
- `SSHConnectionPoolImpl` → `SSHService` → `ComposeService`
- `SSHService` → `FileService`
- `ComposeService` + cache/scanner → `ComposeDiscovery`
- `DockerService`, `EventEmitter`, repositories/caches managed by container
Practical implications:
- Handlers/tools should request services via `ServiceContainer` getters.
- Tests should inject mocks via `set*` methods instead of patching globals.
- Shutdown flows should call container cleanup, not per-service ad hoc teardown.
## HTTP Middleware And Rate Limiting
In HTTP transport mode (`src/index.ts`), request handling is layered:
1. `requestIdMiddleware`
2. JSON body parsing
3. `/health` route with `createHealthRateLimiter()`
4. `/mcp` route with `csrfProtectionMiddleware` then `authMiddleware`
5. Error middleware (`errorHandler`, `fallbackErrorHandler`)
Current rate-limiting scope:
- `/health`: rate-limited (30 requests per IP per 60s)
- `/mcp`: no dedicated rate limiter in current implementation
Implementation and tests:
- `src/health-rate-limiter.ts`
- `src/health-rate-limiter.test.ts`
- `src/middleware/error-handler.integration.test.ts`
## File Structure
```
src/
├── schemas/
│ ├── common.ts # Shared schemas
│ ├── flux/
│ │ ├── index.ts # Flux union of action schemas
│ │ ├── container.ts # Container schemas (14)
│ │ ├── compose.ts # Compose schemas (10)
│ │ ├── docker.ts # Docker schemas (9)
│ │ └── host.ts # Host schemas (9)
│ └── scout/
│ ├── index.ts # Scout discriminated union
│ ├── simple.ts # Simple actions (9)
│ ├── zfs.ts # ZFS nested discriminator (3)
│ └── logs.ts # Logs nested discriminator (4)
├── tools/
│ ├── flux.ts # Flux handler + help
│ ├── scout.ts # Scout handler + help
│ └── handlers/ # Action-specific handlers + shared base utilities
└── utils/
└── help.ts # Help introspection with unwrapping
```
## Performance
### Validation
- **Before (union)**: O(n) worst-case (try each schema)
- **After (discriminated union)**: O(1) (direct lookup)
### Help Generation
- Uses Zod schema introspection
- Extracts types, descriptions, defaults from schema metadata
- No manual documentation maintenance
## Breaking Changes
**V3 is a complete rewrite:**
- Unified `homelab` tool deleted entirely
- Two new tools: `flux` (Docker) and `scout` (SSH)
- `container:unpause` → `container:resume`
- Scout actions restructured with nested discriminators
- MCP SDK 1.25.1 API (`registerTool` instead of `addTool`)