Domain Modules
MemGhost is organized into domain modules, each responsible for a specific aspect of personal knowledge management. Modules communicate via events and maintain strict boundaries.
Module Structure
Each module follows the same layout:
module/├── api/ # HTTP handlers (OpenAPI generated)├── commands/ # Write operations├── queries/ # Read operations├── domain/ # Business logic│ ├── aggregates/ # Domain entities│ └── events/ # Domain events├── projections/ # Read model builders└── module.go # Module initializationModule Boundaries
Modules only communicate via:
- Events published through the event bus
- Read-only queries to other modules’ read models (via well-defined interfaces)
- No direct function calls between module internals
Module Overview
| Module | Purpose | Status |
|---|---|---|
| Vault | Canonical item store, ingest pipeline, classification | Active |
| Hubs | Topic graph, AI routing, content materialization | Active |
| Spaces | AI conversation workspaces with personas and artifacts | Active |
| Note | Read model for note-type items with tags and folders | Active |
| Agent | AI chat sessions, MCP tool servers, semantic search | Active |
| TTS | Voice synthesis via Kokoro, voice management | Active |
| Auth | JWT authentication, sessions, role-based access | Active |
| Setup | First-run wizard and initial data import | Active |
Vault Module
Purpose: The canonical store for all captured items. Everything enters the system through the vault.
Aggregate: VaultItem (with type, status, raw_payload, metadata, tags, folder)
Key Operations: Capture item, classify, update, archive, tag/untag, move
Events Emitted:
item.created.v1— new item captureditem.classified.v1— type and metadata assigned by pipelineitem.updated.v1— content or metadata changeditem.archived.v1— item archiveditem.tagged.v1,item.untagged.v1— tag changes
Events Consumed: None — this is the source module.
Hubs Module
Purpose: Maintains a topic graph where each node is a hub page. An AI pipeline routes vault items to hubs and materializes page content.
Aggregates: HubNode, HubEdge
Key Operations: Route item to hub, materialize node content, create/update/delete nodes
Pipeline Stages:
- Routing (instant, per-item) — LLM assigns item to existing hub or proposes new one
- Materialization (debounced ~30s, per-node) — LLM synthesizes page content from all source items
Events Consumed:
item.classified.v1— triggers routing for new/updated items
Design: Hubs are pure derived state. Vault items are the source of truth; hub pages are synthesized from them. User edits to hub content are recorded as hub_edit vault items that flow back through the pipeline.
Spaces Module
Purpose: AI conversation workspaces with configurable personas, living artifacts, and vault sync rules. Each Space registers a dynamic agent so the existing chat infrastructure works as-is.
Aggregate: Space (with agent config, artifact definitions, sync rules, model tier)
Key Operations: Create space, update config, archive/restore, manage artifacts, end session
Events Emitted:
space.created.v1— new space created (from template or custom)space.updated.v1— config or persona changedspace.archived.v1— space archivedspace.restored.v1— space restored from archive
Components:
- Templates — YAML files (e.g.,
therapy.yaml,hub-context.yaml) packaging persona + artifacts + sync rules - Artifacts — DB-stored documents (
space_artifacts) with path-based naming (e.g.,sessions/2026-05-08.md). Agents read/write via tools - Sync rules — Configurable rules that publish Space outputs back to the vault on session end
- Auto-prompt — Optional field that triggers the agent to speak first on new sessions
- Contextual hub spaces — Spaces bound to a hub page, with pinned artifacts mirroring hub content
Events Consumed:
hub.node.materialized.v1— updates pinned artifacts in contextual hub spaces
Note Module
Purpose: Provides a clean read/write view of note-type vault items. The note_views table is a projection of vault events — not an independent store.
Key Operations: List notes, get note, pin/unpin (only operation on note aggregate)
Events Consumed:
item.classified.v1— create/update note_views rowitem.updated.v1— update note contentitem.archived.v1— mark note archiveditem.tagged.v1,item.untagged.v1— update tags
Write Path: All writes (create, update, archive, tag, move) go through the vault module. The note module only handles pin/unpin on its own aggregate.
Agent Module
Purpose: AI chat with conversational agents that have MCP tool access to your data.
Aggregates: AgentSession (tree-structured conversation history)
Key Operations: Create session, send message, stream response, list sessions
Components:
- Agent registry with per-module agent definitions
- MCP tool servers exposing search, get, similarity queries
- Semantic search via pgvector embeddings
- Chat streaming via Ollama + Vercel AI SDK
TTS Module
Purpose: Text-to-speech synthesis for spoken AI responses.
Key Operations: Synthesize text, manage voices, preview voices
Components:
- Kokoro integration for speech synthesis (82M parameter model, CPU-friendly)
- Voice management (create, update, delete custom voices)
- Audio streaming for synthesized speech
Auth Module
Purpose: User authentication and session management.
Key Operations: Login, logout, refresh token, manage users and roles
Components:
- JWT token issuance and validation
- Session management with refresh tokens
- Role-based access control
- Admin user and role management
Setup Module
Purpose: First-run experience for new installations.
Key Operations: Check setup status, run setup wizard, import initial data
Components:
- Setup status tracking in system_settings
- Step-by-step wizard (welcome, account creation, completion)
- Data import pipeline with progress tracking (SSE)
Cross-Module Event Flow
Example: User Captures a Quick Note
- User types a note in the vault capture UI
- Vault stores the item and emits
item.created.v1 - Classification pipeline processes the item, emits
item.classified.v1 - Note projection creates a row in note_views
- Hub routing assigns the item to a topic hub
- Materialization regenerates the hub page content
- Embedding projection generates vectors for semantic search
- SSE pushes updates to the frontend in real-time
Example: User Adds a Line from a Hub Page
- User types a quick entry from a hub page (with hub_hint context)
- Vault stores the item with hub_hint in raw_payload
- Classification emits
item.classified.v1 - Hub routing uses the hub_hint as strong signal, routes to the viewed hub
- Materialization updates the hub page with the new content
Event Flow Summary
| Producer | Event | Consumers |
|---|---|---|
| Vault | item.created.v1 | Classification pipeline |
| Vault | item.classified.v1 | Note projection, Hub routing, Embedding projection |
| Vault | item.updated.v1 | Note projection, Hub re-routing |
| Vault | item.archived.v1 | Note projection |
| Vault | item.tagged.v1 | Note projection |
| Vault | item.untagged.v1 | Note projection |
| Hubs | hub.node_materialized.v1 | Frontend (SSE) |