177 lines
6.7 KiB
Markdown
177 lines
6.7 KiB
Markdown
# GovOPlaN Module Architecture
|
|
|
|
GovOPlaN is structured as a core platform runner plus installable feature modules. Core owns the runtime shell and cross-cutting primitives. Modules own feature behavior and contribute backend routes, database metadata, permissions, WebUI routes, and navigation metadata.
|
|
|
|
## Core Responsibilities
|
|
|
|
Core owns:
|
|
|
|
- the server entry point and platform configuration
|
|
- module discovery, registry validation, route aggregation, and platform metadata APIs
|
|
- database engine/session primitives and migration orchestration
|
|
- auth, tenants, RBAC, governance, audit, CSRF/API helpers, and secret helpers
|
|
- shared WebUI shell components such as `AppShell`, `IconRail`, `DataGrid`, `ExplorerTree`, `MessageDisplayPanel`, dialogs, loading frames, access boundaries, and form primitives
|
|
- centralized mapping from serializable icon names to renderable frontend icons
|
|
|
|
Core must not import module feature pages or module business logic directly. It should interact with modules through manifests, entry points, metadata, and route contributions.
|
|
|
|
## Module Responsibilities
|
|
|
|
A module owns one bounded feature area. A module can include both backend and WebUI code in the same repository so feature behavior and frontend integration evolve together.
|
|
|
|
A module owns:
|
|
|
|
- backend routers and feature services
|
|
- SQLAlchemy models for module-owned tables
|
|
- module migrations and migration metadata
|
|
- module permissions and role templates
|
|
- module-specific schemas, policies, and domain rules
|
|
- WebUI pages, feature-specific components, API clients, route contributions, and navigation metadata
|
|
|
|
A module should not own generic platform UI. If a component is useful outside one module, move it to `@govoplan/core-webui` and parameterize it there before reusing it.
|
|
|
|
## Backend Contract
|
|
|
|
Backend modules register through the `govoplan.modules` entry point and expose a `ModuleManifest`.
|
|
|
|
Example:
|
|
|
|
```toml
|
|
[project.entry-points."govoplan.modules"]
|
|
files = "govoplan_files.backend.manifest:get_manifest"
|
|
```
|
|
|
|
The manifest should declare:
|
|
|
|
- `id`, `name`, `version`
|
|
- required `dependencies` and `optional_dependencies`
|
|
- permissions and role templates
|
|
- router factory
|
|
- migration metadata and script location
|
|
- frontend package metadata
|
|
- navigation metadata using serializable icon names
|
|
|
|
Backend nav metadata must use icon-name strings, not frontend components:
|
|
|
|
```python
|
|
NavItem(
|
|
path="/files",
|
|
label="Files",
|
|
icon="folder",
|
|
required_any=("files:file:read",),
|
|
order=40,
|
|
)
|
|
```
|
|
|
|
## Database And Migrations
|
|
|
|
Core owns the database/session lifecycle. Modules access the database through core session dependencies and register their models/migrations through their manifest.
|
|
|
|
Rules:
|
|
|
|
- Do not create independent database engines in modules.
|
|
- Use core session dependencies, base metadata, and migration orchestration.
|
|
- Keep module-owned tables and migrations in the module repository.
|
|
- Keep cross-module foreign-key assumptions explicit and conservative.
|
|
- Register module metadata in `MigrationSpec` so core can discover it.
|
|
|
|
## WebUI Contract
|
|
|
|
A WebUI module exports a `PlatformWebModule` from its package. The object contributes local/fallback metadata and route render functions.
|
|
|
|
Example:
|
|
|
|
```ts
|
|
export const filesModule: PlatformWebModule = {
|
|
id: "files",
|
|
label: "Files",
|
|
version: "1.0.0",
|
|
dependencies: ["access"],
|
|
navItems: [
|
|
{ to: "/files", label: "Files", iconName: "folder", anyOf: ["files:file:read"], order: 40 }
|
|
],
|
|
routes: [
|
|
{ path: "/files", anyOf: ["files:file:read"], order: 40, render: ({ settings, auth }) => createElement(FilesPage, { settings, auth }) }
|
|
]
|
|
};
|
|
```
|
|
|
|
WebUI modules receive only the core route context:
|
|
|
|
- `settings`
|
|
- `auth`
|
|
|
|
A module should call its own API client and module-owned backend routes. Shared API helpers should live in core only when they are truly platform-level concerns.
|
|
|
|
## Icon Rules
|
|
|
|
Icons are resolved centrally by core.
|
|
|
|
Modules must provide icon names with `iconName` in frontend nav contributions and `icon` in backend manifest metadata. Modules must not import Lucide icons for navigation metadata.
|
|
|
|
Current core icon names include:
|
|
|
|
- `activity`
|
|
- `campaign`
|
|
- `dashboard`
|
|
- `file`
|
|
- `files`
|
|
- `folder`
|
|
- `form`
|
|
- `mail`
|
|
- `reports`
|
|
- `users`
|
|
|
|
If a module needs a new navigation icon, add the name-to-component mapping in core first, then use the name in backend and frontend metadata.
|
|
|
|
## Shared Component Rules
|
|
|
|
Use this rule of thumb:
|
|
|
|
- If it is platform-level or likely reusable by more than one module, define it in `@govoplan/core-webui` with parameters.
|
|
- If it is feature-specific and only meaningful inside one bounded module, keep it in that module.
|
|
- Modules must not import components from another feature module.
|
|
- If one module needs a component currently owned by another module, promote a generic version into core and replace the old usage with the core component.
|
|
|
|
Examples:
|
|
|
|
- `ExplorerTree` is core because files, mailboxes, and future modules can all render hierarchical navigation.
|
|
- `MessageDisplayPanel` is core because mail, campaign sending, and later audit/review surfaces can display message-like content.
|
|
- `MailProfileManagement` remains in the mail module because it is specific to mail transport policies and profiles.
|
|
|
|
## Cross-Module Integration
|
|
|
|
A module can declare required dependencies and optional dependencies. Optional behavior should be enabled by module presence and permissions, not by importing another module's WebUI internals.
|
|
|
|
Rules:
|
|
|
|
- Use core module metadata to check whether another module is installed.
|
|
- Use backend APIs/events/service contracts for runtime cooperation.
|
|
- Keep UI integration declarative where possible: nav items, route contributions, context actions, and explicit extension points.
|
|
- Avoid direct imports from one feature module into another feature module unless the imported package is a published API contract designed for that purpose. UI components should be promoted to core instead.
|
|
|
|
## Build And Verification
|
|
|
|
Backend verification from core:
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/govoplan-core
|
|
./.venv/bin/python -m compileall src/govoplan_core ../govoplan-files/src/govoplan_files ../govoplan-mail/src/govoplan_mail ../govoplan-campaign/src/govoplan_campaign
|
|
```
|
|
|
|
Core WebUI host verification:
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/govoplan-core/webui
|
|
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm run build
|
|
```
|
|
|
|
Wrapper WebUI verification, while the legacy wrapper still exists:
|
|
|
|
```bash
|
|
cd /mnt/DATA/git/multi-seal-mail-webui
|
|
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm run build
|
|
```
|
|
|
|
Clean generated `dist`, `.vite`, and source-tree `__pycache__` artifacts after verification unless they are intentionally part of a release artifact.
|