botserver/TASKS.md

153 lines
7.2 KiB
Markdown
Raw Normal View History

2026-01-22 13:57:40 -03:00
# Deep Feature Gating Plan: Schema & Migrations
## Objective
Reduce binary size and runtime overhead by strictly feature-gating Database Schema (`schema.rs`) and Migrations.
The goal is that a "minimal" build (chat-only) should:
1. NOT compile code for `tasks`, `mail`, `calendar`, etc. tables.
2. NOT run database migrations for those features (preventing unused tables in DB).
3. NOT fail compilation due to missing table definitions in `joinable!` macros.
---
## 🚀 Phase 1: Split Diesel Schema (The Hard Part)
The current `schema.rs` is monolithic (3000+ lines).
Diesel requires `joinable!` and `allow_tables_to_appear_in_same_query!` macros to know about relationship graphs.
### **1.1 Analysis & grouping**
Identify which tables belong to which feature and strictly define their relationships.
- **Core**: `users`, `bots`, `sessions`, `organizations`, `rbac_*`
- **Tasks**: `tasks`, `task_comments` (links to `users`, `projects`)
- **Mail**: `email_*` (links to `users`)
- **Drive**: (Uses S3, but maybe metadata tables?)
- **People/CRM**: `crm_*` (links to `users`, `organizations`)
### **1.2 Create Modular Schema Files**
Instead of one file, we will separate them and use `mod.rs` to aggregate.
- `src/core/shared/schema/mod.rs` (Aggregator)
- `src/core/shared/schema/core.rs` (Base tables)
- `src/core/shared/schema/tasks.rs` (Gated `#[cfg(feature="tasks")]`)
- `src/core/shared/schema/mail.rs` (Gated `#[cfg(feature="mail")]`)
...etc.
### **1.3 Solve the `allow_tables_to_appear_in_same_query!` Problem**
The single massive macro prevents gating.
**Solution**: Break the "Universe" assumption.
1. Define a `core_tables!` macro.
2. Define `task_tables!` macro (gated).
3. We might lose the ability to write arbitrary joins between *any* two tables if they are in different clusters, unless we explicitly define `joinable!` in the aggregator.
4. **Strategy**:
- Keep `joinable!` definitions relative to the feature.
- If `TableA` (Core) joins `TableB` (Tasks), the `joinable!` must be gated by `tasks`.
- The `allow_tables...` output must be constructed dynamically or strict subsets defined.
### **1.4 Comprehensive Feature Mapping**
Based on `Cargo.toml`, we need to map all optional features to their schema requirements.
| Feature | Tables (Prefix/Name) | Migrations |
|---------|-----------------------|------------|
| (core) | `users`, `bots`, `sessions`, `orgs`, `rbac_*`, `system_automations`, `bot_memories`, `kb_*` | `migrations/core/` |
| `tasks` | `tasks`, `task_comments` | `migrations/tasks/` |
| `calendar`| `calendars`, `calendar_events`, `calendar_*` | `migrations/calendar/` |
| `mail` | `email_*`, `distribution_lists`, `global_email_signatures` | `migrations/mail/` |
| `people` | `crm_contacts`, `crm_accounts`, `crm_leads`, `crm_opportunities`, `crm_activities`, `crm_pipeline_*`, `people_*` | `migrations/people/` |
| `compliance`| `compliance_*`, `legal_*`, `cookie_consents`, `data_*` | `migrations/compliance/` |
| `meet` | `meet_*`, `meeting_*`, `whiteboard_*` | `migrations/meet/` |
| `attendant`| `attendant_*` | `migrations/attendant/` |
| `analytics`| `dashboards`, `dashboard_*` | `migrations/analytics/` |
| `drive` | (No direct tables? Check `files` or `drive_*`?) | `migrations/drive/` |
| `billing` | `billing_*`, `products`, `services`, `price_*`, `inventory_*` (See note) | `migrations/billing/` |
| `social` | `social_*` | `migrations/social/` |
| `canvas` | `canvases`, `canvas_*` | `migrations/canvas/` |
| `workspaces`| `workspaces`, `workspace_*` | `migrations/workspaces/` |
| `research` | `research_*` | `migrations/research/` |
| `goals` | `okr_*` | `migrations/goals/` |
| `feedback` | `support_tickets`, `ticket_*` | `migrations/tickets/` |
**Note**: `billing` and `tickets` are currently ungated modules in `main.rs`. We should create features or group them. For now, assume they are part of admin/core or need gating.
---
## 🚀 Phase 2: Feature-Gated Migrations
Currently, `embed_migrations!("migrations")` embeds everything.
### **2.1 Split Migration Directories**
Refactor the flat `migrations/` folder into feature-specific directories (requires custom runner logic or Diesel configuration trickery).
Alternately (easier code-wise):
- Keep flat structure but **edit the migration SQL files** to be conditional? No, SQL doesn't support `#[cfg]`.
- **Better Approach**: Use multiple `embed_migrations!` calls.
- `migrations/core/` -> Always run.
- `migrations/tasks/` -> Run if `tasks` feature on.
- `migrations/mail/` -> Run if `mail` feature on.
**Action Plan**:
1. Organize `migrations/` into subdirectories: `core/`, `tasks/`, `mail/`, `people/`.
2. Update `utils.rs` migration logic:
```rust
pub fn run_migrations(conn: &mut PgConnection) {
// Core
const CORE: EmbeddedMigrations = embed_migrations!("migrations/core");
conn.run_pending_migrations(CORE).unwrap();
#[cfg(feature = "tasks")] {
const TASKS: EmbeddedMigrations = embed_migrations!("migrations/tasks");
conn.run_pending_migrations(TASKS).unwrap();
}
// ...
}
```
### **2.2 Verify Migration Dependencies**
Ensure that `tasks` migrations (which might foreign-key to `users`) only run *after* `core` migrations are applied.
---
## 🚀 Phase 3: Fix Dependent Code (Strict Gating)
Once tables are gated, any code referencing `schema::tasks` will fail to compile if the feature is off.
(We have already done most of this in Models/Logic, but Schema was the safety net).
### **3.1 Verify Models imports**
Ensure `models/tasks.rs` uses `crate::schema::tasks` inside the same cfg gate.
### **3.2 Fix Cross-Feature Joins**
If Core code joins `users` with `tasks` (e.g. "get all user tasks"), that code chunk MUST be gated.
---
## Execution Checklist
### Schema
- [x] Create `src/core/shared/schema/` directory
- [x] Move core tables to `schema/core.rs`
- [x] Move task tables to `schema/tasks.rs` (gated)
- [x] Move mail tables to `schema/mail.rs` (gated)
- [x] Move people tables to `schema/people.rs` (gated)
- [x] Move tickets tables to `schema/tickets.rs` (gated)
- [x] Move billing tables to `schema/billing.rs` (gated)
- [x] Move attendant tables to `schema/attendant.rs` (gated)
- [x] Move calendar tables to `schema/calendar.rs` (gated)
- [x] Move goals tables to `schema/goals.rs` (gated)
- [x] Move canvas tables to `schema/canvas.rs` (gated)
- [x] Move workspaces tables to `schema/workspaces.rs` (gated)
- [x] Move social tables to `schema/social.rs` (gated)
- [x] Move analytics tables to `schema/analytics.rs` (gated)
- [x] Move compliance tables to `schema/compliance.rs` (gated)
- [x] Move meet tables to `schema/meet.rs` (gated)
- [x] Move research tables to `schema/research.rs` (gated)
- [x] Refactor `schema/mod.rs` to export modules conditionally
- [x] Split `joinable!` declarations into relevant files
- [x] Refactor `allow_tables_to_appear_in_same_query!` (Skipped/Implicit)
### Migrations
- [x] Audit `migrations/` folder
- [x] Create folder structure `migrations/{core,tasks,mail,people...}`
- [x] Move SQL files to appropriate folders
- [x] Update `run_migrations` in `utils.rs` to run feature-specific migration sets
### Validation
- [ ] `cargo check --no-default-features` (Run ONLY after all migration splits are verified)
- [ ] `cargo check --features tasks`
- [ ] `cargo check --all-features`