You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.8 KiB
7.8 KiB
Software Architect Audit Report (March 27, 2026)
Clarification Questions
- Should a new theme be creatable with empty categories/topic (draft mode), or must it be valid at creation?
- Should
GET /themes/{id}/schedulereturn404when absent, or200withnull? - Which defaults are canonical for themes: DB/spec (
max_items_per_category=4,summary_length=3) or UI/handler (5,2)?
Assumptions
- Documentation in
docs/is the intended target behavior. - This is architecture-focused (entry points, service boundaries, major modules), not a line-by-line audit of all files.
Prioritized Findings
P0
- Theme creation contract is internally inconsistent and likely broken in practice.
- Evidence: UI creates empty topic/categories in
/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/ThemeManager.tsx:144, while backend rejects empty topic/categories in/Users/oabrivard/Projects/rust/ai_synth/backend/src/models/theme.rs:43and enforces validation in/Users/oabrivard/Projects/rust/ai_synth/backend/src/handlers/themes.rs:45. - Why it matters: blocks core onboarding flow.
- Direction: align API contract + UI create flow (draft-support or valid seeded defaults).
- Evidence: UI creates empty topic/categories in
P1
-
Schedule API contract drift across spec, backend, tests, and frontend typing.
- Evidence: spec says
ScheduleResponseor 404 in/Users/oabrivard/Projects/rust/ai_synth/docs/technical_specs.md:420; backend returns200 nullin/Users/oabrivard/Projects/rust/ai_synth/backend/src/handlers/schedules.rs:40; tests expect200 nullin/Users/oabrivard/Projects/rust/ai_synth/backend/tests/api_schedules_test.rs:77; frontend assumes non-null in/Users/oabrivard/Projects/rust/ai_synth/frontend/src/components/settings/SettingsSchedule.tsx:48. - Why it matters: runtime fragility and contract confusion.
- Direction: choose one contract and align all layers.
- Evidence: spec says
-
Theme defaults are inconsistent with DB/spec.
- Evidence: DB migration defaults 4/3 in
/Users/oabrivard/Projects/rust/ai_synth/backend/migrations/20260326000028_create_themes_and_migrate.sql:8; handler uses 5/2 in/Users/oabrivard/Projects/rust/ai_synth/backend/src/handlers/themes.rs:56; UI uses 5/2 in/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/ThemeManager.tsx:51. - Why it matters: non-deterministic behavior and drift.
- Direction: establish a single source of truth for defaults.
- Evidence: DB migration defaults 4/3 in
-
Reliability gap: job-store TTL cleanup exists but is not scheduled at runtime.
- Evidence: cleanup function exists in
/Users/oabrivard/Projects/rust/ai_synth/backend/src/services/job_store.rs:153; startup schedules other tasks but not job-store cleanup in/Users/oabrivard/Projects/rust/ai_synth/backend/src/main.rs:66; docs expect periodic cleanup in/Users/oabrivard/Projects/rust/ai_synth/docs/technical_specs.md:778. - Why it matters: stale in-memory entries and lock leakage risk over time.
- Direction: add periodic
job_store.cleanup_expired()task.
- Evidence: cleanup function exists in
-
Scheduled generation path does not enforce 15-minute timeout used by manual generation.
- Evidence: manual timeout in
/Users/oabrivard/Projects/rust/ai_synth/backend/src/handlers/generation.rs:89; scheduler calls pipeline directly in/Users/oabrivard/Projects/rust/ai_synth/backend/src/services/scheduler.rs:57; requirement states 15-minute cap in/Users/oabrivard/Projects/rust/ai_synth/docs/requirements.md:30. - Why it matters: scheduled runs can overrun and block throughput.
- Direction: apply same timeout semantics to scheduled execution.
- Evidence: manual timeout in
P2
-
Core pipeline and key pages are too large.
- Evidence:
/Users/oabrivard/Projects/rust/ai_synth/backend/src/services/synthesis.rs,/Users/oabrivard/Projects/rust/ai_synth/backend/src/services/scraper.rs,/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/ThemeManager.tsx,/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/Settings.tsx. - Why it matters: weaker SRP, higher cognitive load, slower onboarding/review/testing.
- Direction: split by bounded responsibilities (phase modules/services/hooks/components).
- Evidence:
-
Frontend architectural consistency drift (API and data-loading patterns).
- Evidence: direct
fetchin/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/GenerateSynthesis.tsx:241despite centralized client in/Users/oabrivard/Projects/rust/ai_synth/frontend/src/api/client.ts:25; guideline preference forcreateResourcein/Users/oabrivard/Projects/rust/ai_synth/docs/dev_guidelines.md:174. - Direction: enforce API client boundary and consistent data-loading patterns.
- Evidence: direct
SOLID Scorecard
| Dimension | Score (/5) | Notes |
|---|---|---|
| Single Responsibility | 2 | Several large multi-responsibility modules. |
| Open/Closed | 4 | LLM provider abstraction/factory is extensible. |
| Liskov Substitution | 4 | Provider implementations conform to trait contract cleanly. |
| Interface Segregation | 3 | Mostly good boundaries with a few broad surfaces. |
| Dependency Inversion | 3 | Good trait usage for LLM, pipeline still tightly coupled in places. |
| Overall maintainability | 3 | Good foundations, but contract drift + module size are bottlenecks. |
Refactoring Plan
- Phase 0: Contract decisions (0.5-1 day, low risk).
- Decide canonical behavior for theme creation, schedule GET semantics, and defaults.
- Phase 1: Correctness alignment (1-2 days, medium risk).
- Align backend/frontend/tests with chosen contracts.
- Phase 2: Reliability hardening (1 day, low-medium risk).
- Add job-store cleanup scheduling and timeout parity in scheduler.
- Phase 3: Backend decomposition (3-5 days, medium risk).
- Split synthesis pipeline into phase modules with explicit contexts.
- Phase 4: Frontend decomposition (3-5 days, medium risk).
- Split large pages into composables/components and remove direct page-level fetch.
- Phase 5: Drift prevention (1-2 days, low risk).
- Add conformance tests/checks for contracts/defaults and PR architecture checklist.
Architecture/SOLID Scorecard
| Dimension | Score (/5) | Notes |
|---|---|---|
| Layering clarity | 3 | Clear module boundaries, but some runtime orchestration gaps. |
| SRP | 2 | Multiple "god files" in backend and frontend. |
| OCP | 4 | LLM provider abstraction/factory is cleanly extensible. |
| DIP | 3 | Core synthesis is trait-based for LLM, but still tightly coupled to DB/functions. |
| Testability | 3 | Strong unit/integration coverage in backend; scheduler/e2e gaps remain. |
| Spec alignment | 2 | Multiple contract/default mismatches. |
Refactoring Plan (Architecture-Level)
Phase 1 (1-2 days) — Contract and reliability fixes
- Align theme creation contract (UI + model validation + tests).
- Align schedule GET semantics across docs/handler/tests/frontend types.
- Add periodic
job_store.cleanup_expired()background task. - Apply 15-minute timeout to scheduled generation path.
Phase 2 (3-5 days) — Backend decomposition
- Split
services/synthesis.rsinto submodules:init.rs(load settings/theme/provider)phase1_personalized.rsphase2_fallback.rsfinalize.rstracing.rs
- Introduce explicit pipeline context structs to reduce argument fanout.
Phase 3 (3-5 days) — Frontend decomposition
- Extract page-level logic from
ThemeManagerandSettingsinto composables/hooks:useThemeEditor,useSourcesManager,useScheduleConfig,useSettingsForm
- Normalize API usage through
api/client.tsonly.
Phase 4 (2-3 days) — Conformance hardening
- Add spec-conformance tests for defaults, schedule contract, and theme creation.
- Add architecture fitness checks (lint/custom tests) for forbidden contract drifts.
Quick Wins (< 1 day)
- Add scheduled timeout wrapper in
scheduler.rs. - Add job-store periodic cleanup task in
main.rs. - Fix
ThemeManagercreate payload to pass valid initialthemeand categories. - Unify schedule GET typing with actual backend behavior.