feat: 99% complete migration to new state structs to get away from God-Config struct; i.e. AppConfig, AppState, and RequestContext

This commit is contained in:
2026-04-19 17:05:27 -06:00
parent ff3419a714
commit c057249e52
90 changed files with 18983 additions and 3448 deletions
@@ -0,0 +1,105 @@
# Phase 1 Step 16 Notes: Config → AppConfig Migration Cleanup
**Date**: 2026-04-19
**Status**: PENDING (cleanup task)
## Overview
Complete the migration of mutations from Config to AppConfig/AppState so that Config becomes a pure POJO (serde serialization/deserialization only).
## Problem
The current startup flow mutates `Config` during init, then calls `to_app_config()` which **only copies serialized fields**, losing all the runtime mutations:
```
YAML → Config (mutated during init)
cfg.to_app_config() ← COPIES ONLY, loses mutations
```
### Mutations happening in Config::init
These methods mutate Config and should be migrated to AppConfig:
| Method | Location | What It Does |
|-------|----------|-------------|
| `load_envs()` | `mod.rs:387` | Env var overrides into Config fields |
| `set_wrap(&wrap)?` | `mod.rs:390` | Parse wrap string into Config.wrap |
| `load_functions()` | `mod.rs:393` | Load tool functions into Config.functions |
| `setup_model()` | `mod.rs:398` | Resolve model name → Model |
| `load_mcp_servers()` | `mod.rs:395` | Start MCP servers into Config.mcp_registry |
| `setup_document_loaders()` | `mod.rs:399` | Load document loaders |
| `setup_user_agent()` | `mod.rs:400` | Set user_agent to "auto" |
### Other Config Methods Still In Use
| Method | Location | Used By |
|--------|----------|---------|
| `set_model(&model_id)` | `mod.rs:457-466` | Runtime (role-like mutators) |
| `vault_password_file()` | `mod.rs:411-419` | `vault/mod.rs:40` |
| `sessions_dir()` | `mod.rs:421-429` | Session management |
| `role_like_mut()` | `mod.rs:431-441` | Role/session/agent mutation |
| `set_wrap(&str)` | `mod.rs:443-455` | Runtime wrap setting |
## Solution
**Option A (Quick)**: Move mutations after the bridge in `main.rs`:
```rust
// main.rs
let cfg = Config::init(...).await?;
let app_config = Arc::new(cfg.to_app_config()); // Step 1: copy serialized
// Step 2: apply mutations to AppConfig
app_config.load_envs();
app_config.set_wrap(&wrap)?;
app_config.setup_model()?; // May need refactored
// Step 3: build AppState
let app_state = Arc::new(AppState {
config: app_config,
vault: cfg.vault.clone(),
// ... other fields
});
// Step 4: build RequestContext (runtime only, no config logic)
let ctx = cfg.to_request_context(app_state);
```
**Option B (Proper)**: Remove Config entirely from startup flow - build AppConfig directly from YAML.
## Duplicated Code to Clean Up
After migration, these duplicated methods can be removed from AppConfig:
| Duplicated | Config Location | AppConfig Location |
|-----------|-----------------|-------------------|
| `load_envs()` | `mod.rs:582-722` | `app_config.rs:283-427` |
| `set_wrap()` | `mod.rs:443-455` | `app_config.rs:247-259` |
| `setup_document_loaders()` | `mod.rs:782-789` | `app_config.rs:262-269` |
| `setup_user_agent()` | `mod.rs:791-799` | `app_config.rs:272-280` |
| Default impls | `mod.rs:232-311` | `app_config.rs:94-149` |
## Target State
After Step 16:
- [ ] Config only has serde fields + Deserialization (no init logic)
- [ ] AppConfig receives all runtime mutations
- [ ] AppState built from AppConfig + Vault
- [ ] RequestContext built from AppState + runtime state
- [ ] Duplicated methods removed from AppConfig (or retained if needed)
- [ ] Bridge simplified to just field copying
## Files to Modify
- `src/config/mod.rs` - Remove init mutations, keep only serde
- `src/config/app_config.rs` - Enable mutations, remove duplication
- `src/main.rs` - Move bridge after mutations
- `src/config/bridge.rs` - Simplify or remove
## Notes
- This cleanup enables proper REST API behavior
- Each HTTP request should build fresh RequestContext from AppConfig
- AppConfig should reflect actual runtime configuration