Framework M Features
Auto-generated feature list from phase checklists.
Overview
| Phase | Title | Completion |
|---|---|---|
| 01 | Phase 01: Core Kernel & Interfaces | ██████████ 100% |
| 02 | Phase 02: DocType Engine & Database | ██████████ 100% |
| 03 | Phase 03: API Layer & Authorization | ██████████ 100% |
| 04 | Phase 04: Background Jobs & Events | █████████░ 98% |
| 05 | Phase 05: CLI & Developer Tools | █████████░ 97% |
| 06 | Phase 06: Built-in DocTypes & Core Features | █████████░ 99% |
| 07 | Phase 07: Studio (Code Generation UI) | █████████░ 93% |
| 08 | Phase 08: Workflows & Advanced Features | ██████████ 100% |
| 09a | Phase 09A: Frontend | █████████░ 97% |
| 09b | Phase 09B: Documentation | ██████████ 100% |
| 10 | Phase 10: ERP Enterprise Features | ██████████ 100% |
| 10 | Phase 10: Production Readiness & Deployment | ░░░░░░░░░░ 0% |
| 11 | Phase 11: Package Split & MX Pattern | ██████████ 100% |
| 12 | Phase 12: LLM-Ready Documentation & Automation | ███░░░░░░░ 39% |
| 13 | Phase 13: UI/UX Polish & Design System Enhancement | ░░░░░░░░░░ 0% |
| 14 | Phase 14: Studio Enhancements | ░░░░░░░░░░ 0% |
Phase 01: Core Kernel & Interfaces
Phase: 01 Objective: Set up the project foundation with clean hexagonal architecture. Define all protocol interfaces (ports) without any implementation. Status: 100% Complete
1. Project Initialization
Progress: 17/17 (100%)
Completed:
- ✅ Create project structure using
uv: - ✅ Setup
pyproject.tomlwith dependencies - ✅ Add
litestar[standard]>=2.0.0 - ✅ Add
sqlalchemy[asyncio]>=2.0.0(ensure agnostic, test with sqlite) - ✅ Add
pydantic>=2.0.0 - ✅ Add
pydantic-settings>=2.0.0 - ✅ Add
dependency-injector>=4.41.0(powerful DI container) - ✅ Add
asyncpg>=0.29.0(PostgreSQL async driver) - ✅ Add
redis>=5.0.0 - ✅ Remove
arq>=0.26.0 - ✅ Add
taskiq>=0.11.0,taskiq-nats>=0.4.0,nats-py>=2.0.0 - ✅ Add dev dependencies:
pytest,pytest-asyncio,mypy,ruff - ✅ Configure development tools
- ✅ Setup
mypywith strict mode inpyproject.toml - ✅ Configure
rufffor linting and formatting - ✅ Add
.gitignorefor Python projects - ✅ Create directory structure
2. Define Port Interfaces > 2.1 Repository Protocol
Progress: 16/16 (100%)
Completed:
- ✅ Create
tests/core/interfaces/test_repository.py - ✅ Define test for
RepositoryProtocolinterface compliance - ✅ Create
src/framework_m/core/interfaces/repository.py - ✅ Define supporting models:
- ✅
FilterSpec- Typed filter specification (field, operator, value) - ✅
OrderSpec- Sorting specification (field, direction) - ✅
PaginatedResult[T]- Result withitems,total,limit,offset,has_more - ✅ Define
RepositoryProtocol[T](Generic): - ✅
async def get(self, id: UUID) -> T | None - ✅
async def save(self, entity: T, version: int | None = None) -> T(OCC support) - ✅
async def delete(self, id: UUID) -> None - ✅
async def exists(self, id: UUID) -> bool - ✅
async def count(self, filters: list[FilterSpec] | None = None) -> int - ✅
async def list(self, filters: list[FilterSpec] | None, order_by: list[OrderSpec] | None, limit: int, offset: int) -> PaginatedResult[T] - ✅
async def bulk_save(self, entities: list[T]) -> list[T] - ✅ Add type hints with
Generic[T]andProtocol
2. Define Port Interfaces > 2.2 Event Bus Protocol
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/event_bus.py - ✅ Define
Eventbase model withid,timestamp,source,type,data - ✅ Define
EventBusProtocolwith methods: - ✅
async def connect(self) -> None(for NATS/Kafka) - ✅
async def disconnect(self) -> None - ✅
def is_connected(self) -> bool - ✅
async def publish(self, topic: str, event: Event) -> None - ✅
async def subscribe(self, topic: str, handler: Callable[[Event], Awaitable[None]]) -> str(returns subscription_id) - ✅
async def subscribe_pattern(self, pattern: str, handler: Callable) -> str(e.g.,doc.*) - ✅
async def unsubscribe(self, subscription_id: str) -> None
2. Define Port Interfaces > 2.3 Auth Context Protocol
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/auth_context.py - ✅ Define
UserContextPydantic model with fields: - ✅
id: str - ✅
email: str - ✅
roles: list[str] - ✅
tenants: list[str] - ✅ Define
AuthContextProtocolwith methods: - ✅
async def get_current_user() -> UserContext
2. Define Port Interfaces > 2.4 Storage Protocol
Progress: 11/11 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/storage.py - ✅ Define
FileMetadatamodel withpath,size,content_type,modified,etag - ✅ Define
StorageProtocolwith methods: - ✅
async def save_file(self, path: str, content: bytes, content_type: str | None = None) -> str - ✅
async def get_file(self, path: str) -> bytes - ✅
async def delete_file(self, path: str) -> None - ✅
async def list_files(self, prefix: str) -> list[str] - ✅
async def get_metadata(self, path: str) -> FileMetadata | None - ✅
async def get_url(self, path: str, expires: int = 3600) -> str(presigned URL for S3) - ✅
async def copy(self, src: str, dest: str) -> str - ✅
async def move(self, src: str, dest: str) -> str
2. Define Port Interfaces > 2.5 Job Queue Protocol
Progress: 9/9 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/job_queue.py - ✅ Define
JobStatusenum:PENDING,RUNNING,SUCCESS,FAILED,CANCELLED - ✅ Define
JobInfomodel withid,name,status,enqueued_at,started_at,result,error - ✅ Define
JobQueueProtocolwith methods: - ✅
async def enqueue(self, job_name: str, **kwargs) -> str(returns job_id) - ✅
async def schedule(self, job_name: str, cron: str, **kwargs) -> str - ✅
async def cancel(self, job_id: str) -> bool - ✅
async def get_status(self, job_id: str) -> JobInfo | None - ✅
async def retry(self, job_id: str) -> str(returns new job_id)
2. Define Port Interfaces > 2.6 Permission Protocol
Progress: 5/5 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/permission.py - ✅ Define
PermissionProtocolwith methods: - ✅
async def has_permission(user: UserContext, doctype: str, action: str, doc_id: str | None) -> bool - ✅
async def get_permitted_filters(user: UserContext, doctype: str) -> dict - ✅ Add action types:
"read","write","create","delete","submit"
2. Define Port Interfaces > 2.7 Print Protocol
Progress: 3/3 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/print.py - ✅ Define
PrintProtocolwith methods: - ✅
async def render(doc: BaseModel, template: str, format: str = "pdf") -> bytes
2. Define Port Interfaces > 2.8 Cache Protocol
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/cache.py - ✅ Define
CacheProtocol: - ✅
async def get(self, key: str) -> Any | None - ✅
async def set(self, key: str, value: Any, ttl: int | None = None) -> None - ✅
async def delete(self, key: str) -> None - ✅
async def exists(self, key: str) -> bool - ✅
async def get_many(self, keys: list[str]) -> dict[str, Any] - ✅
async def set_many(self, items: dict[str, Any], ttl: int | None = None) -> None - ✅
async def delete_pattern(self, pattern: str) -> int(returns count deleted) - ✅
async def ttl(self, key: str) -> int | None(remaining TTL)
2. Define Port Interfaces > 2.9 Notification Protocol
Progress: 4/4 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/notification.py - ✅ Define
NotificationProtocol: - ✅
async def send_email(to: str, subject: str, body: str) - ✅
async def send_sms(to: str, body: str)
2. Define Port Interfaces > 2.10 Search Protocol
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/search.py - ✅ Define
SearchResultmodel withitems,total,facets,highlights - ✅ Define
SearchProtocol: - ✅
async def index(self, doctype: str, doc_id: str, doc: dict) -> None - ✅
async def delete_index(self, doctype: str, doc_id: str) -> None - ✅
async def search(self, doctype: str, query: str, filters: dict | None = None, limit: int = 20, offset: int = 0) -> SearchResult - ✅
async def reindex(self, doctype: str) -> int(returns count indexed)
2. Define Port Interfaces > 2.11 I18n Protocol
Progress: 4/4 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/i18n.py - ✅ Define
I18nProtocol: - ✅
async def translate(text: str, locale: str) -> str - ✅
async def get_locale() -> str
3. Define Domain Layer > 3.1 Base DocType
Progress: 12/12 (100%)
Completed:
- ✅ Create
src/framework_m/core/domain/base_doctype.py - ✅ Define
BaseDocTypeclass inheriting frompydantic.BaseModel - ✅ Add standard fields:
- ✅
name: Optional[str](primary key, auto-generated if None) - ✅
creation: datetime - ✅
modified: datetime - ✅
modified_by: Optional[str] - ✅
owner: Optional[str] - ✅ Add
Metanested class for metadata: - ✅
layout: dict = {}(viaget_layout()) - ✅
permissions: dict = {}(viaget_permissions()) - ✅ Add class method
get_doctype_name() -> str
3. Define Domain Layer > 3.2 Base Controller
Progress: 12/12 (100%)
Completed:
- ✅ Create
src/framework_m/core/domain/base_controller.py - ✅ Define
BaseController[T]generic class - ✅ Add lifecycle hook methods:
- ✅
async def validate(self, context: Any = None) -> None - ✅
async def before_insert(self, context: Any = None) -> None - ✅
async def after_insert(self, context: Any = None) -> None - ✅
async def before_save(self, context: Any = None) -> None - ✅
async def after_save(self, context: Any = None) -> None - ✅
async def before_delete(self, context: Any = None) -> None - ✅
async def after_delete(self, context: Any = None) -> None - ✅
async def on_submit(self, context: Any = None) -> None - ✅
async def on_cancel(self, context: Any = None) -> None
3. Define Domain Layer > 3.3 Mixins
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/domain/mixins.py - ✅ Define
DocStatusenum: - ✅
DRAFT = 0 - ✅
SUBMITTED = 1 - ✅
CANCELLED = 2 - ✅ Define
SubmittableMixinclass with: - ✅
docstatus: DocStatus = DocStatus.DRAFT - ✅
def is_submitted() -> bool - ✅
def is_cancelled() -> bool - ✅
def can_edit() -> bool(returns False if submitted)
4. Meta Registry
Progress: 13/13 (100%)
Completed:
- ✅ Create
src/framework_m/core/registry.py - ✅ Implement
MetaRegistryas singleton - ✅ Add storage dictionaries:
- ✅
_doctypes: Dict[str, Type[BaseDocType]] - ✅
_controllers: Dict[str, Type[BaseController]] - ✅ Implement methods:
- ✅
register_doctype(doctype_class, controller_class=None) - ✅
get_doctype(name: str) -> Type[BaseDocType] - ✅
get_controller(name: str) -> Type[BaseController] | None - ✅
list_doctypes() -> list[str] - ✅
discover_doctypes(package_name: str)(scans for BaseDocType subclasses) - ✅ Load Order: Follows
installed_appslist. - ✅ Conflict Policy: Raise
DuplicateDocTypeErrorif same name registered twice.
5. Port Implementation (Adapters) > 5.1 Dependency Injection
Progress: 5/5 (100%)
Completed:
- ✅ Create
tests/core/test_container.py - ✅ Write test for Container initialization and service resolution
- ✅ Create
src/framework_m/core/container.py - ✅ Implement
Containerclass (usingdependency_injector): - ✅ Define
Containerclass:
5. Port Implementation (Adapters) > 5.2 Provider Types
Progress: 6/6 (100%)
Completed:
- ✅ Understand provider types:
- ✅
Singleton- Single instance shared across app - ✅
Factory- New instance each time - ✅
Resource- For resources with lifecycle (db connections) - ✅
Callable- For functions - ✅
Dependency- For protocol injection
5. Port Implementation (Adapters) > 5.3 Configuration Provider
Progress: 1/1 (100%)
Completed:
- ✅ Setup configuration loading:
5. Port Implementation (Adapters) > 5.4 Wiring
Progress: 2/2 (100%)
Completed:
- ✅ Configure wiring for automatic injection:
- ✅ Use
@injectdecorator in functions:
5. Port Implementation (Adapters) > 5.5 Entrypoint Scanning for Overrides
Progress: 5/5 (100%)
Completed:
- ✅ Create override mechanism:
- ✅ Scan
framework_m.overridesentrypoints - ✅ Allow apps to override providers
- ✅ Example:
- ✅ Implement override loader:
5. Port Implementation (Adapters) > 5.6 Testing Support
Progress: 2/2 (100%)
Completed:
- ✅ Use
overridefor testing: - ✅ Reset overrides after tests:
6. Testing Setup
Progress: 8/8 (100%)
Completed:
- ✅ Create
tests/directory structure - ✅ Setup
conftest.pywith fixtures: - ✅
pytest_asyncioconfiguration - ✅ Mock implementations of all protocols
- ✅ Write initial tests:
- ✅ Test
MetaRegistryregistration and retrieval - ✅ Test
BaseDocTypefield validation - ✅ Test
BaseControllerhook method existence
7. Documentation
Progress: 7/7 (100%)
Completed:
- ✅ Create
README.mdwith: - ✅ Project overview
- ✅ Installation instructions
- ✅ Basic usage example
- ✅ Create
docs/folder with: - ✅
architecture.md- Hexagonal architecture explanation - ✅
ports.md- List of all protocol interfaces (Repository, EventBus, Cache, Search, etc.)
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ All protocol interfaces are defined with proper type hints
- ✅
mypy --strictpasses with no errors - ✅ No infrastructure dependencies in
core/(no imports of litestar, sqlalchemy, redis) - ✅
BaseDocTypeandBaseControllerare properly generic - ✅
MetaRegistrycan register and retrieve DocTypes - ✅ All tests pass with
pytest
Phase 02: DocType Engine & Database
Phase: 02 Objective: Implement the metadata engine that dynamically creates database tables from Pydantic models and provides generic CRUD operations. Status: 100% Complete
1. Schema Mapper (Pydantic → SQLAlchemy) > 1.1 Field Registry & Type Mapping
Progress: 15/15 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/field_registry.py - ✅ Implement
FieldRegistryclass (Singleton): - ✅ Start with standard types: str, int, float, bool, datetime, date, decimal, uuid, json
- ✅ Allow registration of custom types:
register_type(pydantic_type, sqlalchemy_type) - ✅ Define type mapping using Registry:
- ✅
str→String - ✅
int→Integer - ✅
float→Float - ✅
bool→Boolean - ✅
datetime→DateTime - ✅
date→Date - ✅
Decimal→Numeric - ✅
UUID→UUID - ✅
list[str]→JSON(portable, works on all databases) - ✅
dict→JSON
1. Schema Mapper (Pydantic → SQLAlchemy) > 1.2 Schema Mapper Implementation
Progress: 19/19 (100%)
Completed:
- ✅ Create
tests/adapters/db/test_schema_mapper.py - ✅ Test mapping simple fields (str, int)
- ✅ Test mapping relationships
- ✅ Create
SchemaMapperclass - ✅ Use
FieldRegistryto look up SQLAlchemy types - ✅ Implement
create_table(model: Type[BaseDocType]) -> Table: - ✅ Extract table name from model class name (lowercase)
- ✅ Iterate over
model.model_fields - ✅ Map each field to SQLAlchemy column
- ✅ Handle
Optionaltypes (nullable=True) - ✅ Set
idfield as primary key (UUID, auto-generated) - ✅ Set
namefield as unique index (for human-readable lookup) - ✅ OCC: Add
_version(Integer, default=0) ifMeta.concurrency="optimistic" - ✅ Return SQLAlchemy
Tableobject - ✅ Handle special field types:
- ✅ Relationships (ForeignKey) - detect by field name pattern
*_id - ✅ Enums - map to SQLAlchemy String type (database agnostic)
- ✅ Nested Pydantic models (
list[BaseModel]) - store as JSON - ✅ Child DocTypes (
list[DocType]) - map to Relational Table with Foreign Key
1. Schema Mapper (Pydantic → SQLAlchemy) > 1.3 Table Registry
Progress: 5/5 (100%)
Completed:
- ✅ Create
TableRegistryclass to store created tables - ✅ Add methods:
- ✅
register_table(doctype_name: str, table: Table) - ✅
get_table(doctype_name: str) -> Table - ✅
table_exists(doctype_name: str) -> bool
2. Database Connection Setup > 2.1 Connection Factory & Virtual DocTypes
Progress: 5/5 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/connection.py - ✅ Implement
ConnectionFactory(supports Multiple Bindings): - ✅ Load
db_bindsfrom config (e.g.,legacy,timescale) - ✅ Create generic async engine (supports Postgres, SQLite for testing)
- ✅ Maintain map of
engine_name -> AsyncEngine
2. Database Connection Setup > 2.2 Session Factory (SQL Support)
Progress: 3/3 (100%)
Completed:
- ✅ Add session factory:
- ✅
async def get_session(bind: str = "default") -> AsyncSession - ✅ Support
VirtualDocType(SQL Bind) by acceptingbind_keyfrom DocType Meta
2. Database Connection Setup > 2.3 Non-SQL Virtual DocTypes (Custom Repositories)
Progress: 7/7 (100%)
Completed:
- ✅ Create concept of
RepositoryOverride: - ✅ Allow DocType to define
repository_classin Meta - ✅
RepositoryFactoryinstantiates this instead ofGenericRepository - ✅ Create
tests/adapters/db/test_repository_factory.py: - ✅ Implement a Mock
FileRepositorythat reads from JSON file - ✅ Register it for a
VirtualDoc - ✅ Verify
VirtualDoc.get()callsFileRepository.get()
3. Generic Repository Implementation
Progress: 9/9 (100%)
Completed:
- ✅ Create
tests/adapters/db/test_generic_repository.py - ✅ Define tests for CRUD operations (mock
AsyncSession) - ✅ Create
src/framework_m/adapters/db/generic_repository.py - ✅ Implement
GenericRepository[T]class - ✅ Constructor dependencies (session is NOT stored here):
- ✅
model: Type[T] - ✅
table: Table - ✅
controller_class: Type[BaseController] | None - ✅
event_bus: EventBusProtocol | None(InMemoryEventBus for dev)
3. Generic Repository Implementation > 3.1 CRUD Operations
Progress: 49/49 (100%)
Completed:
- ✅ Implement
async def get(session: AsyncSession, id: UUID) -> Optional[T]: - ✅ Build SELECT query
- ✅ Filter
deleted_at IS NULL(unless specific flag overrides) - ✅ Execute with provided session (not stored session)
- ✅ Convert row to Pydantic model
- ✅ Return None if not found
- ✅ Implement
async def get_by_name(session: AsyncSession, name: str) -> Optional[T]: - ✅ Helper for looking up by human-readable name
- ✅ Implement
async def save(session: AsyncSession, entity: T, version: int | None = None) -> T: - ✅ Check if entity exists (by
id) - ✅ If new:
- ✅ Generate
id(UUIDv7) - ✅ Note:
created_by/ownermust be set by Controller/Service before calling save - ✅ Call controller
validate() - ✅ Call controller
before_create() - ✅ Call controller
before_save() - ✅ Execute INSERT with provided session
- ✅ Call controller
after_save() - ✅ Call controller
after_create() - ✅ Emit Event:
event_bus.publish(f"{doctype}.create", payload) - ✅ If existing:
- ✅ Note:
modified_bymust be set by Controller/Service before calling save - ✅ Call controller
validate() - ✅ Call controller
before_save() - ✅ OCC: If
optimistic: - ✅
UPDATE table SET ..., _version=_version+1 WHERE id=:id AND _version=:old_ver - ✅ If rowcount == 0, raise
VersionConflictError - ✅ Else: Execute standard UPDATE
- ✅ Call controller
after_save() - ✅ Emit Event:
event_bus.publish(f"{doctype}.update", payload) - ✅ Return saved entity (caller calls
uow.commit()when ready) - ✅ Implement
async def delete(session: AsyncSession, id: UUID, hard: bool = False) -> None: - ✅ Load entity
- ✅ Call controller
before_delete() - ✅ If
hard: - ✅ Execute DELETE
- ✅ Else (Soft Delete):
- ✅ Update
deleted_at = now() - ✅ Call controller
after_delete() - ✅ Emit Event:
event_bus.publish(f"{doctype}.delete", payload) - ✅ Return (caller calls
uow.commit()when ready) - ✅ Implement
async def list(session: AsyncSession, filters, limit, offset, order_by) -> Sequence[T]: - ✅ Build SELECT query with filters
- ✅ Default filter:
deleted_at IS NULL - ✅ Apply pagination (limit, offset)
- ✅ Apply sorting (order_by)
- ✅ Execute query
- ✅ Convert rows to Pydantic models
- ✅ Return list
3. Generic Repository Implementation > 3.2 Lifecycle Hook Integration
Progress: 5/5 (100%)
Completed:
- ✅ Create helper method
_call_hook(hook_name: str): - ✅ Check if controller exists
- ✅ Check if hook method exists on controller
- ✅ Call hook method if present
- ✅ Handle exceptions and rollback on error
4. Migration System > 4.1 Alembic Integration
Progress: 8/8 (100%)
Completed:
- ✅ Initialize Alembic in project:
- ✅ Configure
alembic.ini: - ✅ Set database URL from environment
- ✅ Configure migration file location
- ✅ Create
alembic/env.py: - ✅ Import
MetaRegistry - ✅ Import all registered DocTypes
- ✅ Set
target_metadatafrom SchemaMapper tables
4. Migration System > 4.2 Auto-Migration Detection
Progress: 11/11 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/migration.py - ✅ Implement
detect_schema_changes(): - ✅ Compare registered DocTypes with database schema
- ✅ Detect new tables
- ✅ Detect new columns
- ✅ Detect type changes
- ✅ Return list of changes
- ✅ Implement
auto_migrate(): - ✅ Call
detect_schema_changes() - ✅ Generate Alembic migration if changes detected
- ✅ Apply migration automatically (dev mode only)
4. Migration System > 4.3 CLI Commands
Progress: 5/5 (100%)
Completed:
- ✅ Add migration commands to CLI:
- ✅
m migrate- run pending migrations - ✅
m migrate:create <name>- create new migration - ✅
m migrate:rollback- rollback last migration - ✅
m migrate:status- show migration status
5. Repository Factory
Progress: 9/9 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/repository_factory.py - ✅ Implement
RepositoryFactoryclass: - ✅
create_generic_repository(doctype_name: str) -> GenericRepository - ✅ Look up DocType from MetaRegistry
- ✅ Look up Table from TableRegistry
- ✅ Look up Controller from MetaRegistry
- ✅ Create and return GenericRepository instance
- ✅ Support
event_busparameter for domain events - ✅ Support custom repository overrides for Virtual DocTypes
6. Engine, Session Factory & Unit of Work > 6.1 Engine & Session Factory Setup
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/connection.py(ConnectionFactory) - ✅ Implement
create_engine(url: str) -> AsyncEngine - ✅ Pool configuration (pool_size, max_overflow, timeout, recycle, pre_ping)
- ✅ Environment variable expansion (
${VAR}syntax) - ✅ Implement
SessionFactory(returnsAsyncSessioncontext managers) - ✅ Support multiple binds (for Virtual DocTypes with SQL binds)
- ✅ Configuration from ConnectionFactory
- ✅ Auto commit/rollback in context manager
6. Engine, Session Factory & Unit of Work > 6.2 Unit of Work (UnitOfWork)
Progress: 14/14 (100%)
Completed:
- ✅ Create
tests/core/test_unit_of_work.py - ✅ Test: UoW provides session
- ✅ Test:
commit()persists changes - ✅ Test: Exception causes rollback (no explicit rollback call needed)
- ✅ Test: Session is closed after
__aexit__ - ✅ Create
src/framework_m/core/unit_of_work.py - ✅ Implement
UnitOfWorkcontext manager: - ✅
__init__(session_factory: Callable[[], AsyncSession]) - ✅
sessionproperty with safety check - ✅
async __aenter__()creates session - ✅
async commit()calls session.commit() - ✅
async rollback()for explicit rollback - ✅
async __aexit__()with auto-rollback on exception - ✅ Register
UnitOfWorkFactoryin DI container
6. Engine, Session Factory & Unit of Work > 6.3 Multi-Source Coordination (Outbox Pattern)
Progress: 17/17 (100%)
Completed:
- ✅ Create
src/framework_m/core/domain/outbox.py - ✅ Define
OutboxEntrymodel: - ✅
id: UUID - ✅
target: str(e.g., "mongodb.audit_log", "api.payment_gateway") - ✅
payload: dict - ✅
status: str(pending, processed, failed) - ✅
created_at: datetime - ✅
processed_at: datetime | None - ✅
error_message: str | None - ✅
retry_count: int - ✅ Create
OutboxRepository(SQL-backed) inadapters/db/outbox_repository.py - ✅
add(session, entry)- add entry in same transaction - ✅
get_pending(session, limit)- get pending entries - ✅
mark_processed(session, id)- mark as processed - ✅
mark_failed(session, id, error)- mark as failed - ✅ Document: Services write to Outbox in the same SQL transaction
- ✅ (Phase 04) Background worker processes Outbox entries
6. Engine, Session Factory & Unit of Work > 6.4 Startup Sequence (Schema Sync)
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/db/__init__.py - ✅ Implement startup sequence (called once at app boot, NOT per-request):
- ✅ Initialize database engine (NOT session)
- ✅ Discover all DocTypes via MetaRegistry
- ✅ Create/sync tables via SchemaMapper
- ✅ Register tables in TableRegistry
- ✅ Run auto-migration (if enabled)
7. Testing > 7.1 Unit Tests
Progress: 9/9 (100%)
Completed:
- ✅ Test
SchemaMapper: - ✅ Test type mapping for all supported types (
test_schema_mapper.py) - ✅ Test primary key creation (
test_table_has_id_column_as_primary_key) - ✅ Test nullable fields (
TestSchemaMapperNullableFields) - ✅ Test enum mapping (
TestSchemaMapperEnums) - ✅ Test
GenericRepository: - ✅ Test CRUD operations with mock data (
test_generic_repository.py) - ✅ Test lifecycle hook calls (
TestControllerHooks) - ✅ Test transaction rollback on error (
TestTransactionRollback)
7. Testing > 7.2 Integration Tests
Progress: 13/13 (100%)
Completed:
- ✅ Setup testcontainers for PostgreSQL (skips if Docker unavailable)
- ✅ Create test DocType (
IntegrationTestDoc/PostgresTestDoc) - ✅ Test full flow (SQLite & Postgres - Postgres skipped without Docker):
- ✅ Register DocType (
test_register_doctype) - ✅ Create table (
test_table_created) - ✅ Insert document (
test_insert_document) - ✅ Query document (
test_query_document) - ✅ Update document (
test_update_document) - ✅ Delete document (
test_delete_document) - ✅ Test migration:
- ✅ Add field to DocType
- ✅ Run auto-migration
- ✅ Verify column added to table
8. Error Handling
Progress: 10/10 (100%)
Completed:
- ✅ Create custom exceptions (
core/exceptions.py): - ✅
DocTypeNotFoundError - ✅
ValidationError - ✅
PermissionDeniedError - ✅
DuplicateNameError - ✅
RepositoryError,EntityNotFoundError,DatabaseError,IntegrityError - ✅ Add error handling in repository (
generic_repository.py): - ✅ Catch SQLAlchemy errors (
IntegrityError,OperationalError,SQLAlchemyError) - ✅ Convert to domain exceptions (
DuplicateNameError,DatabaseError, etc.) - ✅ Log errors with context (using
logger.errorwithextradict)
9. Performance Optimizations
Progress: 13/13 (100%)
Completed:
- ✅ Add query result caching (phase-04):
- ✅ Cache
get()results by ID - ✅ Invalidate cache on save/delete
- ✅ Use Redis for distributed cache
- ✅ Add bulk operations (
generic_repository.py): - ✅
async def bulk_save(entities)- separates new/existing - ✅
async def _bulk_insert(entities)- true SQLAlchemy bulk insert - ✅ Uses
insert().values([...])for performance - ✅ Add query optimization (add indexes after the API layer exists):
- ✅ Add indexes for common queries (schema_mapper: owner, creation, Meta.indexes)
- ✅ Add parent index for child tables (efficient joins)
- ✅ Use
select_in_loadingfor relationships (load_children_for_parentsmethod) - ✅ Add query logging in dev mode (
logger.debugfor GET/LIST)
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ Can create tables from Pydantic models dynamically
- ✅ CRUD operations work with lifecycle hooks
- ✅ Migrations are generated and applied correctly
- ✅ All integration tests pass with real PostgreSQL (skips if Docker unavailable)
- ✅ No direct SQLAlchemy imports in domain layer
- ✅ Repository implements
RepositoryProtocolcorrectly
Phase 03: API Layer & Authorization
Phase: 03 Objective: Expose DocTypes via HTTP with auto-generated CRUD endpoints, implement permission system with row-level security, and add RPC support. Status: 100% Complete
1. Litestar Application Setup
Progress: 14/14 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/web/app.py - ✅ Initialize Litestar app:
- ✅ Configure CORS for development
- ✅ Add exception handlers
- ✅ Configure OpenAPI documentation
- ✅ Integrate with
dependency-injectorContainer (wire modules) - ✅ Middleware Discovery:
- ✅ Scan
MiddlewareRegistryfor registered App Middlewares. - ✅ Allow Apps to inject ASGI Middleware (e.g.
RateLimit,cors,Compression). - ✅ APM & Tracing: Support OpenTelemetry, DataDog, Sentry via standard ASGI middleware.
- ✅ Support ordering (priority).
- ✅ Add application lifecycle:
- ✅
on_startup: Initialize Container, database, discover DocTypes - ✅
on_shutdown: Close database connections, unwire Container
2. Authentication Middleware
Progress: 9/9 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/web/middleware.py - ✅ Implement
AuthMiddleware: - ✅ Extract
x-user-idheader - ✅ Extract
x-rolesheader (comma-separated) - ✅ Extract
x-tenantsheader (optional, comma-separated) - ✅ Create
UserContextobject - ✅ Store in
request.state.user - ✅ Return 401 if headers missing (configurable)
- ✅ Add middleware to Litestar app (available via
create_auth_middleware())
3. Permission System > 3.1 Permission Protocol Implementation
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/auth/rbac_permission.py - ✅ Implement
RbacPermissionAdapter: - ✅ Implement
evaluate(request: PolicyEvaluateRequest) -> PolicyEvaluateResult - ✅ Read permissions from
DocType.Meta.permissions - ✅ Match
request.principal_attributes["roles"]against allowed roles - ✅
CustomPermissionDocType created (integration pending) - ✅ Return
PolicyEvaluateResult(authorized=True/False, decision_source=DecisionSource.RBAC)
3. Permission System > 3.2 Permission Configuration
Progress: 7/7 (100%)
Completed:
- ✅ Define permission structure in DocType:
- ✅ Implement
has_permission(): - ✅ Check
requires_auth— if False and no user, allow read - ✅ Check if user has required role
- ✅ Check database overrides via
PermissionLookupService(CustomPermission DocType) - ✅ For object-level: check ownership or custom rules
- ✅ Return boolean
3. Permission System > 3.3 System Context (Elevated Operations)
Progress: 4/4 (100%)
Completed:
- ✅ Create
src/framework_m/core/system_context.py - ✅ Implement
SystemContext: - ✅ Usage in background jobs:
- ✅ Audit: All system operations logged with
principal="system"
3. Permission System > 3.4 Row-Level Security (RLS)
Progress: 13/13 (100%)
Completed:
- ✅ Implement
get_permitted_filters(): - ✅ For standard users: add
WHERE owner = :user_id - ✅ For admins: no filter (see all)
- ✅ For custom rules: via
Meta.rls_field(completed by Section 3.5 Team-Based Access) - ✅ Return dict of SQLAlchemy filters
- ✅ Update
GenericRepository.list(): - ✅
list_for_user()method with RLS filtering - ✅
apply_rls_filters()helper available - ✅ Merge with user-provided filters
- ✅ Apply to SQL query
- ✅ Update
GenericRepository.get(): - ✅
get_for_user()method with permission check - ✅ Raise
PermissionDeniedErrorif denied
3. Permission System > 3.5 Team-Based Access (Indie)
Progress: 5/5 (100%)
Completed:
- ✅ Add
Meta.rls_fieldoption: - ✅ Update
get_permitted_filters(): - ✅ If
rls_field = "owner"(default):WHERE owner = :user_id - ✅ If
rls_field = "team":WHERE team IN :user_teams - ✅ Support custom fields
3. Permission System > 3.6 Explicit Sharing (DocumentShare)
Progress: 6/6 (100%)
Completed:
- ✅ Create built-in
DocumentShareDocType: - ✅ Update
get_permitted_filters()to include shares viaget_rls_filters_with_shares(): - ✅ Add share management API:
- ✅
POST /api/v1/share— Create share - ✅
DELETE /api/v1/share/{id}— Remove share - ✅
GET /api/v1/{doctype}/{id}/shares— List shares for a doc
3. Permission System > 3.7 Indie Mode: Permission Conveniences
Progress: 14/14 (100%)
Completed:
- ✅ Create
src/framework_m/core/decorators.py(if not exists) - ✅ Implement
@requires_permission(action: PermissionAction): - ✅ Internally builds
PolicyEvaluateRequestfromself.user,self.doctype_name - ✅ Calls
permission.evaluate(request) - ✅ Raises
PermissionDeniedErrorif not authorized - ✅ Works on Controller methods
- ✅ Add to
BaseController: - ✅ Add to
BaseController: - ✅ Verify: All auto-generated CRUD routes (Section 4) automatically call
permission.evaluate(): - ✅
POST /api/v1/{doctype}→ checksCREATEpermission (verified via test) - ✅
GET /api/v1/{doctype}/{id}→ checksREADpermission (verified via test) - ✅
PUT /api/v1/{doctype}/{id}→ checksWRITEpermission (verified via test) - ✅
DELETE /api/v1/{doctype}/{id}→ checksDELETEpermission (verified via test) - ✅ No manual code required for indie devs using auto-CRUD (verified via test)
4. Auto-CRUD Router > 4.1 Meta Router Implementation
Progress: 6/6 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/web/meta_router.py - ✅ Implement
create_crud_routes(doctype_class: type[BaseDocType]): - ✅ Check Opt-in: Verify
DocType.Meta.api_resource is True. Skip if False. - ✅ Generate 5 routes per DocType
- ✅ Inject repository and permission service
- ✅ Parse filters from JSON string via
_parse_filters()
4. Auto-CRUD Router > 4.2 List Endpoint
Progress: 5/5 (100%)
Completed:
- ✅ Create
GET /api/v1/{doctype}: - ✅ Accept query parameters:
limit,offset,filters,order_by - ✅ Parse filters from JSON string
- ✅ Call repository
list_entities()with RLS filters viaapply_rls_filters() - ✅ Return paginated response with metadata:
4. Auto-CRUD Router > 4.3 Create Endpoint
Progress: 6/6 (100%)
Completed:
- ✅ Create
POST /api/v1/{doctype}: - ✅ Validate request body against Pydantic model
- ✅ Check
CREATEpermission via_check_permission() - ✅ Set
ownerto current user (data["owner"] = user_id) - ✅ Call repository
save() - ✅ Return 201 with created document
4. Auto-CRUD Router > 4.4 Read Endpoint
Progress: 6/6 (100%)
Completed:
- ✅ Create
GET /api/v1/{doctype}/{id}: - ✅ Call repository
get(id) - ✅ Check
READpermission - ✅ Return 404 if not found (via
NotFoundException) - ✅ Return 403 if permission denied
- ✅ Return document
4. Auto-CRUD Router > 4.5 Update Endpoint
Progress: 7/7 (100%)
Completed:
- ✅ Create
PUT /api/v1/{doctype}/{id}: - ✅ Load existing document via
repo.get() - ✅ Check
WRITEpermission - ✅ Check if submitted (deny if immutable) via
_check_submitted() - ✅ Merge changes via
entity.model_copy(update=data) - ✅ Call repository
save() - ✅ Return updated document
4. Auto-CRUD Router > 4.6 Delete Endpoint
Progress: 6/6 (100%)
Completed:
- ✅ Create
DELETE /api/v1/{doctype}/{id}: - ✅ Load document
- ✅ Check
DELETEpermission - ✅ Check if submitted (deny if immutable) via
_check_submitted() - ✅ Call repository
delete() - ✅ Return 204 No Content
4. Auto-CRUD Router > 4.7 Router Registration
Progress: 5/5 (100%)
Completed:
- ✅ Implement
create_meta_router(): - ✅ Get all DocTypes from MetaRegistry
- ✅ For each DocType with
api_resource=True, callcreate_crud_routes() - ✅ Register all routes with Litestar
- ✅ Return Router instance
5. RPC System > 5.1 Whitelisted Controller Methods
Progress: 13/13 (100%)
Completed:
- ✅ Create
@whitelistdecorator: - ✅ Mark controller methods as publicly callable
- ✅ Store metadata on method (
WHITELIST_ATTR) - ✅
is_whitelisted()helper function - ✅
get_whitelist_options()helper function - ✅ Create
POST /api/v1/rpc/{doctype}/{method}: - ✅ Load DocType controller
- ✅ Check if method has
@whitelistdecorator - ✅ Validate method exists
- ✅ Parse request body as method arguments
- ✅ Instantiate controller with document (if doc_id provided)
- ✅ Call method
- ✅ Return result
5. RPC System > 5.2 Arbitrary RPC Functions
Progress: 16/16 (100%)
Completed:
- ✅ Create
@rpcdecorator for standalone functions: - ✅ Register function in RPC registry (
RpcRegistrysingleton) - ✅ Store function path (e.g.,
my_app.api.send_email) - ✅
is_rpc_function()helper - ✅
get_rpc_options()helper - ✅ Create
POST /api/v1/rpc/fn/{dotted.path}: - ✅ Parse dotted path (e.g.,
my_app.api.send_email) - ✅ Look up function in registry
- ✅ Validate function has
@rpcdecorator - ✅ Parse request body as function arguments
- ✅ Call function
- ✅ Return result
- ✅ Add permission check for RPC:
- ✅ Support
@rpc(permission="custom_permission") - ✅ Check permission before calling function
- ✅ Support
@rpc(allow_guest=True)for public endpoints
6. Metadata API
Progress: 11/11 (100%)
Completed:
- ✅ Create
GET /api/meta/{doctype}: - ✅ Get DocType class from registry
- ✅ Generate JSON Schema from Pydantic model:
- ✅ Extract layout from
Meta.layout - ✅ Extract permissions from
Meta.permissions - ✅ Return:
- ✅ Add field metadata:
- ✅ Field labels (from
Field(title=...)) - included in JSON Schema - ✅ Help text (from
Field(description=...)) - included in JSON Schema - ✅ Validation rules (from Pydantic validators) - included in JSON Schema
- ✅ Field types and options - included in JSON Schema
7. OpenAPI Documentation
Progress: 10/10 (100%)
Completed:
- ✅ Configure Litestar OpenAPI:
- ✅ Set title, version, description
- ✅ Add authentication scheme (header-based:
x-user-id,x-roles) - ✅ Enable Swagger UI at
/schema/swagger - ✅ Enable ReDoc at
/schema/redoc - ✅ Enhance auto-generated docs:
- ✅ Add descriptions to CRUD endpoints (via docstrings)
- ✅ Add examples for request/response (via Pydantic models)
- ✅ Document RPC endpoints (auto-generated from route handlers)
- ✅ Add permission requirements to docs (via security schemes)
8. Error Handling
Progress: 7/7 (100%)
Completed:
- ✅ Create exception handlers:
- ✅
ValidationError→ 400 Bad Request (validation_error_handler) - ✅
PermissionDeniedError→ 403 Forbidden (permission_denied_handler) - ✅
DocTypeNotFoundError→ 404 Not Found (not_found_handler) - ✅
DuplicateNameError→ 409 Conflict (duplicate_name_handler) - ✅ Generic exceptions → 500 Internal Server Error (
framework_error_handler) - ✅ Return consistent error format:
9. Request/Response DTOs
Progress: 7/7 (100%)
Completed:
- ✅ Use Litestar DTOs for validation:
- ✅ Auto-generate from Pydantic models (via Litestar)
- ✅ Add DTO for list response (pagination):
PaginatedResponse[T] - ✅ Add DTO for error responses:
ErrorResponse - ✅ Implement response filtering:
- ✅ Exclude sensitive fields based on permissions (via field selection)
- ✅ Support field selection via query param:
?fields=name,title
10. Testing > 10.1 Unit Tests
Progress: 8/8 (100%)
Completed:
- ✅ Test permission system:
- ✅ Test role-based access (
test_rbac_permission.py) - ✅ Test RLS filter generation (
test_rls.py) - ✅ Test object-level permissions (
test_object_level_permissions.py) - ✅ Test RPC system:
- ✅ Test
@whitelistdecorator (test_whitelist_decorator.py) - ✅ Test
@rpcdecorator (test_rpc_decorator.py) - ✅ Test dotted path resolution (
test_rpc_routes.py)
10. Testing > 10.2 Integration Tests
Progress: 15/15 (100%)
Completed:
- ✅ Test CRUD endpoints (
test_api_endpoints.py): - ✅ Test create with valid data
- ✅ Test create with invalid data (validation)
- ✅ Test create without permission (403)
- ✅ Test list with RLS (only see own docs)
- ✅ Test update immutable doc (covered by existing
test_meta_router.py) - ✅ Test delete with permission (covered by existing permission tests)
- ✅ Test RPC endpoints (
test_api_endpoints.py,test_rpc_routes.py): - ✅ Test whitelisted controller method
- ✅ Test arbitrary RPC function
- ✅ Test RPC with permissions
- ✅ Test with real HTTP client (
test_real_http_client.py): - ✅ Uses
httpx.AsyncClientagainst real uvicorn server - ✅ Tests: list endpoint, create endpoint, health check
- ✅ Manual testing scripts available in
examples/folder
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ All CRUD endpoints work with permissions (verified via
test_meta_router.py,test_api_endpoints.py) - ✅ RLS filters are applied correctly (verified via
test_rls.py,test_object_level_permissions.py) - ✅ RPC system works for controller methods and functions (verified via
test_rpc_routes.py) - ✅ OpenAPI docs are generated correctly (SwaggerUI + ReDoc enabled)
- ✅ Error handling returns proper status codes (verified via
test_app.py) - ✅ Integration tests pass with real HTTP requests (verified via
test_real_http_client.py)
Edge Cases to Handle > Child Table Permissions
Progress: 4/4 (100%)
Completed:
- ✅ Define: Child tables inherit parent's RLS by default (
Meta.is_child_table = True) - ✅ Child rows are not independently permission-checked (
api_resource = False) - ✅ Loading parent loads all its children (no separate RLS query)
- ✅ Document: If independent child access needed, make it a separate DocType (tests in
test_child_table_permissions.py)
Edge Cases to Handle > Link Field Data Leakage
Progress: 3/3 (100%)
Completed:
- ✅ When serializing a doc with Link fields, do NOT auto-include linked doc data (Link fields store UUID, not embedded objects)
- ✅ If linked doc data is needed, make a separate API call (permission checked) - documented pattern
- ✅ Optional:
?expand=customerparam design documented (checks permission before expanding)
Edge Cases to Handle > Bulk Operations & RLS
Progress: 3/3 (100%)
Completed:
- ✅
GenericRepository.delete_many_for_user(filters)applies RLS - ✅
GenericRepository.update_many_for_user(filters, data)applies RLS - ✅ User can only bulk-modify docs they have access to (tests in
test_bulk_operations_rls.py)
Phase 04: Background Jobs & Events
Phase: 04 Objective: Implement asynchronous job processing, event-driven architecture, and webhook system with pluggable backends (Redis, NATS, In-Memory). Status: 98% Complete
0. Backend Selection (Cross-Platform) > 0.2 Dev Mode (No External Deps)
Progress: 3/3 (100%)
Completed:
- ✅ Implement
InMemoryJobQueuefor local dev (asyncio.Queue). - ✅ Implement
InMemoryEventBusfor local dev. - ✅ Auto-detect: If
NATS_URLnot set, use in-memory.
1. Taskiq + NATS Integration (Primary) > 1.1 Taskiq Setup
Progress: 8/8 (100%)
Completed:
- ✅ Add dependencies:
taskiq,taskiq-nats. - ✅ Create
src/framework_m/adapters/jobs/taskiq_adapter.py - ✅ Configure Taskiq with NATS JetStream:
- ✅ Set NATS connection URL from environment (
NATS_URL) - ✅ Configure job timeout (default: 300s)
- ✅ Configure max retries (default: 3)
- ✅ Use
PullBasedJetStreamBrokerfor reliable delivery - ✅ Create broker instance:
1. Taskiq + NATS Integration (Primary) > 1.2 Job Queue Protocol Implementation
Progress: 7/7 (100%)
Completed:
- ✅ Implement
TaskiqJobQueueAdapter: - ✅
async def enqueue(job_name: str, **kwargs) -> str: - ✅ Get registered task
- ✅ Call
.kiq()to enqueue - ✅ Return job ID
- ✅
async def schedule(job_name: str, cron: str, **kwargs): - ✅ Use
TaskiqSchedulerwith cron triggers
1. Taskiq + NATS Integration (Primary) > 1.3 Job Registration
Progress: 4/4 (100%)
Completed:
- ✅ Create job decorator
@job: - ✅ Implement job registry:
- ✅ Store all
@broker.taskdecorated functions - ✅ Auto-discover on startup
2. Worker Process > 2.1 Worker Implementation
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m/cli/worker.py - ✅ Implement worker command:
- ✅ Worker startup:
- ✅ Initialize database connection
- ✅ Discover and register all jobs
- ✅ Start Taskiq worker
- ✅ Listen for jobs from NATS JetStream
2. Worker Process > 2.2 Job Context
Progress: 10/10 (100%)
Completed:
- ✅ Create job context for dependency injection:
- ✅ Provide database session
- ✅ Provide repository factory
- ✅ Provide event bus
- ✅ Pass to job functions
- ✅ Add job metadata:
- ✅ Job ID
- ✅ Enqueued time
- ✅ Started time
- ✅ User context (Must re-hydrate from job arguments if applicable)
3. Scheduler > 3.1 Cron Jobs
Progress: 8/8 (100%)
Completed:
- ✅ Support Taskiq's native cron syntax:
- ✅ Create
ScheduledJobDocType: - ✅
name: str- Job identifier - ✅
function: str- Dotted path to function - ✅
cron_expression: str- Cron syntax - ✅
enabled: bool- Active/inactive - ✅
last_run: datetime | None - ✅
next_run: datetime | None
3. Scheduler > 3.2 Dynamic Scheduler
Progress: 3/4 (75%)
Completed:
- ✅ Implement dynamic job scheduling:
- ✅ Load
ScheduledJobDocTypes from database - ✅ Register with Taskiq at startup
Pending:
- ⏳ Support adding/removing jobs without restart (via signal) NOT NEEDED: Worker restart is acceptable for schedule changes; k8s rolling updates handle this gracefully. If needed in future, can use NATS pub/sub to signal workers in Phase 06+ (Ops/Deployment).
4. Event Bus > 4.1 NATS Event Bus Implementation
Progress: 9/9 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/events/nats_event_bus.py - ✅ Implement
NatsEventBusAdapter: - ✅
async def publish(topic: str, event: BaseModel): - ✅ Serialize event to JSON
- ✅ Publish to NATS JetStream subject
- ✅
async def subscribe(topic: str, handler: Callable): - ✅ Subscribe to NATS JetStream subject
- ✅ Deserialize event
- ✅ Call handler function
4. Event Bus > 4.2 Event Types
Progress: 7/7 (100%)
Completed:
- ✅ Create base event class:
- ✅ Define standard events:
- ✅
DocCreated - ✅
DocUpdated - ✅
DocDeleted - ✅
DocSubmitted - ✅
DocCancelled
4. Event Bus > 4.3 Event Publishing from Lifecycle Hooks
Progress: 6/6 (100%)
Completed:
- ✅ Update
GenericRepository: - ✅ Inject event bus
- ✅ Publish
DocCreatedafter insert - ✅ Publish
DocUpdatedafter update - ✅ Publish
DocDeletedafter delete - ✅ Add event publishing to controller hooks:
5. Webhook System > 5.1 Webhook DocType
Progress: 9/9 (100%)
Completed:
- ✅ Create
WebhookDocType: - ✅
name: str - ✅
event: str- Event to listen to (e.g., "doc.created") - ✅
doctype_filter: str | None- Filter by DocType - ✅
url: str- Webhook endpoint URL - ✅
method: str- HTTP method (POST, PUT) - ✅
headers: dict- Custom headers - ✅
enabled: bool - ✅
secret: str- For signature verification
5. Webhook System > 5.2 Webhook Listener
Progress: 6/6 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/webhooks/listener.py - ✅ Implement webhook listener:
- ✅ Subscribe to all events
- ✅ Load active webhooks from database
- ✅ Filter events by webhook configuration
- ✅ Trigger HTTP call to webhook URL
5. Webhook System > 5.3 Webhook Delivery
Progress: 9/9 (100%)
Completed:
- ✅ Implement webhook delivery:
- ✅ Use
httpxfor async HTTP calls - ✅ Add signature header (HMAC-SHA256 with secret)
- ✅ Set timeout (default: 30s)
- ✅ Handle errors and retries
- ✅ Add retry logic:
- ✅ Retry on failure (exponential backoff)
- ✅ Max retries: 3
- ✅ Log failed deliveries
5. Webhook System > 5.4 Webhook Logs
Progress: 8/8 (100%)
Completed:
- ✅ Create
WebhookLogDocType: - ✅
webhook: str- Reference to Webhook - ✅
event: str- Event that triggered - ✅
status: str- Success/Failed - ✅
response_code: int - ✅
response_body: str - ✅
error: str | None - ✅
timestamp: datetime
6. Job Monitoring > 6.1 Job Status Tracking
Progress: 13/13 (100%)
Completed:
- ✅ Create
JobLogDocType: - ✅
job_id: str - ✅
job_name: str - ✅
status: str- Queued/Running/Success/Failed - ✅
enqueued_at: datetime - ✅
started_at: datetime | None - ✅
completed_at: datetime | None - ✅
error: str | None - ✅
result: dict | None - ✅ Update job execution to log status:
- ✅ Create log entry on enqueue
- ✅ Update on start
- ✅ Update on completion/failure
6. Job Monitoring > 6.2 Job Management API
Progress: 5/5 (100%)
Completed:
- ✅ Create endpoints:
- ✅
GET /api/v1/jobs- List jobs - ✅
GET /api/v1/jobs/{job_id}- Get job status - ✅
POST /api/v1/jobs/{job_id}/cancel- Cancel job - ✅
POST /api/v1/jobs/{job_id}/retry- Retry failed job
6. Job Monitoring > 6.3 Job Monitor (Admin UI)
Progress: 3/6 (50%)
Completed:
- ✅ Option A: Native Desk UI (IMPLEMENTED):
- ✅
Job LogList View (auto-generated viaapi_resource=True). - ✅ Shows Status, Error, Duration (
duration_secondsproperty).
Pending:
- ⏳
Option B: Taskiq Dashboard (External)- NOT NEEDED for MVP: Native JobLog UI is sufficient for debugging. External dashboards can be mounted in Phase 06+ (Ops/Deployment) if production monitoring requires deeper worker introspection. - ⏳ Mount
taskiq-dashboard(if available) or similar tool. - ⏳ Useful for sysadmins to debug worker health.
4. Real-time Events (WebSockets) > 4.1 WebSocket Protocol (The Port)
Progress: 4/4 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/socket.py - ✅ Define
SocketProtocol: - ✅
async def broadcast(topic: str, message: dict) - ✅
async def send_to_user(user_id: str, message: dict)
4. Real-time Events (WebSockets) > 4.2 NATS Backplane (The Adapter)
Progress: 7/7 (100%)
Completed:
- ✅ Create
tests/adapters/socket/test_nats_socket.py - ✅ Write tests using testcontainers-nats to verify Pub/Sub.
- ✅ Create
src/framework_m/adapters/socket/nats_socket.py - ✅ Implement
NatsSocketAdapter: - ✅ On Boot: Subscribe to
framework.events.*. - ✅ On Event:
await nc.publish(subject, json.dumps(msg).encode()). - ✅ On Receive (Sub): Forward to local connected Websocket clients (Connection Manager).
4. Real-time Events (WebSockets) > 4.3 WebSocket Endpoint (Litestar)
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/web/socket.py - ✅ Implement
ConnectionManager: - ✅ Store active connections
Dict[UserId, List[WebSocket]]. - ✅ Add route
WS /api/v1/stream: - ✅ Authenticate user (Query param token).
- ✅ Upgrade connection.
- ✅ Register with
ConnectionManager. - ✅ Listen for client disconnect.
7. Testing > 7.1 Unit Tests
Progress: 6/6 (100%)
Completed:
- ✅ Test job registration:
- ✅ Test
@jobdecorator - ✅ Test job registry
- ✅ Test event bus:
- ✅ Test publish/subscribe
- ✅ Test event serialization
7. Testing > 7.2 Integration Tests
Progress: 13/13 (100%)
Completed:
- ✅ Test job execution:
- ✅ Enqueue job
- ✅ Verify job runs
- ✅ Check job result
- ✅ Test scheduled jobs:
- ✅ Register cron job
- ✅ Verify execution at scheduled time (use time mocking)
- ✅ Test webhooks:
- ✅ Create webhook
- ✅ Trigger event
- ✅ Verify HTTP call made
- ✅ Check webhook log
- ✅ Use testcontainers for NATS
8. CLI Commands
Progress: 5/5 (100%)
Completed:
- ✅ Add job management commands:
- ✅
m worker- Start worker process - ✅
m job:list- List registered jobs - ✅
m job:run <name>- Run job immediately - ✅
m job:status <id>- Check job status
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ Jobs can be enqueued and executed
- ✅ Scheduled jobs run at correct times
- ✅ Events are published and received
- ✅ Webhooks are triggered on events
- ✅ Job logs are created and updated
- ✅ Worker process starts and processes jobs
Phase 05: CLI & Developer Tools
Phase: 05
Objective: Build a comprehensive CLI tool (m) to replace Frappe's "bench", with commands for development, deployment, and management.
Status: 97% Complete
1. CLI Framework Setup
Progress: 5/5 (100%)
Completed:
- ✅ Create
src/framework_m/cli/main.py - ✅ Use
cycloptsfor CLI framework (native async, better type support) - ✅ Setup main CLI app:
- ✅ Add version command:
- ✅ Add help documentation for all commands
1. CLI Framework Setup > 1.1 Pluggable CLI Architecture (Entry Points)
Progress: 11/11 (100%)
Completed:
- ✅ Define Entry Point Group:
framework_m.cli_commands - ✅ Implement Plugin Loader in
plugin_loader.py: - ✅ Use
importlib.metadata.entry_points(group="framework_m.cli_commands") - ✅ Iterate over registered entry points
- ✅ If entry point is a
cyclopts.App:app.command(plugin_app, name=ep.name) - ✅ If entry point is a function:
app.command(plugin_func, name=ep.name) - ✅ Goal: 3rd party apps (and
framework-m-studio) can add commands tomwithout modifying core. - ✅ Customization Philosophy:
- ✅ Standard commands (
start,test) are strict relays. - ✅ For customization (e.g.,
start-mqtt,super-test): Users MUST register a custom command via entry points. - ✅ Result:
mremains a clean, standard runner.
2. Development Server (Uvicorn Relay) > 2.1 Start Command
Progress: 5/5 (100%)
Completed:
- ✅ Implement
m start: - ✅ Implementation: Wrapper around
uvicorn. - ✅ Argument Forwarding: Uses cyclopts Parameter for options.
- ✅ Usage:
m start --workers 4 --log-level debug - ✅ Value Add: Sets
PYTHONPATH, auto-detects app, transparently passes args.
2. Development Server (Uvicorn Relay) > 2.2 Worker Command (Taskiq Relay)
Progress: 4/4 (100%)
Completed:
- ✅ Implement
m worker: - ✅ Implementation: Native Taskiq integration (better than wrapper).
- ✅ Options:
--concurrency,--verbose. - ✅ Usage:
m worker --concurrency 8
2. Development Server (Uvicorn Relay) > 2.3 Studio Command (Litestar Relay)
Progress: 4/4 (100%)
Completed:
- ✅ Implement
m studio: - ✅ Implementation: Wrapper around
uvicornfor Studio app. - ✅ Options:
--host,--port,--reload,--log-level. - ✅ Usage:
m studio --port 9000 --reload
3. Database Commands (Alembic Relay) > 3.1 Migration Commands
Progress: 5/5 (100%)
Completed:
- ✅ Implement
m migrate: - ✅ Implementation: Wrapper around MigrationManager (uses Alembic).
- ✅ Commands:
migrate,create,rollback,status,history,init. - ✅ Usage:
m migrate create "add users" --autogenerate - ✅ Value Add: Auto-detects schema changes, supports custom DB URL, env vars.
4. Scaffolding (Cruft/Cookiecutter Relay) > 4.1 New App (Starter Template)
Progress: 4/4 (100%)
Completed:
- ✅ Implement
m new:app: - ✅ Implementation: Wrapper around
cruft(cookiecutter). - ✅ Options:
--template,--checkout,--no-input. - ✅ Usage:
m new:app myapp --checkout main
4. Scaffolding (Cruft/Cookiecutter Relay) > 4.2 New DocType (Jinja Relay)
Progress: 26/26 (100%)
Completed:
- ✅ Implement
m new:doctype <name>: - ✅ Implementation: Template rendering (embedded templates).
- ✅ Output:
doctype.py,controller.py,test_*.py,__init__.py. - ✅ App Detection:
--app> pyproject.toml > interactive prompt. - ✅ CLI Parameter (Unattended/Automation):
- ✅
--app <app_name>: Explicit app target. - ✅ If
--appprovided, use it directly (no prompt). - ✅ Automation Friendly: Scripts can pass
--appto avoid prompts. - ✅ Auto-Detection from CWD:
- ✅ If
--appnot provided, attempt to detect from current directory. - ✅ Check if CWD is inside an app's source tree.
- ✅ Look for
pyproject.tomlin CWD or parent directories. - ✅ Read
[project] nameto determine app. - ✅ Interactive Prompt (Default Fallback):
- ✅ If detection fails AND stdin is interactive (TTY):
- ✅ List installed apps from
framework_m.appsentry points. - ✅ Prompt user to select:
"Which app? [my_app, other_app]". - ✅ If stdin is NOT interactive (pipe/automation):
- ✅ Fail with clear error:
"Cannot detect app. Use --app <name>.". - ✅ Exit code 1 (enables CI/automation to catch failures).
- ✅ Implementation: check
require_app()innew.py - ✅ Scaffold Output Location:
- ✅ Files created in:
{cwd}/doctypes/{doctype_name}/ - ✅ Structure:
__init__.py,doctype.py,controller.py,test_*.py - ✅ Templates:
- ✅ Embedded templates in
new.py(no external Jinja2 files needed).
5. Testing & Quality (Standard Tool Relays) > 5.1 Test Relay
Progress: 5/5 (100%)
Completed:
- ✅ Implement
m test: - ✅ Command:
pytest - ✅ Options:
--verbose,--coverage,-k. - ✅ Usage:
m test -k "user" --verbose - ✅ Value Add: Configures
PYTHONPATH.
5. Testing & Quality (Standard Tool Relays) > 5.2 Lint/Format Relay
Progress: 6/6 (100%)
Completed:
- ✅ Implement
m lint: - ✅ Command:
ruff check . --fix - ✅ Implement
m format: - ✅ Command:
ruff format . - ✅ Implement
m typecheck: - ✅ Command:
mypy .
6. Configuration Management > 6.1 Config File
Progress: 4/4 (100%)
Completed:
- ✅ Create
framework_config.tomlstructure: - ✅ Supports
[framework],[apps]sections - ✅ Load/save with TOML format
- ✅ Auto-detect in CWD or parent directories
6. Configuration Management > 6.2 Config Commands
Progress: 2/2 (100%)
Completed:
- ✅ Implement
m config:show: Display current config. - ✅ Implement
m config:set <key> <value>: Update config.
7. Utility Relays > 7.1 Console (IPython Relay)
Progress: 4/4 (100%)
Completed:
- ✅ Implement
m console: - ✅ Implementation: Wrapper around
ipythonorpython -m asyncio. - ✅ Value Add: Pre-imports framework, async support.
- ✅ Options:
--no-ipythonfor plain Python.
7. Utility Relays > 7.2 System Info
Progress: 3/3 (100%)
Completed:
- ✅ Implement
m info: - ✅ Show versions (Framework, Python).
- ✅
--verbosefor platform and service info.
7. Utility Relays > 7.3 Routes
Progress: 2/2 (100%)
Completed:
- ✅ Implement
m routes: - ✅ Points to OpenAPI/Swagger docs.
8. Build Commands > 8.1 Frontend Build
Progress: 3/3 (100%)
Completed:
- ✅ Implement
m build(placeholder): - ✅ Relay to frontend build system (see Phase 09).
- ✅ Detects package.json and runs
npm run build.
8. Build Commands > 8.2 Docker Build
Progress: 4/4 (100%)
Completed:
- ✅ Implement
m build:docker: - ✅ Command: Wrapper around
docker build. - ✅ Value Add: Reads image name/tag from
framework_config.toml. - ✅ Options:
--tag,--file,--no-cache,--push.
9. Pluggable Extensions
Progress: 1/4 (25%)
Completed:
- ✅ Plugin loader implemented (
load_plugins())
Pending:
- ⏳
m studio(external) - ⏳
m docs:generate(external) - ⏳
m codegen(external)
10. CLI Entry Point
Progress: 2/2 (100%)
Completed:
- ✅ Configure
pyproject.tomlscripts:m = "framework_m.cli.main:app" - ✅ Test installation (
m --help) - 22 commands registered.
Phase 06: Built-in DocTypes & Core Features
Phase: 06 Objective: Implement essential built-in DocTypes (User, Role, Permission) and core features like file attachments, audit logging, and printing. Status: 99% Complete
1. Identity & Access Management (PIM) > 1.1 Identity Provider Protocol
Progress: 4/4 (100%)
Completed:
- ✅ Create
IdentityProtocol(Interface): - ✅
get_user(id: str) -> User - ✅
authenticate(credentials) -> Token - ✅
get_attributes(user) -> dict[str, Any](ABAC replacement for get_roles)
1. Identity & Access Management (PIM) > 1.2 User DocTypes (Pluggable)
Progress: 8/8 (100%)
Completed:
- ✅ Mode A: Local (Indie):
- ✅
LocalUser(SQL Table): Stores email, password_hash, full_name. - ✅
LocalIdentityAdapter: argon2 password hashing, JWT generation. - ✅ Mode B: Federated (Enterprise):
- ✅
FederatedIdentityAdapter(Proxy): - ✅ No SQL Table required.
- ✅ Hydrates from Auth Header (
X-User-ID,X-Email) viahydrate_from_headers(). - ✅
UserPreferencesDocType stores settings locally.
1. Identity & Access Management (PIM) > 1.3 User Controller (Adapter)
Progress: 4/4 (100%)
Completed:
- ✅ Implement
UserManager: - ✅ Delegates to configured
IdentityProviderviaIdentityProtocol. - ✅ Abstraction layer:
user = await user_manager.get(id). - ✅ Additional
create()method for Indie mode with password hashing.
1. Identity & Access Management (PIM) > 1.4 Auth API (Indie Mode)
Progress: 8/8 (100%)
Completed:
- ✅ Create
GET /api/v1/auth/me: - ✅ Returns current user context (or 401).
- ✅ Create
POST /api/v1/auth/login(Indie Only): - ✅ Accepts
username,password. - ✅ Validates against
LocalUserviaUserManager.authenticate(). - ✅ Returns JWT token.
- ✅ Create
POST /api/v1/auth/logout: - ✅ Returns success message (JWT auth is client-side logout).
1. Identity & Access Management (PIM) > 1.5 Authentication Strategies (Multi-Method)
Progress: 24/24 (100%)
Completed:
- ✅ Create
AuthenticationProtocol(Interface): - ✅
supports(headers: Mapping) -> bool— Can this strategy handle this request? - ✅
authenticate(headers: Mapping) -> UserContext | None— Extract user from request. - ✅ Built-in Strategies:
- ✅
SessionCookieAuth— Browser sessions via cookies. - ✅
BearerTokenAuth— JWT/OAuth2 access tokens. - ✅
ApiKeyAuth—X-API-Keyheader for scripts/integrations. - ✅
HeaderAuth— Federated mode gateway header hydration. - ✅
BasicAuth— HTTP Basic for CLI tools. - ✅ Strategy Chain (
AuthChain): - ✅ Try each strategy in priority order.
- ✅ First successful match wins.
- ✅ Configurable order via
framework_config.toml(create_auth_chain_from_config). - ✅ API Key DocType (Indie Mode):
- ✅
ApiKeyDocType: - ✅
key_hash: str— Hashed API key (never store plaintext, excluded from serialization). - ✅
user_id: str— Owner of the key. - ✅
name: str— Human-readable label. - ✅
scopes: list[str]— Optional permission scopes. - ✅
expires_at: datetime | None— Expiration. - ✅
last_used_at: datetime | None— Usage tracking. - ✅
POST /api/v1/auth/api-keys— Create new key. - ✅
DELETE /api/v1/auth/api-keys/{id}— Revoke key. - ✅
GET /api/v1/auth/api-keys— List user's keys.
1. Identity & Access Management (PIM) > 1.6 Social Login (OAuth2/OIDC)
Progress: 26/27 (96%)
Completed:
- ✅ Option A: Built-in OAuth2 (Indie):
- ✅ Supported Providers (config structure ready):
- ✅ Google (well-known URLs configured)
- ✅ GitHub (well-known URLs configured)
- ✅ Microsoft (well-known URLs configured)
- ✅ Generic OIDC (any compliant provider via
get_oidc_well_known) - ✅ Configuration via
framework_config.toml: - ✅ Endpoints:
- ✅
GET /api/v1/auth/oauth/{provider}/start— Redirect to provider. - ✅
GET /api/v1/auth/oauth/{provider}/callback— Handle callback. (Placeholder) - ✅ Option B: Federated (Enterprise):
- ✅ Delegate to Keycloak / Authelia / Auth0 via
HeaderAuthstrategy. - ✅ Framework receives headers only (
X-User-ID,X-Email). - ✅ Zero PII stored locally.
- ✅ SocialAccount DocType:
- ✅
provider: str— OAuth provider name. - ✅
provider_user_id: str— Unique ID from provider. - ✅
user_id: str— Links to local user. - ✅
email: str | None— For lookup (optional). - ✅
display_name: str— For UI display. - ✅ One User can have multiple SocialAccounts.
- ✅ Passwordless Option (Requires Section 10: Email):
- ✅
POST /api/v1/auth/magic-link— Send email with login link. - ✅
GET /api/v1/auth/magic-link/{token}— Verify and create session. - ✅
MagicLinkCredentialsadded to identity protocol - ✅ Token generation with HMAC-SHA256 signing
Pending:
- ⏳ Use
authlibfor OAuth2 flows. (Full implementation deferred)
1. Identity & Access Management (PIM) > 1.7 Session Management
Progress: 20/20 (100%)
Completed:
- ✅ Session Storage:
- ✅ Redis (Default):
RedisSessionAdapterwith JSON storage and TTL. - ✅ Database (Fallback):
DatabaseSessionAdapterfor indie apps. - ✅ Configurable via
framework_config.toml: - ✅ Session DocType (database backend):
- ✅
session_id: str— Unique session identifier. - ✅
user_id: str— Links to user. - ✅
expires_at: datetime - ✅
ip_address: str | None - ✅
user_agent: str | None - ✅ SessionProtocol Interface:
- ✅
create()— Create new session - ✅
get()— Retrieve by ID - ✅
delete()— Remove session - ✅
delete_all_for_user()— Logout all - ✅
list_for_user()— List active sessions - ✅ Session API:
- ✅
GET /api/v1/auth/sessions— List active sessions. - ✅
DELETE /api/v1/auth/sessions/{id}— Revoke session. - ✅
DELETE /api/v1/auth/sessions— Logout all.
1. Identity & Access Management (PIM) > 1.8 PII Handling (Indie Guidance)
Progress: 16/16 (100%)
Completed:
- ✅ Auth Mode Presets (
AuthModeenum incore/pii.py): - ✅ Minimal PII Pattern:
- ✅
LocalUserstores only: - ✅
email(for login/notification) - ✅
display_name(for UI) - ✅
password_hash(only ifmode = "local") - ✅ Do NOT store by default (
PII_SENSITIVE_FIELDS): - ✅ Full legal name
- ✅ Phone number
- ✅ Address
- ✅ Date of birth
- ✅ Helper:
is_sensitive_pii(field_name)to detect sensitive fields. - ✅ Data Deletion (
DeletionModeenum): - ✅
DELETE /api/v1/auth/me— Delete user account (GDPR right to erasure). - ✅
GET /api/v1/auth/me/data— Export user data (GDPR data portability). - ✅ Configurable: Hard delete vs anonymize.
2. Tenancy & Attributes (Multi-Tenant Core) > 2.1 Tenant Protocol
Progress: 5/5 (100%)
Completed:
- ✅ Create
TenantProtocol(Interface incore/interfaces/tenant.py): - ✅
get_current_tenant() -> str - ✅
get_tenant_attributes(tenant_id) -> dict - ✅
TenantContextmodel for request context - ✅ Configuration helpers:
is_multi_tenant(),get_default_tenant_id()
2. Tenancy & Attributes (Multi-Tenant Core) > 2.2 Tenancy Adapters
Progress: 12/12 (100%)
Completed:
- ✅ Mode A: Single Tenant (Indie):
- ✅
ImplicitTenantAdapter(adapters/tenant.py): - ✅
tenant_id="default"(configurable). - ✅
attributes={"plan": "unlimited", "features": "*"}. - ✅
get_context()returnsTenantContextwithis_default=True. - ✅ Factory:
create_tenant_adapter_from_headers()auto-selects. - ✅ Mode B: Multi-Tenant (Enterprise):
- ✅
HeaderTenantAdapter(adapters/tenant.py): - ✅ Extracts
X-Tenant-IDfrom Gateway headers. - ✅ Extracts
X-Tenant-Attributes(JSON) for feature flags, plan. - ✅
get_context()parses headers intoTenantContext. - ✅ Benefit: Feature toggling per tenant without DB lookup.
2. Tenancy & Attributes (Multi-Tenant Core) > 2.3 Attributes (The New Roles)
Progress: 7/7 (100%)
Completed:
- ✅ Goal: Replace "Roles" with refined "Attributes" (ABAC).
- ✅ Implementation (in
UserContext): - ✅
user.attributes(dict): Stores{"department": "sales", "level": 5, "roles": ["admin"]}. - ✅
user.get_attribute(key, default)— Get attribute value. - ✅
user.has_attribute(key, value)— Check attribute equality. - ✅ Legacy Support:
user.has_role("x")checks bothroleslist ANDattributes.roles. - ✅
is_system_useruseshas_role("System")for consistency.
3. Permission Management (Pluggable) > 3.1 Permission Protocol
Progress: 7/7 (100%)
Completed:
- ✅ Create
PermissionProtocol(core/interfaces/permission.py): - ✅
PolicyEvaluateRequest- Stateless authorization request - ✅
PolicyEvaluateResult- Result with authorized, decision_source, reason - ✅
async def evaluate(request) -> PolicyEvaluateResult - ✅
async def get_permitted_filters(...) -> dict- RLS support - ✅
PermissionActionenum (read, write, create, delete, submit, cancel, amend) - ✅
DecisionSourceenum (rbac, abac, rebac, combo, custom)
3. Permission Management (Pluggable) > 3.2 Permission Adapters
Progress: 18/18 (100%)
Completed:
- ✅ Mode A: Standard (Indie) -
RbacPermissionAdapter: - ✅ Reads permissions from
DocType.Meta.permissions. - ✅ Checks
CustomPermissionrules from database. - ✅ Role matching against
principal_attributes["roles"]. - ✅ Admin role bypass (configurable).
- ✅ RLS via
get_permitted_filters()usingMeta.rls_field. - ✅ Mode B: Citadel Policy (Enterprise) -
CitadelPolicyAdapter: - ✅
AuthorizationRequestmodel (Cedar-compatible format): - ✅
Principal:user.id - ✅
Action:doctype:action(e.g.,Invoice:create) - ✅
Resource:doctype:name(e.g.,Invoice:INV-001) - ✅
TenantID:user.tenant_id - ✅
Context:doc.as_dict() - ✅
PrincipalAttributes:user.attributes(Diet Claims) - ✅
AuthorizationResponsemodel withallowed,reason,policy_id - ✅ Calls configurable policy endpoint (Cedar/OPA)
- ✅ Fallback behavior on error (configurable)
- ✅ Configuration via
[permissions.citadel]inframework_config.toml
4. File Management > 4.1 File DocType
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/file.py - ✅ Define
FileDocType: - ✅
name: str- File ID (inherited from BaseDocType) - ✅
file_name: str- Original filename - ✅
file_url: str- Storage URL - ✅
file_size: int- Size in bytes - ✅
content_type: str- MIME type - ✅
attached_to_doctype: str | None - ✅
attached_to_name: str | None - ✅
is_private: bool- Private/public file (default: True)
4. File Management > 4.2 File Upload API
Progress: 9/9 (100%)
Completed:
- ✅ Create
POST /api/v1/file/upload(adapters/web/file_routes.py): - ✅ Accept multipart/form-data via
UploadFile - ✅ Validate file size (max 10MB default, configurable)
- ✅ Validate file type (configurable whitelist)
- ✅ Generate unique storage path (YYYY/MM/DD/random_filename)
- ✅ Create File DocType record
- ✅ Return file URL and metadata
- ✅ Configuration via
[files]inframework_config.toml - ✅ Response models:
FileUploadResponse,FileDeleteResponse
4. File Management > 4.3 File Download API
Progress: 8/8 (100%)
Completed:
- ✅ Create
GET /api/v1/file/{file_id}: - ✅ Check permissions for private files (RLS on owner)
- ✅ Prepare streaming response from storage
- ✅ Set correct
Content-Typeheader - ✅ Set
Content-Dispositionheader (inline/attachment) - ✅ Support
?inline=truefor browser display - ✅ Create
GET /api/v1/file/{file_id}/info: - ✅ Return metadata without downloading content
4. File Management > 4.4 Storage Adapters
Progress: 13/13 (100%)
Completed:
- ✅ Implement
LocalStorageAdapter(adapters/storage/local.py): - ✅ Save files to local directory with atomic writes
- ✅ Organize by date (YYYY/MM/DD) via path parameter
- ✅ Generate unique filenames (handled by file_routes)
- ✅ Path traversal protection
- ✅ Async operations via
aiofiles - ✅ Implement
S3StorageAdapter(adapters/storage/s3.py): - ✅ Use
aioboto3for async S3 operations - ✅ Presigned URLs for direct client uploads (PUT method)
- ✅ Multipart upload for large files (>25MB)
- ✅ Configure bucket and region from
framework_config.toml - ✅ Support S3-compatible services (MinIO, DigitalOcean Spaces)
- ✅
InMemoryStorageAdapterfor testing (adapters/storage/memory.py)
5. Audit Logging (Pluggable) > 5.1 Audit Log Protocol
Progress: 5/5 (100%)
Completed:
- ✅ Create
AuditLogProtocol(core/interfaces/audit.py): - ✅
AuditEntrymodel (user, action, doctype, document_id, changes, metadata) - ✅
async def log(...)- Record audit entry - ✅
async def query(...)- Query with filters/pagination - ✅
InMemoryAuditAdapterfor testing
5. Audit Logging (Pluggable) > 5.2 Audit Adapters
Progress: 6/7 (86%)
Completed:
- ✅ Mode A: Database (Indie):
- ✅
DatabaseAuditAdapter: Writes toActivityLogrecords. - ✅ Uses ActivityLog DocType from 5.3
- ✅ Mode B: External (Enterprise):
- ✅
FileAuditAdapter: Writes toaudit.log(JSONL) for Splunk/Filebeat. - ✅ Prevents main DB bloat.
Pending:
- ⏳
ElasticAuditAdapter: Writes directly to Elasticsearch (Phase 10).
5. Audit Logging (Pluggable) > 5.3 Activity Log DocType (Indie Only)
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/activity_log.py - ✅ Define
ActivityLogDocType: - ✅
user_id: str - ✅
action: str(create, read, update, delete) - ✅
doctype: str - ✅
document_id: str - ✅
timestamp: datetime - ✅
changes: dict | None - ✅
metadata: dict | None - ✅ Immutable (no write/delete permissions)
5. Audit Logging (Pluggable) > 5.4 Activity Feed API
Progress: 4/4 (100%)
Completed:
- ✅ Create
GET /api/v1/activity: - ✅ List recent activities
- ✅ Filter by user, doctype, document, action
- ✅ Paginate results (limit, offset)
6. Error Logging > 6.1 Error Log DocType
Progress: 12/12 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/error_log.py - ✅ Define
ErrorLogDocType: - ✅
title: str- Short error description - ✅
error_type: str- Exception class name - ✅
error_message: str- Full error message - ✅
traceback: str | None- Full stack trace - ✅
request_url: str | None - ✅
user_id: str | None - ✅
request_id: str | None- For log correlation - ✅
timestamp: datetime - ✅
context: dict | None- Additional context - ✅ Admin-only permissions (immutable)
6. Error Logging > 6.2 Error Logging Integration
Progress: 6/6 (100%)
Completed:
- ✅ Add global exception handler (
adapters/web/error_handler.py): - ✅ Catch all unhandled exceptions
- ✅ Create ErrorLog entry with full context
- ✅ Return user-friendly ErrorResponse (no sensitive data)
- ✅ Log to console in dev mode (configurable)
- ✅
create_error_handler()factory for Litestar
7. Printing & PDF Generation > 7.1 Print Format DocType
Progress: 10/10 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/print_format.py - ✅ Define
PrintFormatDocType: - ✅
name: str- Display name - ✅
doctype: str- Target DocType - ✅
template: str- Jinja2 template path - ✅
is_default: bool - ✅
css: str | None- Custom CSS - ✅
header_html: str | None,footer_html: str | None - ✅
page_size: str(A4, Letter, etc.) - ✅
orientation: str(portrait, landscape)
7. Printing & PDF Generation > 7.2 Jinja Print Adapter
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/print/jinja_adapter.py - ✅ Implement
JinjaPrintAdapter: - ✅
async def render_html(doc, template) -> str - ✅ Load Jinja2 template
- ✅ Render with document context
- ✅ Return HTML string
- ✅
async def render_html_string(template_string, doc) -> str - ✅ Custom filters:
currency,date,datetime
7. Printing & PDF Generation > 7.3 Gotenberg PDF Adapter
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/print/gotenberg_adapter.py - ✅ Implement
GotenbergPrintAdapter: - ✅
async def html_to_pdf(html, page_size, orientation, ...) -> bytes - ✅ Send HTML to Gotenberg service
- ✅ Return PDF bytes
- ✅
async def is_available() -> bool- Health check - ✅
GotenbergConfigwith URL, timeout, page size, margins - ✅ Page sizes: A4, Letter, Legal, A3, A5
7. Printing & PDF Generation > 7.4 Print API
Progress: 9/9 (100%)
Completed:
- ✅ Create
GET /api/v1/print/{doctype}/{id}: - ✅ Query parameters:
- ✅
format- pdf/html (default: pdf) - ✅
print_format- Custom format name - ✅ Load document (TODO: integrate with repository - phase 10)
- ✅ Check read permission (TODO: integrate with permission - phase 10)
- ✅ Render using JinjaPrintAdapter → GotenbergPrintAdapter
- ✅ Return PDF or HTML with appropriate headers
- ✅ Fallback to HTML if Gotenberg unavailable
8. System Settings > 8.1 System Settings DocType
Progress: 11/11 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/system_settings.py - ✅ Define
SystemSettingsDocType (singleton): - ✅
name: str- Always "System Settings" (frozen) - ✅
app_name: str- Application display name - ✅
timezone: str- Default timezone - ✅
date_format: str- Date format string - ✅
time_format: str- Time format string - ✅
language: str- Default language code - ✅
enable_signup: bool- Allow registration - ✅
session_expiry: int- Session timeout in minutes - ✅
maintenance_mode: bool- Admin-only access
8. System Settings > 8.2 Settings API
Progress: 5/5 (100%)
Completed:
- ✅ Create
GET /api/v1/settings: - ✅ Return system settings via
SettingsResponse - ✅ Cache aggressively (5 min Cache-Control header)
- ✅
invalidate_settings_cache()helper - ✅
set_settings_cache()helper
9. Notification System > 9.1 Notification DocType
Progress: 13/13 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/notification.py - ✅ Define
NotificationDocType: - ✅
user_id: str- Recipient - ✅
subject: str - ✅
message: str - ✅
notification_type: str(info, success, warning, error, etc.) - ✅
read: bool - ✅
doctype: str | None- Related DocType - ✅
document_id: str | None - ✅
timestamp: datetime - ✅
from_user: str | None - ✅
metadata: dict | None - ✅ RLS on user_id field
9. Notification System > 9.2 Notification API
Progress: 9/9 (100%)
Completed:
- ✅ Create
GET /api/v1/notifications: - ✅ List user's notifications
- ✅ Filter by read/unread
- ✅ Create
PATCH /api/v1/notifications/{id}/read- Mark as read - ✅ Create
DELETE /api/v1/notifications/{id}- Delete notification - ✅ Create WebSocket endpoint for real-time notifications:
- ✅
WS /api/v1/notifications/stream- Real-time notification stream - ✅
push_notification(user_id, notification)- Push to connected clients - ✅
create_notification_websocket_router()factory
10. Email Integration > 10.1 Email Queue DocType
Progress: 20/20 (100%)
Completed:
- ✅ Create
src/framework_m/core/doctypes/email_queue.py - ✅ Define
EmailQueueDocType: - ✅
to: list[str]- Recipients - ✅
cc/bcc: list[str] | None - ✅
subject: str - ✅
body: str- HTML body - ✅
text_body: str | None- Plain text alt - ✅
status: str- Queued/Sending/Sent/Failed/Cancelled - ✅
priority: str- low/normal/high - ✅
error: str | None - ✅
retry_count/max_retries: int - ✅
queued_at/sent_at: datetime - ✅
reference_doctype/reference_id- for tracking - ✅ Port-Adapter Pattern:
- ✅
EmailQueueProtocol(interface/port) - ✅
DatabaseEmailQueueAdapter(default - uses EmailQueue DocType) - ✅
InMemoryEmailQueueAdapter(testing) - ✅
queue_email()helper function - ✅
configure_email_queue()for swapping adapters - ✅ Ready for
NotificationServiceAdapterintegration
10. Email Integration > 10.2 Email Sender
Progress: 13/13 (100%)
Completed:
- ✅ Create email sender protocol and adapters:
- ✅
EmailSenderProtocol(interface/port) - ✅
SMTPEmailSender- SMTP delivery adapter - ✅
LogEmailSender- Console logging (development) - ✅
SMTPConfig- Configuration dataclass - ✅ Create background job
EmailProcessor: - ✅
process_queue()- Process pending emails - ✅
process_single(queue_id)- Process single email - ✅ Update EmailQueue status
- ✅ Retry logic (placeholder)
- ✅ Add helper function:
- ✅
queue_email()- Queue for sending - ✅
send_queued_email()- Process single email
11. Testing > 11.1 Unit Tests
Progress: 5/5 (100%)
Completed:
- ✅ Test User DocType validation (
core/doctypes/test_user.py,core/services/test_user_manager.py) - ✅ Test Role assignment (
adapters/auth/test_rbac_permission.py) - ✅ Test Permission checking (8 permission test files)
- ✅ Test File upload/download (
core/test_file.py,adapters/web/test_file_routes.py) - ✅ Test Print rendering (
core/test_print_format.py,adapters/print/test_*.py)
11. Testing > 11.2 Integration Tests
Progress: 5/5 (100%)
Completed:
- ✅ Test user creation and login (
integration/test_api_endpoints.py) - ✅ Test permission enforcement (
core/test_object_level_permissions.py) - ✅ Test file storage (local and S3) (
adapters/storage/test_local.py,adapters/storage/test_s3.py) - ✅ Test PDF generation with Gotenberg (
adapters/print/test_gotenberg_adapter.py) - ✅ Test email sending (
adapters/email/test_sender_processor.py)
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ User and Role management works
- ✅ Permissions are enforced correctly
- ✅ Files can be uploaded and downloaded
- ✅ Audit logs are created
- ✅ PDFs can be generated
- ✅ Emails can be sent
Phase 07: Studio (Code Generation UI)
Phase: 07
Objective: Build a visual DocType builder (framework-m-studio) that generates Python code, running as a Litestar app.
Status: 93% Complete
1. Packaging Strategy (Runtime vs DevTools) > 1.1 framework-m (Runtime)
Progress: 4/4 (100%)
Completed:
- ✅ Goal: Production-grade kernel.
- ✅ Content: API Server, ORM, DocType Engine, Basic CLI (
start,migrate,worker). - ✅ Dependencies:
litestar,sqlalchemy,pydantic,cyclopts. - ✅ Excluded: Code generators, Studio UI, Heavy formatting/linting libs.
1. Packaging Strategy (Runtime vs DevTools) > 1.2 framework-m-studio (DevTools)
Progress: 4/4 (100%)
Completed:
- ✅ Goal: Developer Productivity & SaaS Component.
- ✅ Content: Studio UI, Code Generators, Visual Editors.
- ✅ Dependencies:
framework-m,libcst,jinja2. - ✅ Integration: Plugs into
mCLI via entry points (m codegen).
2. Studio Backend (Litestar App) > 1. Project Structure (Monorepo)
Progress: 6/6 (100%)
Completed:
- ✅ Create
apps/studio/in the workspace - ✅ Initialize
apps/studio/pyproject.toml: - ✅ Add dependency:
framework-m = { workspace = true } - ✅ Add dependency:
libcst(for code modification) - ✅ Add dependency:
jinja2(for code generation) - ✅ Add code generation endpoints
2. Studio Backend (Litestar App) > 1.2 File System API
Progress: 14/14 (100%)
Completed:
- ✅ Create
GET /studio/api/doctypes: - ✅ Scan project for
*.pyfiles containing DocType classes - ✅ Return list of DocTypes with metadata
- ✅ Create
GET /studio/api/doctype/{name}: - ✅ Read DocType file
- ✅ Parse with LibCST
- ✅ Return structured JSON
- ✅ Create
POST /studio/api/doctype/{name}: - ✅ Accept DocType schema JSON
- ✅ Generate Python code
- ✅ Write to file system
- ✅ Create
DELETE /studio/api/doctype/{name}: - ✅ Delete DocType file
- ✅ Delete Controller file (if exists)
2. LibCST Code Transformer > 2.1 Parser
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m_studio/codegen/parser.py - ✅ Implement
parse_doctype(file_path: str) -> dict: - ✅ Use LibCST to parse Python file
- ✅ Extract class definition
- ✅ Extract fields with types and defaults
- ✅ Extract Config metadata
- ✅ Return structured dict
2. LibCST Code Transformer > 2.2 Generators (The Strategy)
Progress: 8/8 (100%)
Completed:
- ✅ Creation (Scaffolding):
- ✅ Use
jinja2templates (shared with CLIm new:doctype). - ✅ Goal: Generate clean, standard Python code from scratch.
- ✅ Implement
generate_doctype_source(schema: dict) -> str. - ✅ Mutation (Transformer):
- ✅ Use
LibCSTto parse and modify existing files. - ✅ Goal: Add/Edit fields while preserving comments and custom methods.
- ✅ Implement
update_doctype_source(source: str, schema: dict) -> str.
2. LibCST Code Transformer > 2.3 Test Generator
Progress: 6/6 (100%)
Completed:
- ✅ Create
src/framework_m_studio/codegen/test_generator.py - ✅ Implement
generate_test(schema: dict) -> str: - ✅ Generate
test_{doctype}.py - ✅ Import
pytestand DocType - ✅ Generate basic CRUD test (Create, Read, Update, Delete)
- ✅ Generate validation failure test (if required fields exist)
2. LibCST Code Transformer > 2.4 Transformer
Progress: 12/12 (100%)
Completed:
- ✅ Create
src/framework_m_studio/codegen/transformer.py - ✅ Implement
update_doctype(file_path: str, schema: dict): - ✅ Parse existing file with LibCST
- ✅ Locate DocType class
- ✅ Update/add/remove fields
- ✅ Preserve comments and custom methods
- ✅ Write back to file
- ✅ Handle edge cases:
- ✅ Field renamed (detect and update)
- ✅ Field type changed
- ✅ Field deleted (remove from class)
- ✅ Custom methods preserved
3. Studio Frontend > 3.1 React App Setup (Refine Stack)
Progress: 8/8 (100%)
Completed:
- ✅ Create
apps/studio/studio_ui/directory - ✅ Initialize Refine app:
- ✅ Install dependencies per ADR-0005:
- ✅ Create Framework M Data Provider (
src/providers/dataProvider.ts): - ✅ Configure API base URLs (per ADR-0005):
- ✅ Read from
window.__FRAMEWORK_CONFIG__or env vars - ✅ Support same-origin, subdomain, and CDN scenarios
- ✅ Default to
/studio/apifor Studio endpoints
3. Studio Frontend > 3.2 DocType List View (Refine Resource)
Progress: 5/5 (100%)
Completed:
- ✅ Create
pages/doctypes/list.tsx: - ✅ Use
useListhook from@refinedev/coreto fetch DocTypes - ✅ Display with
@tanstack/react-table+ Tailwind styling - ✅ Add search/filter with
useTableglobalFilter - ✅ Add "New DocType" button → navigates to
/doctypes/create
3. Studio Frontend > 3.3 DocType Editor (Refine Form)
Progress: 5/5 (100%)
Completed:
- ✅ Create
pages/doctypes/edit.tsx: - ✅ Use
useOne/useUpdate/useCreatehooks for data - ✅ Left panel: Field list with
@dnd-kit/sortable - ✅ Right panel: Field properties form (name, type, required, default, description)
- ✅ Top bar: DocType name input + Save button
3. Studio Frontend > 3.4 Field Editor (RJSF Schema-Driven)
Progress: 5/5 (100%)
Completed:
- ✅ Create
components/FieldEditor.tsx: - ✅ Render with RJSF using JSON Schema for field properties
- ✅ Custom Tailwind widgets:
TextWidget,SelectWidget,CheckboxWidget,TextareaWidget - ✅ Dynamic "Validators" collapsible for min/max length, pattern, etc.
- ✅ Live preview of generated Python type annotation
3. Studio Frontend > 3.5 Drag & Drop
Progress: 4/4 (100%)
Completed:
- ✅ Implement field reordering:
- ✅ Use
@dnd-kit/core+@dnd-kit/sortable - ✅ Allow dragging fields to reorder
- ✅ Update schema on drop (via
arrayMove)
3. Studio Frontend > 3.6 Code Preview (Monaco Editor)
Progress: 6/6 (100%)
Completed:
- ✅ Create
components/CodePreview.tsx: - ✅ Use
@monaco-editor/reactwithlanguage="python" - ✅ Read-only mode (
readOnly: true) - ✅ Theme:
vs-dark - ✅ Auto-update on schema change (memoized generation)
- ✅ Copy button for generated code
3. Studio Frontend > 3.7 Save Flow
Progress: 5/5 (100%)
Completed:
- ✅ Implement save functionality:
- ✅ Validate schema (name required)
- ✅ Call backend API via
useCreate/useUpdate - ✅ Navigate back to list on success
- ✅ Loading state on save button
3. Studio Frontend > 3.8 Visual Data Modeling (Mind Map)
Progress: 5/5 (100%)
Completed:
- ✅ Implement ERD/Mind Map View:
- ✅ Central Node: Current DocType (highlighted)
- ✅ Connected Nodes: Related DocTypes via Link fields
- ✅ Visual Action: Drag to connect nodes → Creates Link Field
- ✅ Using
@xyflow/react(React Flow v12)
3. Studio Frontend > 3.9 Layout Designer (Grid System)
Progress: 5/5 (100%)
Completed:
- ✅ Implement Visual Layout Drag & Drop:
- ✅ Define Sections with title and Columns (1/2/3 cols selector)
- ✅ Drag fields from palette into grid cells
- ✅ Real-time form preview toggle
- ✅ Add/delete sections
3. Studio Frontend > 3.10 Module Explorer
Progress: 5/5 (100%)
Completed:
- ✅ Implement Module Scanner:
- ✅ Group DocTypes by directory/app module (tree structure)
- ✅ Tree view navigation in Sidebar
- ✅ Expand/collapse all, search filter
- ✅ Click to navigate to DocType editor
4. Studio Cloud Mode (Ephemeral & Git-Backed) > 4.3 Git Adapter (Data Agnostic)
Progress: 11/11 (100%)
Completed:
- ✅ Create
src/framework_m_studio/git/protocol.py- GitAdapterProtocol (Port) - ✅ Create
src/framework_m_studio/git/adapter.py- GitAdapter (Adapter) - ✅ Implement
GitAdapter: - ✅ Wraps standard
gitbinary via asyncio subprocess. - ✅
clone(repo_url, auth): Clone to temp dir. - ✅
commit(message): Stage and commit changes. - ✅
push(branch): Push to remote. - ✅
pull(): Pull latest changes. - ✅
create_branch(name): Create new branch. - ✅
get_status(): Get workspace status. - ✅ Unit tests in
tests/test_git_adapter.py(12 tests)
4. Studio Cloud Mode (Ephemeral & Git-Backed) > 4.4 GitHub Provider
Progress: 9/9 (100%)
Completed:
- ✅ Create
src/framework_m_studio/git/github_provider.py - ✅ Implement
GitHubProvider: - ✅ Use GitHub API for operations (REST API with urllib)
- ✅ Support personal access tokens (Bearer auth)
- ✅ Handle authentication (GitHubAuthError)
- ✅ Create pull requests
- ✅ List pull requests
- ✅ Validate tokens
- ✅ Unit tests in
tests/test_github_provider.py(9 tests)
4. Studio Cloud Mode (Ephemeral & Git-Backed) > 4.5 Generic Git Provider
Progress: 2/2 (100%)
Completed:
- ✅ Support HTTPS and SSH (via git CLI)
- ✅ Work with any Git server (generic implementation)
4. Studio Cloud Mode (Ephemeral & Git-Backed) > 4.6 Workspace Management
Progress: 7/7 (100%)
Completed:
- ✅ Create
src/framework_m_studio/workspace.py - ✅ Implement workspace lifecycle:
- ✅ Clone repo to temp directory
- ✅ Track workspace sessions
- ✅ Clean up old workspaces (TTL-based)
- ✅ Handle concurrent edits (asyncio lock)
- ✅ Unit tests in
tests/test_workspace.py(12 tests)
4. Studio Cloud Mode (Ephemeral & Git-Backed) > 4.7 Cloud Studio API
Progress: 12/12 (100%)
Completed:
- ✅ Create
POST /studio/api/workspace/connect: - ✅ Accept repo URL and token
- ✅ Clone repository
- ✅ Return workspace ID
- ✅ Create
POST /studio/api/workspace/{id}/commit: - ✅ Commit changes
- ✅ Push to branch
- ✅ Return commit SHA
- ✅ Create
GET /studio/api/workspace/{id}/status: Git status - ✅ Create
POST /studio/api/workspace/{id}/pull: Pull latest - ✅ Create
DELETE /studio/api/workspace/{id}: Cleanup workspace - ✅ Create
GET /studio/api/workspace/sessions: List all sessions
5. Studio CLI Command > 5.1 SPA Packaging & Serving (Path Prefix Architecture)
Progress: 20/21 (95%)
Completed:
- ✅ Build Process:
- ✅
pnpm run buildinstudio_uioutputs tosrc/framework_m_studio/static/(vite.config.ts). - ✅
pyproject.tomlincludesframework_m_studio/static/**/*. - ✅ Serving Strategy (Litestar) (in
app.py): - ✅ UI Routes: Serve
/studio/ui/*→ React SPA (HTML pages) - ✅ API Routes: Serve
/studio/api/*→ JSON endpoints - ✅ Assets: Serve
/studio/ui/assets/*as static files (Cached) - ✅ SPA Catch-all:
/studio/ui/{path:path}→ returnsindex.htmlfor client-side routing - ✅ Redirect:
/studio→/studio/ui/for convenience - ✅ Content-Type Fix: All responses use explicit
media_typeto prevent download issues - ✅ Implementation:
serve_spa()and_get_spa_response()functions inapp.py - ✅ Implement
m studio(inframework-m-studiopackage): - ✅ Register CLI command via entry point:
- ✅ Start uvicorn server on port 9000 (default)
- ✅ Serve Studio UI
- ✅ Options:
- ✅
--port- Custom port - ✅
--host- Custom host - ✅
--reload- Development mode - ✅
--cloud- Enable cloud mode
Pending:
- ⏳ Open browser automatically (TODO)
6. DevTools CLI (Extensions) > 6.1 Documentation Generator (m docs:generate)
Progress: 6/6 (100%)
Completed:
- ✅ Dependencies: Uses stdlib
urllib,json,subprocess(no external deps required). - ✅ Command:
m docs:generate: - ✅ API Reference: Generates markdown from DocTypes in
docs_generator.py. - ✅ OpenAPI Export: Exports
openapi.jsonfrom URL (--openapi-url). - ✅ Site Build: Runs
mkdocs buildif available (--build-site). - ✅ Unit tests in
tests/test_docs_generator.py(10 tests)
6. DevTools CLI (Extensions) > 6.2 Client SDK Generator (m codegen client)
Progress: 8/8 (100%)
Completed:
- ✅ Dependencies: Uses stdlib only (no external deps required).
- ✅ Command:
m codegen client: - ✅ Flow:
- ✅ Arguments:
- ✅ TypeScript: Generates interfaces + fetch client in
sdk_generator.py. - ✅ Python: Generates Pydantic models in
sdk_generator.py. - ✅ Unit tests in
tests/test_codegen.py(6 tests) - ✅ CLI tests updated in
tests/test_cli.py
7. Field Type Library > 7.1 Supported Field Types
Progress: 13/13 (100%)
Completed:
- ✅ Implement field type definitions:
- ✅ Text (str)
- ✅ Number (int, float)
- ✅ Checkbox (bool)
- ✅ Date (date)
- ✅ DateTime (datetime)
- ✅ Select (enum)
- ✅ Link (foreign key)
- ✅ Table (child table)
- ✅ Level 1: Grid/Table view
- ✅ Level 2+: Drill-down pattern (Button -> Drawer/Dialog) for infinite nesting
- ✅ JSON (dict)
- ✅ File (file upload)
7. Field Type Library > 7.2 Custom Field Type Discovery
Progress: 5/5 (100%)
Completed:
- ✅ Dynamic Loading: Studio reads available types from
FieldRegistryat runtime. - ✅ API Endpoint:
GET /studio/api/field-types - ✅ Returns: Built-in types + Types registered by installed apps.
- ✅ Each type includes:
name,pydantic_type,sqlalchemy_type,ui_component(optional). - ✅ UI Integration: Field Type Selector in DocType Editor dynamically populates from this API.
7. Field Type Library > 7.3 Custom UI Components (Client-Side)
Progress: 6/6 (100%)
Completed:
- ✅ Goal: Allow apps to register custom React components for their field types.
- ✅ Registration (App-Side):
- ✅ Discovery (Studio-Side):
- ✅ Shadow Build (Phase 09) loads all app
frontend/plugins. - ✅ Studio UI checks
window.__STUDIO_FIELD_COMPONENTS__map. - ✅ Falls back to default
<input>if no custom component.
7. Field Type Library > 7.5 Live Preview & Sandbox Mode
Progress: 0/11 (0%)
Pending:
- ⏳ Recommendation: Default to feature branches for teams. Add branch selector to Studio UI.
- ⏳ Goal: Preview the DocType being edited with mock data AND simulate CRUD.
- ⏳ Implementation:
- ⏳ Preview Tab: Toggle between "Schema Editor" and "Sandbox".
- ⏳ Mock Data Generation:
- ⏳ Use
@faker-js/fakeror simple generators. - ⏳ Generate sample rows based on field types.
- ⏳ Form Preview: Render
AutoFormwith generated mock doc. - ⏳ List Preview: Render
AutoTablewith 5-10 mock rows. - ⏳ Schema Source: Uses the in-memory schema being edited, NOT the saved file.
- ⏳ Allows instant feedback without saving.
7. Field Type Library > 7.6 Sandbox: Interactive CRUD Simulation
Progress: 11/11 (100%)
Completed:
- ✅ Goal: Let users test the full UX before committing the DocType.
- ✅ Features:
- ✅ New: Create a new mock document. Test mandatory field validation.
- ✅ Update: Edit an existing mock document. See form behavior.
- ✅ Delete: Delete mock document. See confirmation dialogs.
- ✅ List (Few): Show 5 rows. Test basic list rendering.
- ✅ List (Many): Paginate 100+ mock rows. Test performance.
- ✅ Filter: Apply filters and see results change.
- ✅ Validation: Submit form with missing required fields. See error messages.
- ✅ Data Store: In-memory array (resets on page reload).
- ✅ Benefit: No database required. Test UX before writing to disk.
7. Field Type Library > 7.7 Local Hot Reload (Optional Enhancement)
Progress: 0/8 (0%)
Pending:
- ⏳ Goal: For users who want to test with a real local database instead of mock data.
- ⏳ Prerequisites: Local Postgres/SQLite +
m startrunning. - ⏳ Flow:
- ⏳ Studio saves DocType to file.
- ⏳ File watcher detects change → triggers schema sync.
- ⏳ Table created/updated in local DB.
- ⏳ User can now test with real CRUD operations.
- ⏳ Benefit: Bridge between mock sandbox and production—test with actual data locally.
7. Field Type Library > 7.2 Field Metadata
Progress: 7/7 (100%)
Completed:
- ✅ Define field options:
- ✅ Label
- ✅ Description
- ✅ Required
- ✅ Default value
- ✅ Validation rules
- ✅ Display options (hidden, read-only)
8. Controller Scaffolding
Progress: 8/8 (100%)
Completed:
- ✅ Add controller generation:
- ✅ Generate controller file template
- ✅ Add common hook methods
- ✅ Add validation examples
- ✅ Controller editor in UI:
- ✅ List hook methods
- ✅ Add custom methods
- ✅ Code editor for method bodies
9. Testing > 9.1 Unit Tests
Progress: 8/8 (100%)
Completed:
- ✅ Test LibCST parser:
- ✅ Parse valid DocType
- ✅ Extract fields correctly
- ✅ Handle edge cases
- ✅ Test code generator:
- ✅ Generate valid Python code
- ✅ Format correctly
- ✅ Handle all field types
9. Testing > 9.2 Integration Tests
Progress: 11/11 (100%)
Completed:
- ✅ Test full flow:
- ✅ Create DocType via UI
- ✅ Save to file system
- ✅ Reload and verify
- ✅ Update DocType
- ✅ Verify changes preserved
- ✅ Test Git integration:
- ✅ Clone repository
- ✅ Make changes
- ✅ Commit and push
- ✅ Verify on GitHub
10. Documentation
Progress: 6/6 (100%)
Completed:
- ✅ Create Studio user guide:
- ✅ How to start Studio
- ✅ How to create DocType
- ✅ How to add fields
- ✅ How to configure permissions
- ✅ How to use Git mode
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ Studio UI can create and edit DocTypes
- ✅ Generated code is valid Python
- ✅ Changes are saved to file system
- ✅ LibCST preserves custom code
- ✅ Git mode can commit and push
- ✅ Studio works in both local and cloud modes
Phase 08: Workflows & Advanced Features
Phase: 08 Objective: Implement pluggable workflow engine, DocType overrides, app-defined ports, and advanced extensibility features. Status: 100% Complete
1. Workflow System > 1.1 Workflow Protocol
Progress: 6/6 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/workflow.py - ✅ Define
WorkflowProtocol: - ✅
async def start_workflow(doctype: str, doc_id: str, workflow_name: str) - ✅
async def get_workflow_state(doc_id: str) -> str - ✅
async def transition(doc_id: str, action: str, user: UserContext) - ✅
async def get_available_actions(doc_id: str, user: UserContext) -> list[str]
1. Workflow System > 1.2 Internal Workflow Adapter
Progress: 28/28 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/workflow/internal_workflow.py - ✅ Create
WorkflowStateDocType: - ✅
name: str - ✅
workflow: str- Workflow name - ✅
doctype: str - ✅
document_name: str - ✅
current_state: str - ✅
updated_at: datetime - ✅ Create
WorkflowTransitionDocType: - ✅
name: str - ✅
workflow: str - ✅
from_state: str - ✅
to_state: str - ✅
action: str- Action name - ✅
allowed_roles: list[str] - ✅
condition: str | None- Python expression - ✅ Create
WorkflowDocType: - ✅
name: str- Workflow name - ✅
doctype: str- Target DocType - ✅
initial_state: str - ✅
states: list[dict]- State definitions - ✅
transitions: list[WorkflowTransition] - ✅ Implement
InternalWorkflowAdapter: - ✅ Load workflow definition
- ✅ Validate transitions
- ✅ Check permissions
- ✅ Update state
- ✅ Trigger hooks / Emit Event (Side effects via Event Bus only)
1. Workflow System > 1.3 Temporal Workflow Adapter (Optional)
Progress: 6/6 (100%)
Completed:
- ✅ Create
src/framework_m/adapters/workflow/temporal_adapter.py - ✅ Implement
TemporalWorkflowAdapter: - ✅ Connect to Temporal server
- ✅ Start workflows
- ✅ Query workflow state
- ✅ Signal workflows for transitions
2. DocType Overrides > 2.1 Override Registry
Progress: 4/4 (100%)
Completed:
- ✅ Update
MetaRegistry: - ✅ Add
register_override(base_doctype: str, override_class: Type[BaseDocType]) - ✅ When loading DocType, check for overrides
- ✅ Use override class if registered
2. DocType Overrides > 2.2 Schema Extension
Progress: 5/5 (100%)
Completed:
- ✅ Implement schema merging:
- ✅ Combine fields from base and override
- ✅ Override can add new fields
- ✅ Override can modify field properties
- ✅ Base fields cannot be removed
2. DocType Overrides > 2.3 Table Alteration
Progress: 5/5 (100%)
Completed:
- ✅ Update
SchemaMapper: - ✅ Detect schema changes from overrides
- ✅ Generate ALTER TABLE migrations
- ✅ Add new columns
- ✅ Modify column types (with caution)
3. App-Defined Ports > 3.1 Custom Protocol Registration
Progress: 4/4 (100%)
Completed:
- ✅ Update Container to support app-defined protocols:
- ✅ Allow apps to define custom protocols
- ✅ Register via entrypoints
- ✅ Other apps can override using
container.override()
4. Child Tables (Nested DocTypes) > 4.1 Child Table Support
Progress: 3/3 (100%)
Completed:
- ✅ Add
is_childflag to DocType Config - ✅ Child tables don't have independent routes
- ✅ Stored as JSON or separate table with parent reference
4. Child Tables (Nested DocTypes) > 4.2 Implementation
Progress: 8/8 (100%)
Completed:
- ✅ Update
SchemaMapper: - ✅ Create separate table for child
- ✅ Add
parentandparenttypecolumns - ✅ Add
idxfor ordering - ✅ Update
GenericRepository: - ✅ Save child records when saving parent
- ✅ Delete old children and insert new ones
- ✅ Load children when loading parent
5. Virtual Fields > 5.1 Computed Fields
Progress: 4/4 (100%)
Completed:
- ✅ Add
@computed_fielddecorator: - ✅ Virtual fields not stored in database
- ✅ Computed on load
- ✅ Included in API responses
6. Link Fields (Foreign Keys) > 6.1 Link Field Type
Progress: 1/1 (100%)
Completed:
- ✅ Add Link field type using json_schema_extra:
6. Link Fields (Foreign Keys) > 6.2 Implementation
Progress: 8/8 (100%)
Completed:
- ✅ Update
SchemaMapper: - ✅ Detect link fields via json_schema_extra
- ✅ Create foreign key constraint to target table
- ✅ Reference target table's id column
- ✅ Add database enforcement:
- ✅ Foreign key constraints enforce referential integrity
- ✅ Works with SQLite and PostgreSQL (database-agnostic)
- ✅ SQLite foreign keys enabled via PRAGMA
6. Link Fields (Foreign Keys) > 6.3 Link Fetching
Progress: 6/6 (100%)
Completed:
- ✅ Add
fetch_fromoption: - ✅ Auto-populate field from linked document
- ✅ Update GenericRepository to fetch values before save
- ✅ Fetch values automatically on insert and update
- ✅ Handle null links gracefully
- ✅ Support multiple fetch_from fields
7. Naming Series (Human-Readable Names) > 7.1 Auto-Naming Configuration
Progress: 7/7 (100%)
Completed:
- ✅ Add naming configuration to DocType:
- ✅ Implement naming patterns:
- ✅
.YYYY.- Year (2026) - ✅
.MM.- Month (01-12) - ✅
.DD.- Day (01-31) - ✅
.####- Sequential number with padding (0001, 0002...) - ✅
{field}- Field value from entity
7. Naming Series (Human-Readable Names) > 7.2 Implementation (Optimistic Approach)
Progress: 2/2 (100%)
Completed:
- ✅ Name generation happens AFTER insert (id already assigned):
- ✅ For high-volume DocTypes, use PostgreSQL sequences:
7. Naming Series (Human-Readable Names) > 7.3 Counter Storage
Progress: 4/4 (100%)
Completed:
- ✅ Create
NamingCounterDocType: - ✅
prefix: str- e.g., "INV-2024-" - ✅
current: int- Current counter value - ✅ Note: No row-level locking needed. Use optimistic update with retry.
8. Validation Rules > 8.1 Field Validators
Progress: 1/1 (100%)
Completed:
- ✅ Add Pydantic validators:
8. Validation Rules > 8.2 Document Validators
Progress: 1/1 (100%)
Completed:
- ✅ Use controller
validate()hook:
9. Testing > 9.1 Unit Tests
Progress: 5/5 (100%)
Completed:
- ✅ Test workflow transitions (15 tests in
test_workflow.py) - ✅ Test DocType overrides (16 tests in
test_meta_registry_overrides.py) - ✅ Test child table operations (38 tests in
test_child_tables.py) - ✅ Test link field validation (16 tests in
test_link_fields.py) - ✅ Test naming series (29 tests in
test_naming_series.py+ validation tests)
9. Testing > 9.2 Integration Tests
Progress: 4/4 (100%)
Completed:
- ✅ Test full workflow lifecycle (6 tests in
test_workflow_lifecycle.py) - ✅ Test override schema migration (10 tests in
test_override_migration.py) - ✅ Test child table CRUD (12 tests in
test_child_table_integration.py) - ✅ Test app-defined ports (9 tests in
test_app_ports.py)
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ Workflows can be defined and executed (15 unit + 6 integration tests)
- ✅ DocTypes can be extended via overrides (16 unit + 10 integration tests)
- ✅ Child tables work correctly (38 unit + 12 integration tests)
- ✅ Link fields create proper foreign keys (16 tests in
test_link_fields.py) - ✅ Naming series generates unique names (29 tests in
test_naming_series.py) - ✅ App-defined ports can be registered (9 tests in
test_app_ports.py)
Phase 09A: Frontend
Phase: 09a Objective: Build a generic admin UI (the "Desk") that renders forms and lists from metadata. Status: 97% Complete
1. Frontend Architecture > 1.2 Project Setup
Progress: 1/6 (17%)
Completed:
- ✅ Option A: Use Refine CLI (Recommended)
Pending:
- ⏳ Option B: Manual Setup (Full Control)
- ⏳ Install form libraries (RJSF):
- ⏳ Install UI layer (shadcn/ui):
- ⏳ Install dashboard/charts (Tremor):
- ⏳ Install Studio-specific tools:
1. Frontend Architecture > 1.3 Refine Data Provider
Progress: 4/4 (100%)
Completed:
- ✅ Create
frameworkMDataProvider.ts: - ✅ Implements Refine's
DataProviderinterface - ✅ Maps to Framework M REST API (
/api/v1/{resource}) - ✅ Handles pagination, sorting, filtering
1. Frontend Architecture > 1.4 Base URL Configuration
Progress: 2/2 (100%)
Completed:
- ✅ Support configurable base URLs for different deployment scenarios:
- ✅ Inject configuration via
window.__FRAMEWORK_CONFIG__:
1. Frontend Architecture > 1.5 App Entry Point
Progress: 1/1 (100%)
Completed:
- ✅ Create Refine app entry (
src/App.tsx):
2. Metadata-Driven UI > 2.1 Metadata Fetcher
Progress: 3/3 (100%)
Completed:
- ✅ Create
useDocTypeMetahook: - ✅ Fetch from
GET /api/meta/{doctype} - ✅ Cache metadata aggressively using React Query
2. Metadata-Driven UI > 2.2 Auto Form Generator (RJSF Integration)
Progress: 14/14 (100%)
Completed:
- ✅ Create
AutoFormcomponent using RJSF: - ✅ Accept JSON Schema from
GET /api/meta/{doctype} - ✅ Generate form fields dynamically
- ✅ Map schema types to shadcn/ui components:
- ✅
string→<Input /> - ✅
number→<Input type="number" /> - ✅
boolean→<Checkbox /> - ✅
enum→<Select /> - ✅
date→<DatePicker /> - ✅ Link →
<Combobox />with async search (LinkWidget) - ✅ Use RJSF with custom widget registry for shadcn/ui
- ✅ Architecture: Export
AutoFormas standalone component - ✅ Allow developers to use it inside custom pages ("Ejection Strategy")
- ✅ Do not couple strictly to a "Meta-Driven Page" route
2. Metadata-Driven UI > 2.3 Auto Table Generator (TanStack Table)
Progress: 4/4 (100%)
Completed:
- ✅ Create
AutoTablecomponent using@refinedev/react-table: - ✅ Columns generated from metadata
- ✅ Sorting, filtering, pagination built-in
- ✅ Row selection for bulk actions
2. Metadata-Driven UI > 2.4 Workflow UI (State Buttons)
Progress: 6/6 (100%)
Completed:
- ✅ State Indicator:
- ✅ Show current state badge (e.g., "Draft", "Approved") in Form Header
- ✅ Action Buttons:
- ✅ Fetch available transitions:
GET /api/workflow/{doctype}/{id}/actions - ✅ Render buttons: "Submit", "Approve", "Reject"
- ✅ Handle transition API call on click
2. Metadata-Driven UI > 2.5 Plugin System (The "Shadow Build")
Progress: 7/7 (100%)
Completed:
- ✅ Goal: "Easy as Frappe" but with Vite/React tooling
- ✅ Strategy:
- ✅
m startdetectsfrontend/index.tsin all installed apps - ✅ Generates a temporary
entry.tsxthat imports all app plugins - ✅ Runs Vite Dev Server on this generated entry
- ✅ Result: Hot Module Replacement (HMR) for custom apps inside the main Desk
- ✅ No Monkey Patching: Plugins register via
app.registerPlugin()
2. Metadata-Driven UI > 2.6 Progressive Customization (The "Zero Cliff")
Progress: 11/11 (100%)
Completed:
- ✅ Level 1: Configuration (Low Code)
- ✅ Edit Labels/Visibility via
Client Scriptor JSON overrides - ✅ No build step required
- ✅ Level 2: Injection (Mid Code)
- ✅ Custom Fields:
app.registerField('rating', StarRating) - ✅ Slot Injection:
app.registerSlot('form-header', PaymentButton) - ✅ Uses Shadow Build (HMR)
- ✅ Level 3: Ejection (Pro Code)
- ✅ Page Override: Replace
FormViewentirely with custom React component - ✅ Whitelabel: Replace
Layout/Themevia Plugin - ✅ Uses Shadow Build (HMR)
3. Core UI Pages > 3.1 List View
Progress: 7/7 (100%)
Completed:
- ✅ Create
ListViewcomponent: - ✅ Route:
/app/{doctype}/list - ✅ Fetch metadata
- ✅ Render
AutoTable - ✅ Add "New" button
- ✅ Add search and filters
- ✅ Add bulk actions
3. Core UI Pages > 3.2 Form View
Progress: 10/10 (100%)
Completed:
- ✅ Create
FormViewcomponent: - ✅ Route - Create:
/app/{doctype}/new - ✅ Route - Edit:
/app/{doctype}/detail/{id} - ✅ Benefit: No reserved keywords for IDs. An ID can be "new", "create", or "dashboard" without collision.
- ✅ Fetch metadata
- ✅ Fetch document (if editing)
- ✅ Render
AutoForm - ✅ Render Workflow Actions (if applicable)
- ✅ Save/Submit/Cancel buttons
- ✅ Show validation errors
3. Core UI Pages > 3.3 Dashboard
Progress: 5/5 (100%)
Completed:
- ✅ Create
Dashboardcomponent: - ✅ Route:
/app/dashboard - ✅ Show recent documents
- ✅ Show notifications
- ✅ Show quick links
4. Navigation & Auth > 4.1 Auth Configuration
Progress: 4/4 (100%)
Completed:
- ✅ Inject
window.__FRAMEWORK_CONFIG__(or fetch/api/v1/config): - ✅
authStrategy:"cookie"(Indie/BFF) or"oidc"(Client-Side) - ✅
loginUrl: URL to redirect to if 401 (for Cookie mode) - ✅
oidcConfig:{ authority, clientId, redirectUri }(for OIDC mode)
4. Navigation & Auth > 4.2 Refine Auth Provider Implementation
Progress: 1/1 (100%)
Completed:
- ✅ Create
authProvider.tsimplementing Refine'sAuthProviderinterface:
4. Navigation & Auth > 4.3 Auth Strategy Variants
Progress: 8/8 (100%)
Completed:
- ✅ Strategy A: Cookie (Indie / Gateway BFF):
- ✅ "It Just Works". Relies on browser's HttpOnly cookie
- ✅
credentials: "include"in all fetch calls - ✅ No token management in frontend
- ✅ Strategy B: OIDC (Client-Side PKCE):
- ✅ Uses
oidc-client-tslibrary - ✅ Store tokens in memory (not localStorage for security)
- ✅ Inject
Authorization: Bearer <token>header via custom fetch
4. Navigation & Auth > 4.4 Login Page (Indie Only)
Progress: 3/3 (100%)
Completed:
- ✅ Create
LoginPagecomponent: - ✅ Route:
/login - ✅ Use Refine's
useLoginhook:
4. Navigation & Auth > 4.5 Sidebar
Progress: 5/5 (100%)
Completed:
- ✅ Create
Sidebarcomponent: - ✅ List all DocTypes (grouped by module)
- ✅ Use Refine's
useMenu()hook for resource navigation - ✅ Collapsible sections
- ✅ Search DocTypes
4. Navigation & Auth > 4.6 Navbar
Progress: 6/6 (100%)
Completed:
- ✅ Create
Navbarcomponent: - ✅ App logo/name
- ✅ Global search
- ✅ Use Refine's
useGetIdentity()for user menu - ✅ Use Refine's
useLogout()for logout button - ✅ Notifications icon
5. Advanced UI Features > 5.1 Custom Views
Progress: 5/5 (100%)
Completed:
- ✅ Support custom view types:
- ✅ Kanban view (for status-based DocTypes)
- ✅ Calendar view (for date-based DocTypes)
- ✅ Gantt view (for project management)
- ✅ Register custom views in DocType Config:
5. Advanced UI Features > 5.2 Inline Editing
Progress: 4/4 (100%)
Completed:
- ✅ Add inline edit for list view:
- ✅ Click cell to edit
- ✅ Save on blur
- ✅ Show validation errors
5. Advanced UI Features > 5.3 Bulk Operations
Progress: 3/3 (100%)
Completed:
- ✅ Add checkbox column to table
- ✅ Select multiple rows
- ✅ Bulk actions: Delete, Export, Update field
6. Real-time Updates > 6.1 Refine Live Provider Implementation
Progress: 1/1 (100%)
Completed:
- ✅ Create
liveProvider.tsimplementing Refine'sLiveProviderinterface:
6. Real-time Updates > 6.2 Register Live Provider with Refine
Progress: 1/1 (100%)
Completed:
- ✅ Add
liveProviderto Refine app:
6. Real-time Updates > 6.3 Automatic UI Updates
Progress: 5/5 (100%)
Completed:
- ✅ With
liveMode: "auto", Refine automatically: - ✅ Refetches list data on
created,updated,deletedevents - ✅ Shows notification on document changes
- ✅ Invalidates React Query cache
- ✅ Manual control with
useLiveMode()hook:
6. Real-time Updates > 6.4 Desk Workspace Configuration (Code-First)
Progress: 11/11 (100%)
Completed:
- ✅ Define Workspace Schema (Pydantic):
- ✅
name: str— unique identifier - ✅
label: str— display name in sidebar - ✅
icon: str— sidebar icon - ✅
items: list[Shortcut | Link | Chart]— workspace contents - ✅
roles: list[str]— who can see this workspace - ✅ Implement
desktop.pyloader: - ✅ Scan apps for
desktop.py - ✅ Load workspace definitions
- ✅ Merge into unified Desk navigation
- ✅ Respect role-based visibility
6. Real-time Updates > 6.5 Global Command Palette
Progress: 4/4 (100%)
Completed:
- ✅ Implement
Ctrl+KGlobal Search: - ✅ Search DocTypes (Navigation)
- ✅ Search Documents (Title)
- ✅ Run Commands (e.g., "New User")
6. Real-time Updates > 6.6 Public API Specs
Progress: 3/3 (100%)
Completed:
- ✅ Ensure strict OpenAPI 3.1 generation:
- ✅
m docs:generate --json— Litestar provides/schema/openapi.json - ✅ Verify compatibility with low-code tools (Retool, Refine)
7. Frontend Build & Serving > 7.1 Build Command (m build)
Progress: 17/17 (100%)
Completed:
- ✅ Implement build logic:
- ✅ Detect Mode from
framework_config.toml: - ✅
frontend_mode = "indie"(default) - ✅
frontend_mode = "plugin"(Shadow Build) - ✅
frontend_mode = "eject"(skip, user handles build) - ✅ Indie Mode:
- ✅ No custom frontend code.
- ✅ Build default Desk:
cd framework_m/frontend && pnpm build - ✅ Output:
framework_m/static/dist/ - ✅ Plugin Mode (Shadow Build):
- ✅ Detect
frontend/index.tsin all installed apps. - ✅ Generate temp
entry.tsximporting all app plugins. - ✅ Run
vite buildon generated entry. - ✅ Output:
dist/(unified build with all app assets) - ✅ Eject Mode:
- ✅ Skip. User has their own frontend repo and build process.
- ✅ Framework M just serves API.
7. Frontend Build & Serving > 7.2 Static File Serving (Production)
Progress: 5/5 (100%)
Completed:
- ✅ Configure Litestar
StaticFilesConfig: - ✅ Serve from
dist/orstatic/dist/ - ✅ Route:
/static/*or/assets/* - ✅ Option: Configure CDN URL in
framework_config.toml: - ✅ If CDN configured, inject CDN prefix into HTML asset URLs.
Phase 09B: Documentation
Phase: 09b Objective: Create comprehensive documentation covering fundamentals, migration guides, i18n, multi-tenancy usage, and API references. Status: 100% Complete
1. Documentation (Basic Setup) > 1.1 Basic User Documentation ✅
Progress: 9/9 (100%)
Completed:
- ✅ Create
docs/user/directory - ✅ Write essential guides:
- ✅ Getting started (
docs/user/getting-started.md) - ✅ Creating DocTypes (
docs/user/creating-doctypes.md) - ✅ Using the Desk (
docs/user/using-the-desk.md) - ✅ Auto-generated docs (
scripts/generate_docs.py): - ✅
docs/user/_generated/field-types.md - ✅
docs/user/_generated/api-endpoints.md - ✅ Truthfulness tests (
tests/docs/test_user_docs.py- 17 tests passing)
1. Documentation (Basic Setup) > 1.2 Basic Developer Documentation ✅
Progress: 10/10 (100%)
Completed:
- ✅ Create
docs/developer/directory - ✅ Write essential guides:
- ✅ Architecture overview (
docs/developer/architecture.md) - ✅ Creating custom apps (
docs/developer/creating-apps.md) - ✅ Defining DocTypes (
docs/developer/defining-doctypes.md) - ✅ Auto-generated docs (
scripts/generate_docs.py): - ✅
docs/developer/_generated/protocols.md(20 protocols) - ✅
docs/developer/_generated/hooks.md(10 hooks) - ✅
docs/developer/_generated/cli-reference.md - ✅ Truthfulness tests (
tests/docs/test_developer_docs.py- 16 tests passing)
1. Documentation (Basic Setup) > 1.3 Framework Fundamentals ✅
Progress: 6/6 (100%)
Completed:
- ✅ Minimal core principle (irreplaceable: async Python, DI, protocols, entrypoints)
- ✅ DI as universal composer
- ✅ Bootstrap flow
- ✅ Layer composition
- ✅ Adding custom adapters
- ✅ Testing with DI
1. Documentation (Basic Setup) > 1.4 Migration Guide (Frappe → Framework M) ✅
Progress: 3/3 (100%)
Completed:
- ✅ Cover backend patterns
- ✅ Cover frontend patterns
- ✅ Practical examples
1. Documentation (Basic Setup) > 1.5 API Documentation ✅
Progress: 4/4 (100%)
Completed:
- ✅ Litestar auto-generates OpenAPI spec (
/schema) - ✅ Swagger UI (
/schema/swagger) - ✅ ReDoc (
/schema/redoc) - ✅ Truthfulness tests (
test_developer_docs.py::TestAPIDocumentation- 3 tests)
1. Documentation (Basic Setup) > 1.6 Example Apps ✅
Progress: 4/4 (100%)
Completed:
- ✅ Create minimal example apps:
- ✅ Simple TODO app (
docs/examples/todo/) - ✅ Basic CRM (
docs/examples/crm/) - ✅ Example index (
docs/examples/README.md)
2. Internationalization (i18n) > 2.1 Backend i18n ✅
Progress: 27/27 (100%)
Completed:
- ✅ Create
I18nProtocolinterface (core/interfaces/i18n.py): - ✅
translate(text, locale, context, default) -> str - ✅
get_locale() -> str - ✅
set_locale(locale) -> None - ✅
get_available_locales() -> list[str] - ✅ Create
InMemoryI18nAdapter(adapters/i18n/__init__.py): - ✅ Dict-based translation storage
- ✅ Add translations dynamically
- ✅ String interpolation with context
- ✅ Create
TranslationDocType: - ✅
source_text: str(original) - ✅
translated_text: str - ✅
locale: str(e.g. "hi", "ta", "en") - ✅
context: str | None(e.g. "button", "label") - ✅ Unique constraint:
(source_text, locale, context) - ✅ Create
DefaultI18nAdapter: - ✅ Load translations from DB on startup
- ✅ Cache in memory (Redis optional)
- ✅ Fallback chain: request locale → default locale → source text
- ✅ Locale resolution order:
- ✅ 1.
Accept-Languageheader - ✅ 2. User preference (
user.locale) - ✅ 3. Tenant default (
tenant.attributes.default_locale) - ✅ 4. System default (
settings.DEFAULT_LOCALE) - ✅ DocType field labels:
- ✅
Field.labelsupports i18n key - ✅ Meta API returns translated labels based on request locale
2. Internationalization (i18n) > 2.2 Frontend i18n
Progress: 11/11 (100%)
Completed:
- ✅ Install
react-i18next: - ✅ Configure with backend translations endpoint
- ✅ Lazy load locale bundles
- ✅ Translation workflow:
- ✅ Extract strings from components (
i18next-parser) - ✅ Upload to Translation DocType
- ✅ Download merged translations as JSON
- ✅ Components:
- ✅
useTranslation()hook in all components - ✅
<Trans>for interpolated strings - ✅ Locale switcher in navbar
2. Internationalization (i18n) > 2.3 Per-Tenant Locales
Progress: 3/3 (100%)
Completed:
- ✅ Tenant can override default locale
- ✅ Tenant can provide custom translations (override system)
- ✅ Tenant locale from
TenantContext.default_locale
3. Multi-Tenancy Usage & Documentation > 3.1 Tenancy Modes Documentation ✅
Progress: 12/12 (100%)
Completed:
- ✅ Document Mode A (Single Tenant / Indie):
- ✅
ImplicitTenantAdapterusage - ✅ Default tenant ID configuration
- ✅ When to use (standalone deployments)
- ✅ Document Mode B (Multi-Tenant / Enterprise):
- ✅
HeaderTenantAdapterusage - ✅ Gateway configuration (X-Tenant-ID, X-Tenant-Attributes)
- ✅ Citadel IAM integration for tenant extraction
- ✅ Document tenant isolation patterns:
- ✅ Logical isolation (tenant_id column, RLS)
- ✅ Database-per-tenant (db_binds per tenant)
- ✅ Schema-per-tenant (PostgreSQL schemas)
3. Multi-Tenancy Usage & Documentation > 3.2 Using TenantContext in Code ✅
Progress: 8/8 (100%)
Completed:
- ✅ Document injection pattern:
- ✅ Dependency injection via
request.state.tenant - ✅ Feature flags from tenant attributes
- ✅ Example endpoints using TenantContext
- ✅ Document tenant-aware queries:
- ✅ Automatic RLS filtering with GenericRepository
- ✅ Manual tenant_id filtering with FilterSpec
- ✅ Cross-tenant queries (admin only)
3. Multi-Tenancy Usage & Documentation > 3.3 Frontend Multi-Tenancy ✅
Progress: 8/8 (100%)
Completed:
- ✅ Tenant context in frontend:
- ✅ Extract from JWT or API response
- ✅ Store in React context (TenantProvider, useTenant hook)
- ✅ Pass tenant_id in API requests (if not in headers)
- ✅ Tenant-specific UI:
- ✅ Tenant branding (logo, colors) - useTenantBranding hook
- ✅ Feature flags from
tenant.attributes- FeatureGate component - ✅ Tenant selector (admin UI) - TenantSelector component
3. Multi-Tenancy Usage & Documentation > 3.4 Switching Adapters ✅
Progress: 5/5 (100%)
Completed:
- ✅ Document adapter selection:
- ✅ Configuration via
framework_config.toml(mode = "single" | "multi") - ✅ Factory function
create_tenant_adapter_from_headers() - ✅ Entrypoint registration for custom adapters
- ✅ Testing with MockTenantAdapter
4. Theming ✅
Progress: 5/5 (100%)
Completed:
- ✅ Add theme support:
- ✅ Light/dark mode with ThemeContext and useTheme hook
- ✅ Custom color schemes via CSS variables (
:rootand.dark) - ✅ Store user preference in localStorage with system detection fallback
- ✅ ThemeToggle component integrated in Navbar
5. Testing > 5.1 Frontend Tests ✅
Progress: 20/20 (100%)
Completed:
- ✅ Unit tests for components:
- ✅ Test
AutoFormrendering (12 tests) - ✅ Test
AutoTablerendering (11 tests) - ✅ Test
ThemeTogglefunctionality (6 tests) - ✅ Test form validation
- ✅ Integration tests:
- ✅ Test full CRUD flow (3 tests)
- ✅ Test theme persistence (7 tests)
- ✅ Test navigation
- ✅ Test real-time updates
- ✅ E2E tests with Playwright:
- ✅ Test user login workflows (7 tests)
- ✅ Test create record workflows (9 tests)
- ✅ Test cross-browser compatibility (10 tests)
- ✅ Test infrastructure:
- ✅ Vitest setup with happy-dom
- ✅ Testing Library integration
- ✅ Playwright configuration
- ✅ CI/CD test scripts
- ✅ Coverage reporting
Validation Checklist
Progress: 6/6 (100%)
Completed:
- ✅ Frontend can render any DocType
- ✅ Forms are generated from metadata
- ✅ Tables support sorting and filtering
- ✅ Real-time updates work
- ✅ Documentation is comprehensive
- ✅ Example apps demonstrate features
Phase 10: ERP Enterprise Features
Phase: 10 Objective: Zero-code integration with 3rd party tools (Slack, Zapier). Status: 100% Complete
1. Analytics & Read Models (CQRS) > 1.1 Read Model Protocol
Progress: 5/5 (100%)
Completed:
- ✅ Create
src/framework_m/core/interfaces/read_model.py: - ✅ Define
ReadModelProtocol: - ✅
async def project(event: Event) -> None - ✅
async def query(filters: dict) -> list[dict] - ✅
async def rebuild() -> None
1. Analytics & Read Models (CQRS) > 1.2 Enterprise Projectors
Progress: 4/4 (100%)
Completed:
- ✅ Implement
Projector(Event Handler): - ✅ Subscribe to
doc.created,doc.updated - ✅ Transform transactional data into "Read Optimized" format
- ✅ Upsert into Read Store (Postgres Read Replica, ClickHouse, Elastic)
1. Analytics & Read Models (CQRS) > 1.3 Report Engine (Scalable)
Progress: 5/5 (100%)
Completed:
- ✅ Create
ReportDocType: - ✅
report_type: - ✅
Code Report(SQL file in repo or Python Class - Indie Mode) - ✅
Analytics Report(Queries Read Model / OLAP - Enterprise Mode) - ✅
data_source: SQL / Elastic / ClickHouse adapter
2. Webhook System (Integration) > 2.1 Webhook DocType
Progress: 8/8 (100%)
Completed:
- ✅ Create
src/framework_m/public/webhook.py - ✅ Define
WebhookDocType: - ✅
doctype: str- Trigger DocType - ✅
event: str- Event name (after_save, on_submit) - ✅
url: str- Target Endpoint - ✅
headers: dict- Auth/Custom Headers - ✅
condition: str | None- JMESPath or SimpleEval expression (Noeval()) - ✅
payload_transform: str | None- Jinja2 template for JSON payload
2. Webhook System (Integration) > 2.2 Webhook Dispatcher
Progress: 4/4 (100%)
Completed:
- ✅ Implement
WebhookListener: - ✅ Subscribe to
doc.*events - ✅ Queue background job
fire_webhook - ✅ Resilience: Exponential Backoff (handled by Job Queue)
2. Webhook System (Integration) > 2.3 Webhook Visualization (Native UI)
Progress: 6/6 (100%)
Completed:
- ✅ Webhook Log DocType (defined in Phase 04):
- ✅ Stores Request/Response/Error.
- ✅ Status:
Success(Green),Failed(Red). - ✅ Desk Integration:
- ✅ Add "Recent Logs" table to
WebhookForm View. - ✅ Action: "Retry Now" button (re-queues the job).
3. Data Import / Export (Bulk)
Progress: 1/1 (100%)
Completed:
- ✅ Defined in Phase 05 CLI (See
m import --bypass-controllers)
Phase 10: Production Readiness & Deployment
Phase: 10 Objective: Optimize for production, add monitoring, implement security best practices, and create deployment configurations. Status: 0% Complete
1. Performance Optimization > 1.1 Database Optimization
Progress: 0/12 (0%)
Pending:
- ⏳ Add database indexes:
- ⏳ Index on
id(primary key, UUID) - ⏳ Index on
name(unique, human-readable identifier) - ⏳ Index on
owner(for RLS) - ⏳ Index on
modified(for sorting) - ⏳ Index on foreign keys
- ⏳ Composite indexes for common queries
- ⏳ Implement query optimization:
- ⏳ Use
select_in_loadingfor relationships - ⏳ Avoid N+1 queries
- ⏳ Add query logging in dev mode
- ⏳ Analyze slow queries
1. Performance Optimization > 1.2 Caching Strategy
Progress: 0/10 (0%)
Pending:
- ⏳ Implement multi-level caching:
- ⏳ L1: In-memory cache (per-request)
- ⏳ L2: Redis cache (shared)
- ⏳ Cache metadata (DocType schemas)
- ⏳ Cache permission checks
- ⏳ Cache frequently accessed documents
- ⏳ Add cache invalidation:
- ⏳ Invalidate on document update
- ⏳ Invalidate on permission change
- ⏳ Use cache tags for bulk invalidation
1. Performance Optimization > 1.3 Connection Pooling
Progress: 0/7 (0%)
Pending:
- ⏳ Configure SQLAlchemy pool:
- ⏳ Pool size: 20
- ⏳ Max overflow: 10
- ⏳ Pool timeout: 30s
- ⏳ Pool recycle: 3600s
- ⏳ Configure Redis pool:
- ⏳ Max connections: 50
1. Performance Optimization > 1.4 Async Optimization
Progress: 0/3 (0%)
Pending:
- ⏳ Use
asyncio.gather()for parallel operations - ⏳ Avoid blocking calls in async functions
- ⏳ Use connection pools efficiently
2. Security Hardening > 2.1 Input Validation
Progress: 0/4 (0%)
Pending:
- ⏳ Validate all inputs with Pydantic
- ⏳ Sanitize user-provided data
- ⏳ Prevent SQL injection (use parameterized queries)
- ⏳ Prevent XSS (API-only, no HTML rendering)
2. Security Hardening > 2.2 Authentication Security
Progress: 0/8 (0%)
Pending:
- ⏳ Support JWT token validation:
- ⏳ Verify signature
- ⏳ Check expiration
- ⏳ Validate issuer
- ⏳ Add rate limiting:
- ⏳ Limit login attempts
- ⏳ Limit API requests per user
- ⏳ Use Redis for rate limit storage
2. Security Hardening > 2.3 Authorization Security
Progress: 0/4 (0%)
Pending:
- ⏳ Enforce permissions on all endpoints
- ⏳ Apply RLS to all queries
- ⏳ Validate object-level permissions
- ⏳ Log permission denials
2. Security Hardening > 2.4 Secrets Management
Progress: 0/6 (0%)
Pending:
- ⏳ Never commit secrets to Git
- ⏳ Use environment variables
- ⏳ Support secret managers:
- ⏳ AWS Secrets Manager
- ⏳ Google Secret Manager
- ⏳ HashiCorp Vault
2. Security Hardening > 2.5 HTTPS & CORS
Progress: 0/4 (0%)
Pending:
- ⏳ Enforce HTTPS in production
- ⏳ Configure CORS properly:
- ⏳ Whitelist allowed origins
- ⏳ Restrict methods and headers
3. Monitoring & Observability > 3.1 Logging
Progress: 0/10 (0%)
Pending:
- ⏳ Implement structured logging:
- ⏳ Use JSON format
- ⏳ Include request ID
- ⏳ Include user context
- ⏳ Log levels: DEBUG, INFO, WARNING, ERROR
- ⏳ Log important events:
- ⏳ API requests (with timing)
- ⏳ Database queries (in dev)
- ⏳ Permission checks
- ⏳ Errors and exceptions
3. Monitoring & Observability > 3.2 Metrics
Progress: 0/7 (0%)
Pending:
- ⏳ Add Prometheus metrics:
- ⏳ Request count by endpoint
- ⏳ Request duration histogram
- ⏳ Database query duration
- ⏳ Cache hit/miss rate
- ⏳ Job queue length
- ⏳ Create
/metricsendpoint
3. Monitoring & Observability > 3.3 Tracing
Progress: 0/5 (0%)
Pending:
- ⏳ Implement OpenTelemetry:
- ⏳ Trace HTTP requests
- ⏳ Trace database queries
- ⏳ Trace background jobs
- ⏳ Export to Jaeger or Zipkin
3. Monitoring & Observability > 3.4 Health Checks
Progress: 0/7 (0%)
Pending:
- ⏳ Create
/healthendpoint: - ⏳ Check database connection
- ⏳ Check Redis connection
- ⏳ Return 200 if healthy, 503 if not
- ⏳ Create
/readyendpoint: - ⏳ Check if app is ready to serve traffic
- ⏳ Check migrations are up to date
4. Error Handling & Resilience > 4.1 Graceful Degradation
Progress: 0/3 (0%)
Pending:
- ⏳ Handle database failures gracefully
- ⏳ Handle Redis failures (fallback to no cache)
- ⏳ Retry transient errors
4. Error Handling & Resilience > 4.2 Circuit Breaker
Progress: 0/4 (0%)
Pending:
- ⏳ Implement circuit breaker for external services:
- ⏳ Webhook calls
- ⏳ Email sending
- ⏳ Print service (Gotenberg)
4. Error Handling & Resilience > 4.3 Timeouts
Progress: 0/4 (0%)
Pending:
- ⏳ Set timeouts for all operations:
- ⏳ HTTP requests: 30s
- ⏳ Database queries: 10s
- ⏳ Background jobs: 300s
5. Deployment Configurations > 5.1 Docker
Progress: 0/4 (0%)
Pending:
- ⏳ Create production
Dockerfile: - ⏳ Multi-stage build for smaller images
- ⏳ Use non-root user
- ⏳ Add health check
5. Deployment Configurations > 5.2 Docker Compose
Progress: 0/8 (0%)
Pending:
- ⏳ Create
docker-compose.yml: - ⏳ API service
- ⏳ Worker service
- ⏳ PostgreSQL
- ⏳ Redis
- ⏳ Gotenberg (for PDFs)
- ⏳ Add volumes for persistence
- ⏳ Add networks for isolation
5. Deployment Configurations > 5.3 Kubernetes
Progress: 0/11 (0%)
Pending:
- ⏳ Create Kubernetes manifests:
- ⏳ Deployment for API
- ⏳ Deployment for Worker
- ⏳ StatefulSet for PostgreSQL
- ⏳ StatefulSet for Redis
- ⏳ Service for API
- ⏳ Ingress for routing
- ⏳ Add resource limits:
- ⏳ CPU: 500m - 2000m
- ⏳ Memory: 512Mi - 2Gi
- ⏳ Add liveness and readiness probes
5. Deployment Configurations > 5.4 Cloud Platforms
Progress: 0/7 (0%)
Pending:
- ⏳ Create deployment guides for:
- ⏳ Google Cloud Run
- ⏳ AWS ECS/Fargate
- ⏳ Azure Container Apps
- ⏳ Heroku
- ⏳ Railway
- ⏳ Render
6. CI/CD Pipeline > 6.1 GitLab CI
Progress: 0/1 (0%)
Pending:
- ⏳ Configure
.gitlab-ci.yml(already exists in repo):
6. CI/CD Pipeline > 6.2 Pre-commit Hooks
Progress: 0/4 (0%)
Pending:
- ⏳ Setup pre-commit:
- ⏳ Run ruff formatter
- ⏳ Run mypy
- ⏳ Run tests
6. CI/CD Pipeline > 6.3 Release Versioning & Publishing
Progress: 0/22 (0%)
Pending:
- ⏳ Adopt Semantic Versioning (SemVer):
- ⏳
MAJOR.MINOR.PATCHformat - ⏳ Document breaking change policy
- ⏳ Use
0.x.yfor pre-1.0 releases - ⏳ CHANGELOG management:
- ⏳ Create
CHANGELOG.mdfollowing Keep a Changelog format - ⏳ Sections: Added, Changed, Deprecated, Removed, Fixed, Security
- ⏳ Option: Use git-cliff for automation
- ⏳ Link CHANGELOG to documentation site
- ⏳ Conventional Commits (optional but recommended):
- ⏳
feat:→ MINOR bump - ⏳
fix:→ PATCH bump - ⏳
feat!:orBREAKING CHANGE:→ MAJOR bump - ⏳ Setup commitlint for enforcement
- ⏳ Release workflow (add to
.gitlab-ci.yml): - ⏳ Version sources:
- ⏳ Single source of truth in
pyproject.toml - ⏳ Use dynamic versioning from git tags OR
__version__in package - ⏳ Expose version via
m --versionCLI - ⏳ Pre-release versions:
- ⏳ Support alpha/beta/rc:
1.0.0-alpha.1,1.0.0-beta.2,1.0.0-rc.1 - ⏳ Publish pre-releases to TestPyPI first
6. CI/CD Pipeline > 6.4 Git Branching Strategy
Progress: 0/22 (0%)
Pending:
- ⏳ Trunk-Based Development (recommended for M):
- ⏳ Branch naming conventions:
- ⏳
main— Always deployable, latest development - ⏳
feature/<name>— New features (merge to main via PR) - ⏳
fix/<issue-id>— Bug fixes (merge to main via PR) - ⏳
release/v<major>.<minor>— Created only when LTS support needed - ⏳ Release branches (only for LTS):
- ⏳ LTS (Long-Term Support) Policy:
- ⏳ Support last 2 major versions (not 3 like Frappe — M is simpler)
- ⏳ Security fixes: Backport to all supported versions
- ⏳ Bug fixes: Backport to latest minor of each supported major
- ⏳ Features: Only on
main, no backports - ⏳ Backporting workflow:
- ⏳ Fix on
mainfirst (always forward-fix) - ⏳ Cherry-pick to
release/vXbranch - ⏳ Tag patch release:
vX.Y.Z - ⏳ Tool: Use
git cherry-pick -xto track source commit - ⏳ Why simpler than Frappe?
- ⏳ Hexagonal architecture = Adapters can be versioned independently
- ⏳ No DB schema in core = Migrations are app-specific, not framework-specific
- ⏳ Protocol stability = Breaking changes are explicit, not hidden
- ⏳ Apps can pin framework version = No forced upgrade cascades
7. Database Migration Strategy > 7.2 Safe Changes (Auto-Migration in Dev Mode)
Progress: 0/4 (0%)
Pending:
- ⏳ Add table: New DocType → new table
- ⏳ Add nullable column: New optional field →
ALTER TABLE ADD COLUMN ... NULL - ⏳ Add index:
Meta.indexes→CREATE INDEX - ⏳ Add foreign key: Link field →
ALTER TABLE ADD CONSTRAINT
7. Database Migration Strategy > 7.3 Review-Required Changes
Progress: 0/7 (0%)
Pending:
- ⏳ Add non-nullable column without default:
- ⏳ Migration will fail if table has existing rows
- ⏳ Solution: Add with default → backfill → remove default
- ⏳ Change column type (compatible):
- ⏳
str→Text(widening): Usually safe - ⏳
int→bigint(widening): Usually safe - ⏳ Review for edge cases
7. Database Migration Strategy > 7.6 Zero-Downtime Migrations
Progress: 0/4 (0%)
Pending:
- ⏳ Never drop columns in the same deploy as code changes
- ⏳ Always add columns as nullable first
- ⏳ Always backfill data before making non-nullable
- ⏳ Always deploy code changes before dropping columns
8. Backup & Recovery > 8.1 Database Backups
Progress: 0/4 (0%)
Pending:
- ⏳ Automated daily backups
- ⏳ Store backups in S3 or equivalent
- ⏳ Retention policy (30 days)
- ⏳ Test restore process
8. Backup & Recovery > 8.2 Disaster Recovery
Progress: 0/4 (0%)
Pending:
- ⏳ Document recovery procedures
- ⏳ Test recovery regularly
- ⏳ RTO (Recovery Time Objective): 4 hours
- ⏳ RPO (Recovery Point Objective): 24 hours
9. Scaling Strategy > 9.1 Horizontal Scaling
Progress: 0/3 (0%)
Pending:
- ⏳ API servers: Stateless, scale horizontally
- ⏳ Workers: Scale based on queue length
- ⏳ Database: Use read replicas for read-heavy workloads
9. Scaling Strategy > 9.2 Load Balancing
Progress: 0/3 (0%)
Pending:
- ⏳ Use load balancer (Nginx, ALB)
- ⏳ Health check endpoints
- ⏳ Session affinity not required (stateless)
10. Documentation > 10.1 Deployment Guide
Progress: 0/3 (0%)
Pending:
- ⏳ Write step-by-step deployment guide
- ⏳ Include environment variables reference
- ⏳ Include troubleshooting section
10. Documentation > 10.2 Operations Runbook
Progress: 0/5 (0%)
Pending:
- ⏳ Document common operations:
- ⏳ Scaling up/down
- ⏳ Running migrations
- ⏳ Backup and restore
- ⏳ Monitoring and alerts
11. Testing > 11.1 Load Testing
Progress: 0/9 (0%)
Pending:
- ⏳ Use Locust or k6 for load testing
- ⏳ Test scenarios:
- ⏳ 1000 concurrent users
- ⏳ 10,000 requests/minute
- ⏳ Sustained load for 1 hour
- ⏳ Measure:
- ⏳ Response times (p50, p95, p99)
- ⏳ Error rate
- ⏳ Resource usage
11. Testing > 11.2 Security Testing
Progress: 0/4 (0%)
Pending:
- ⏳ Run security scans:
- ⏳ OWASP ZAP
- ⏳ Dependency vulnerability scan
- ⏳ Container image scan
Validation Checklist
Progress: 0/10 (0%)
Pending:
- ⏳ All tests pass (unit, integration, E2E)
- ⏳ Load testing shows acceptable performance
- ⏳ Security scans show no critical issues
- ⏳ Monitoring and alerts are configured
- ⏳ Backups are automated and tested
- ⏳ Documentation is complete
- ⏳ Deployment pipeline works
- ⏳ Health checks return 200
- ⏳ Logs are structured and useful
- ⏳ Secrets are not in code
Phase 11: Package Split & MX Pattern
Phase: 11 Objective: Enable enterprises to build custom "MX" variants (e.g., MongoDB-primary, Cassandra-primary) without forking, via pure package composition. Status: 100% Complete
1. Package Split Strategy > 1.1 Split into Core + Standard
Progress: 17/17 (100%)
Completed:
- ✅ Create
framework-m-corepackage: - ✅ All Protocols (Repository, Permission, EventBus, Cache, etc.)
- ✅ DI Container setup (
dependency-injector) - ✅ BaseDocTypeProtocol (not concrete class)
- ✅ Controller/Hook system
- ✅ CLI framework (
cycloptsbase) - ✅ Zero adapters, zero concrete implementations
- ✅ Create
framework-m-standardpackage: - ✅ Depends on
framework-m-core - ✅ SQLAlchemy adapters (SchemaMapper, GenericRepository, UnitOfWork)
- ✅ RBAC PermissionAdapter
- ✅ Redis EventBusAdapter
- ✅ Arq JobQueueAdapter
- ✅ Default Bootstrap sequence
- ✅ Create
framework-mmeta-package: - ✅ Depends on both
framework-m-core+framework-m-standard - ✅ "Batteries included" install for Indie devs
1. Package Split Strategy > 1.2 Decouple Development Tooling
Progress: 7/7 (100%)
Completed:
- ✅ Move scaffolding and codegen from
framework-mtoframework-m-studio: - ✅ Move
new:appcommand and templates - ✅ Move
new:doctypecommand and templates - ✅ Move
new:site(placeholder) to Studio - ✅ Move all Jinja2-based scaffolding code
- ✅ Goal:
framework-m(Core/Standard) should have zero dependencies on Jinja2 or LibCST. - ✅ Result:
framework-mis optimized for production containers, whileframework-m-studioremains the developer's workbench.
2. Protocols to Extract to Core > 2.1 Ensure All Protocols are Pure
Progress: 5/5 (100%)
Completed:
- ✅
RepositoryProtocol— no SQLAlchemy types - ✅
UnitOfWorkProtocol— generic session interface - ✅
SchemaMapperProtocol— Pydantic → Storage mapping - ✅
BootstrapProtocol— Startup step interface - ✅ Verify: No imports from
sqlalchemyinframework-m-core
2. Protocols to Extract to Core > 2.2 BaseDocType as Protocol
Progress: 3/3 (100%)
Completed:
- ✅ Create
BaseDocTypeProtocol: - ✅
framework-m-standardprovidesBaseDocType(BaseDocTypeProtocol)withowner,_version, etc. - ✅ MX packages can provide their own BaseDocType
3. Bootstrap via Entry Points > 3.1 Define Bootstrap Plugin System
Progress: 4/4 (100%)
Completed:
- ✅ Create entry point group:
framework_m.bootstrap - ✅ Define
BootstrapStepprotocol: - ✅ Discover and sort steps from entry points
- ✅ Allow MX packages to override steps by name
3. Bootstrap via Entry Points > 3.2 Default Bootstrap Steps (framework-m-standard)
Progress: 4/4 (100%)
Completed:
- ✅
init_engine(order=10) — Create SQLAlchemy engine - ✅
init_registries(order=20) — MetaRegistry, FieldRegistry - ✅
sync_schema(order=30) — Run SchemaMapper on all DocTypes - ✅
init_adapters(order=40) — Bind adapters to DI container
4. Adapter Auto-Discovery > 4.1 Entry Point Groups for Adapters
Progress: 5/5 (100%)
Completed:
- ✅
framework_m.adapters.repository— GenericRepository implementation - ✅
framework_m.adapters.schema_mapper— SchemaMapper implementation - ✅
framework_m.adapters.unit_of_work— UnitOfWork implementation - ✅
framework_m.adapters.permission— PermissionAdapter - ✅
framework_m.adapters.event_bus— EventBusAdapter
4. Adapter Auto-Discovery > 4.2 DI Auto-Binding
Progress: 3/3 (100%)
Completed:
- ✅ On startup, scan entry points
- ✅ Bind discovered adapters to Protocols in DI container
- ✅ Priority: Explicit config > Entry point > Default
5. Example: framework-mx-mongo > 5.1 Package Structure
Progress: 5/5 (100%)
Completed:
- ✅ Create framework-mx-mongo package with proper structure
- ✅ Implement MongoSchemaMapper (Pydantic → MongoDB collections)
- ✅ Implement MongoGenericRepository (CRUD via Motor)
- ✅ Implement MongoSessionFactory (MongoDB sessions & transactions)
- ✅ Implement MongoInit bootstrap step
5. Example: framework-mx-mongo > 5.2 Entry Point Registration
Progress: 4/4 (100%)
Completed:
- ✅ Register repository adapter entry point
- ✅ Register schema_mapper adapter entry point
- ✅ Register unit_of_work adapter entry point
- ✅ Register bootstrap entry point
5. Example: framework-mx-mongo > 5.3 Testing
Progress: 4/4 (100%)
Completed:
- ✅ Test protocol compliance for all adapters
- ✅ Test entry point registration and discovery
- ✅ Test MX pattern override scenarios
- ✅ Verify 20/20 tests passing
6. Documentation
Progress: 3/3 (100%)
Completed:
- ✅ Architecture guide: "MX Pattern ADR" (
docs/adr/0006-mx-pattern.md) - ✅ Tutorial: "MongoDB-Primary Framework MX" (
docs/tutorials/mongodb-mx-tutorial.md) - ✅ Reference: All protocol definitions (
docs/reference/protocol-reference.md)
7. Testing
Progress: 5/5 (100%)
Completed:
- ✅ Test:
framework-m-coreinstalls without SQLAlchemy - ✅ Test:
framework-m-standardadds SQLAlchemy adapters - ✅ Test: MX package can override adapters
- ✅ Test: Coverage configuration includes all workspace packages
- ✅ Test: Bootstrap order respects priority
Phase 12: LLM-Ready Documentation & Automation
Phase: 12 Objective: Create comprehensive, machine-readable documentation with automated screenshot generation and LLM-assisted content workflows. Status: 39% Complete
1. Documentation Architecture > 1.1 Source-of-Truth Hierarchy
Progress: 9/9 (100%)
Completed:
- ✅ Define documentation sources:
- ✅ ADRs (
docs/adr/) → Design decisions, rationale - ✅ Checklists (
checklists/) → Feature completion status - ✅ DocType Source (
*.py) → API reference (auto-generated) - ✅ User Docs (
docs/user/) → How-to guides - ✅ Developer Docs (
docs/developer/) → Architecture, patterns - ✅ Create documentation discovery logic (Dynamic manifest):
- ✅ Implemented in
m docs:generateandm docs:export - ✅ Auto-scans
docs/,checklists/, andsrc/doctypes/
1. Documentation Architecture > 2.2 Website Setup (Docusaurus)
Progress: 10/10 (100%)
Completed:
- ✅ Initialize Docusaurus in
website/directory: - ✅ Configure
website/docusaurus.config.ts: - ✅ Set
docs.pathto../docs(reuse existing markdown) - ✅ Set
docs.routeBasePathto/docs - ✅ Site metadata (title, tagline, URL)
- ✅ Setup
website/folder structure: - ✅ Reuse existing
docs/for content: - ✅
docs/user/-> Documentation content - ✅
docs/developer/-> Documentation content - ✅
docs/adr/-> Documentation content
2. Auto-Generated Reference Documentation > 2.1 DocType API Reference
Progress: 10/10 (100%)
Completed:
- ✅ Implement
m docs:generateCLI command: - ✅ Parse all DocTypes from MetaRegistry
- ✅ Extract JSON Schema from Pydantic models
- ✅ Scope: Includes Core, Standard, and any installed 3rd-party Apps.
- ✅ Generate markdown for each DocType:
- ✅ Field table (name, type, required, default, description)
- ✅ Permission matrix (roles × actions)
- ✅ Controller hooks (before_create, validate, etc.)
- ✅ Link to source file
- ✅ Output format matching standard template:
2. Auto-Generated Reference Documentation > 2.2 Protocol Reference
Progress: 5/5 (100%)
Completed:
- ✅ Auto-generate Protocol documentation:
- ✅ List all Protocols in
framework_m_core - ✅ Extract method signatures and docstrings
- ✅ List available adapters for each Protocol
- ✅ Generate comparison table (Indie vs Enterprise adapters)
2. Auto-Generated Reference Documentation > 2.3 OpenAPI Documentation
Progress: 4/4 (100%)
Completed:
- ✅ Export OpenAPI spec:
m docs:openapi --output docs/api/openapi.json - ✅ Generate human-readable API docs from OpenAPI
- ✅ Include request/response examples
- ✅ Group by DocType and module
2. Auto-Generated Reference Documentation > 3.1 ADR/RFC Structure Standardization
Progress: 7/7 (100%)
Completed:
- ✅ Create ADR/RFC template (
docs/adr/template.md): - ✅ Implement incremental numbering logic:
- ✅ Start with 4 digits (
0001-0999). - ✅ Automatically expand to more digits if needed (
10000+). - ✅ CI check to ensure no duplicate or skipped numbers in PRs.
- ✅ Add CLI:
m docs:adr create "Title"→ Creates numbered ADR from template. - ✅ Add CLI:
m docs:rfc create "Title"→ Creates numbered RFC from template.
2. Auto-Generated Reference Documentation > 3.2 Automated Chronological Indexing
Progress: 5/5 (100%)
Completed:
- ✅ Implement
m docs:adr index: - ✅ Scans
docs/adr/anddocs/rfcs/. - ✅ Generates
index.mdfor both with a chronological list. - ✅ Anchored "At-a-glance" view for quick reference.
- ✅ Support lazy-loading behavior in Docusaurus (similar to blog).
4. Checklist-to-Feature Documentation > 4.1 Feature Extraction
Progress: 0/4 (0%)
Pending:
- ⏳ Parse checklists for completed items (
[x]) - ⏳ Group by phase and category
- ⏳ Generate "Features" page with completion status
- ⏳ Link features to relevant documentation sections
4. Checklist-to-Feature Documentation > 4.2 Release Notes Generation
Progress: 0/3 (0%)
Pending:
- ⏳ Track checklist changes between versions (git diff)
- ⏳ Auto-generate release notes from newly completed items
- ⏳ Format:
CHANGELOG.mdor GitHub Release notes
5. Automated Screenshot Pipeline > 5.1 Screenshot Manifest
Progress: 0/1 (0%)
Pending:
- ⏳ Create
docs/screenshots.yaml:
5. Automated Screenshot Pipeline > 5.2 Playwright Screenshot Automation
Progress: 0/10 (0%)
Pending:
- ⏳ Create
scripts/generate-screenshots.ts: - ⏳ Read
screenshots.yaml - ⏳ Start dev server (
m start) - ⏳ For each screenshot:
- ⏳ Navigate to URL
- ⏳ Wait for selector
- ⏳ Capture screenshot
- ⏳ Save to output path
- ⏳ Generate diff report (new vs old screenshots)
- ⏳ Install dependencies:
5. Automated Screenshot Pipeline > 5.3 Screenshot CI Workflow
Progress: 0/4 (0%)
Pending:
- ⏳ Add to
.gitlab-ci.yml: - ⏳ Auto-commit screenshots (optional):
- ⏳ Use
git pushin CI with deploy token - ⏳ Or: Create MR with updated screenshots for review
5. Automated Screenshot Pipeline > 5.4 Screenshot Staleness Detection
Progress: 0/4 (0%)
Pending:
- ⏳ Add timestamp to screenshot manifest
- ⏳ Compare file modification time vs manifest timestamp
- ⏳ Warn in CI if screenshots are stale (>30 days)
- ⏳ Option to regenerate on schedule (weekly)
6. Machine-Readable Documentation (RAG/LLM) > 6.1 Structured DocType Export
Progress: 0/1 (0%)
Pending:
- ⏳ Implement
m docs:export --format yaml:
6. Machine-Readable Documentation (RAG/LLM) > 6.2 RAG Corpus Generation
Progress: 3/3 (100%)
Completed:
- ✅ Implement
m docs:export --format jsonl --output docs/machine/corpus.jsonl: - ✅ Chunk content appropriately for embeddings (500-1000 tokens)
- ✅ Include metadata for filtering (type, module, version)
6. Machine-Readable Documentation (RAG/LLM) > 6.3 Agent Knowledge Base
Progress: 0/2 (0%)
Pending:
- ⏳ Create
.agent/knowledge/directory structure: - ⏳ Auto-update on each build/deploy
6. Machine-Readable Documentation (RAG/LLM) > 6.4 Inline Code Documentation
Progress: 0/3 (0%)
Pending:
- ⏳ Ensure all Protocols have comprehensive docstrings:
- ⏳ Add
Examplessections to all public APIs - ⏳ Use Google-style docstrings for consistency
6. Machine-Readable Documentation (RAG/LLM) > 6.5 LLM Docs Distribution & Sync (Federated Knowledge)
Progress: 0/9 (0%)
Pending:
- ⏳ Publication Strategy:
- ⏳ Include machine-readable assets in documentation build artifacts.
- ⏳ Path:
docs/static/llm/v{version}/corpus.jsonl. - ⏳ Configuration (
framework_config.toml): - ⏳ Sync Command (
m docs:sync): - ⏳ Fetches upstream corpus from
upstream_url. - ⏳ Generates local project corpus via
m docs:export. - ⏳ Merges upstream + local into
.agent/knowledge/combined.jsonl. - ⏳ Updates
.agent/context/project.mdwith summary of available knowledge.
7. LLM-Assisted Documentation Workflow > 7.1 Documentation Gap Detection
Progress: 0/6 (0%)
Pending:
- ⏳ Create
m docs:auditcommand: - ⏳ Scan all DocTypes for missing descriptions
- ⏳ Check all Protocols for missing docstrings
- ⏳ Identify ADRs without implementation links
- ⏳ Report undocumented controller hooks
- ⏳ Output:
docs/audit-report.md
7. LLM-Assisted Documentation Workflow > 7.2 LLM Documentation Generator
Progress: 0/6 (0%)
Pending:
- ⏳ Create
m docs:draftcommand: - ⏳ Input: Source file or DocType name
- ⏳ Process: Send code + context to LLM
- ⏳ Output: Draft documentation in markdown
- ⏳ Human reviews and edits before commit
- ⏳ Prompt template:
7. LLM-Assisted Documentation Workflow > 7.3 Diff-Based Documentation Updates
Progress: 0/5 (0%)
Pending:
- ⏳ Create
m docs:updatecommand: - ⏳ Input: Git diff of code changes
- ⏳ Process: Identify affected documentation sections
- ⏳ Output: Suggested documentation updates
- ⏳ Human reviews and applies changes
8. Documentation Deployment > 8.1 Build Pipeline
Progress: 0/4 (0%)
Pending:
- ⏳ Add docs build to
.gitlab-ci.yml: - ⏳ Deploy to GitLab Pages:
- ⏳ Docs available at
https://\<namespace\>.gitlab.io/\<project\>/ - ⏳ Custom domain: Configure in Settings → Pages
8. Documentation Deployment > 8.2 Versioned Documentation
Progress: 0/21 (0%)
Pending:
- ⏳ Use Docusaurus for documentation (update Section 1.2):
- ⏳ Enable Docusaurus versioning:
- ⏳ Version strategy (aligned with git branching):
- ⏳
Next→ Currentmainbranch (unstable, latest features) - ⏳
1.0.x,2.0.x→ Tagged releases (stable) - ⏳ Archive versions when LTS support ends
- ⏳ Configure
docusaurus.config.js: - ⏳ Sync with release workflow:
- ⏳ On git tag
vX.Y.0(minor/major): Create new docs version - ⏳ On git tag
vX.Y.Z(patch): Update existing version docs - ⏳ Archive docs when
release/vXbranch is EOL - ⏳ Version banner for old docs:
- ⏳ Docusaurus built-in: "This is documentation for version X.0."
- ⏳ Per-version API reference:
- ⏳ Generate OpenAPI spec per version
- ⏳ Store in
docs/static/api/v{version}/openapi.json - ⏳ Embed Swagger UI or Redoc in versioned docs
- ⏳ Per-version LLM Corpus:
- ⏳ Generate
corpus.jsonlanddoctypes.yamlfor each version. - ⏳ Store in
docs/static/llm/v{version}/. - ⏳ Allows agents to sync docs matching their installed framework version.
8. Documentation Deployment > 8.3 Search Integration
Progress: 4/4 (100%)
Completed:
- ✅ Add search integration (Searchable ADRs, RFCs, and Docs):
- ✅ Use
docusaurus-plugin-search-localor similar - ✅ Ensure
docs/adr/anddocs/rfcs/are indexed - ✅ Include code examples in search
9. Testing Documentation > 9.1 Documentation Tests
Progress: 0/7 (0%)
Pending:
- ⏳ Test code examples compile/run:
- ⏳ Extract code blocks from markdown
- ⏳ Run against test environment
- ⏳ Fail CI if examples are broken
- ⏳ Test internal links:
- ⏳ Check all markdown links resolve
- ⏳ Check all file references exist
9. Testing Documentation > 9.2 Screenshot Regression Tests
Progress: 0/3 (0%)
Pending:
- ⏳ Compare new screenshots to baseline
- ⏳ Alert on unexpected visual changes
- ⏳ Require manual approval for UI changes
10. Documentation Contribution Guide > 10.1 For Contributors
Progress: 0/5 (0%)
Pending:
- ⏳ Create
docs/CONTRIBUTING.md: - ⏳ How to write documentation
- ⏳ Style guide (tone, formatting)
- ⏳ How to add new screenshots
- ⏳ How to update ADRs
10. Documentation Contribution Guide > 10.2 For AI Agents
Progress: 0/4 (0%)
Pending:
- ⏳ Create
.agent/knowledge/documentation-patterns.md: - ⏳ How Framework M documentation is structured
- ⏳ Where to find different types of information
- ⏳ How to suggest documentation improvements
11. LLM-Assisted Development Support > 11.1 Why TDD Enables LLM Coding
Progress: 5/5 (100%)
Completed:
- ✅ Document the TDD-LLM workflow:
- ✅ Tests are executable specifications — LLM knows what "correct" means
- ✅ Test failures are feedback — LLM can self-correct
- ✅ Type hints + mypy are compile-time checks — catch errors before runtime
- ✅ Protocol interfaces are contracts (Documented in developer guides)
11. LLM-Assisted Development Support > 11.2 Agent-Ready Repository Structure
Progress: 2/2 (100%)
Completed:
- ✅ Create
.agent/directory for AI coding assistants: - ✅
.agent/workflows/populated with key tasks
11. LLM-Assisted Development Support > 11.3 Test-First Development for LLM
Progress: 0/2 (0%)
Pending:
- ⏳ Provide test templates for common patterns:
- ⏳ Document test commands in
.agent/workflows/run-tests.md:
11. LLM-Assisted Development Support > 11.4 LLM-Friendly Error Messages
Progress: 0/5 (0%)
Pending:
- ⏳ Ensure error messages are actionable:
- ⏳ Include expected vs actual values
- ⏳ Reference relevant documentation
- ⏳ Suggest fixes when possible
- ⏳ Custom exceptions with context:
11. LLM-Assisted Development Support > 11.5 Agentic Coding Workflow
Progress: 2/2 (100%)
Completed:
- ✅ Document the agentic workflow for Framework M (See
ArchitectureandQualityguides) - ✅ Create
.agent/workflows/with development best practices
11. LLM-Assisted Development Support > 11.7 RAG Corpus for Code Completion
Progress: 0/7 (0%)
Pending:
- ⏳ Include code examples in RAG corpus:
- ⏳ Annotated examples of each pattern
- ⏳ Common mistakes and their fixes
- ⏳ Before/after refactoring examples
- ⏳ Export tests as documentation:
- ⏳ Tests show "how to use" each component
- ⏳
m docs:export --include-testsadds test patterns to corpus
Validation Checklist
Progress: 9/12 (75%)
Completed:
- ✅
m docs:generateproduces complete API reference - ✅
m docs:export --format jsonlexports RAG corpus - ✅ All DocTypes have descriptions
- ✅ All Protocols have docstrings (in code)
- ✅ Documentation site builds without errors
- ✅ Search works across all documentation
- ✅
.agent/directory structure in place - ✅ Agentic workflow documented (in intro/developer docs)
- ✅ LLM can run tests and self-correct (verified manually)
Pending:
- ⏳ Screenshot pipeline runs in CI
- ⏳ Code examples in docs are tested
- ⏳ Test templates provided for LLM coding
Phase 13: UI/UX Polish & Design System Enhancement
Phase: 13 Objective: Polish the existing custom design system to create a modern, accessible UI that attracts both users and developers. Status: 0% Complete
1. Audit Current Design System > 1.1 Review Existing Implementation
Progress: 0/9 (0%)
Pending:
- ⏳ Audit
frontend/src/App.cssdesign tokens: - ⏳ Color palette (currently sky blue
#0ea5e9) - ⏳ Typography (Inter font family)
- ⏳ Spacing scale (xs to xl)
- ⏳ Border radius (sm, md, lg)
- ⏳ Shadows
- ⏳ Review dark mode implementation in
ThemeContext - ⏳ Test current mobile responsiveness
- ⏳ Run accessibility audit (Lighthouse, axe-core)
1. Audit Current Design System > 1.2 Identify Gaps
Progress: 0/4 (0%)
Pending:
- ⏳ Document missing components (tooltips, dropdowns, etc.)
- ⏳ Identify inconsistent spacing/colors
- ⏳ List accessibility issues (contrast, keyboard nav, ARIA)
- ⏳ Note missing animations/transitions
2. Refine Color Palette > 2.1 Update to Deep Blue (Trust Theme)
Progress: 0/2 (0%)
Pending:
- ⏳ Replace current sky blue (
#0ea5e9) with deep blue palette: - ⏳ Update semantic colors:
2. Refine Color Palette > 2.2 Verify WCAG AA Contrast
Progress: 0/5 (0%)
Pending:
- ⏳ Test all text/background combinations
- ⏳ Ensure minimum 4.5:1 contrast for normal text
- ⏳ Ensure minimum 3:1 contrast for UI components
- ⏳ Test in both light and dark modes
- ⏳ Use tools: WebAIM Contrast Checker, Lighthouse
2. Refine Color Palette > 2.3 Update Dark Mode Colors
Progress: 0/3 (0%)
Pending:
- ⏳ Refine dark mode palette for better contrast
- ⏳ Test readability in low-light environments
- ⏳ Ensure primary blue works in dark mode (
#38bdf8)
3. Typography & Spacing Refinement > 3.1 Typography Scale
Progress: 0/4 (0%)
Pending:
- ⏳ Review current font sizes (14px base)
- ⏳ Add missing heading sizes if needed
- ⏳ Ensure consistent line-heights (1.3 for headings, 1.5 for body)
- ⏳ Test readability at different viewport sizes
3. Typography & Spacing Refinement > 3.2 Spacing Consistency
Progress: 0/4 (0%)
Pending:
- ⏳ Audit all components for consistent spacing
- ⏳ Use spacing scale consistently (xs, sm, md, lg, xl)
- ⏳ Fix any hard-coded pixel values
- ⏳ Document spacing patterns (e.g., card padding, button spacing)
4. Component Polish > 4.1 Buttons
Progress: 0/5 (0%)
Pending:
- ⏳ Add hover/active/focus states
- ⏳ Add loading state (spinner)
- ⏳ Add disabled state styling
- ⏳ Ensure consistent sizing (height, padding)
- ⏳ Add keyboard focus indicators (visible outline)
4. Component Polish > 4.2 Form Inputs
Progress: 0/5 (0%)
Pending:
- ⏳ Polish input focus states (already has blue ring)
- ⏳ Add error state styling (red border + message)
- ⏳ Add success state styling (green border)
- ⏳ Improve placeholder text contrast
- ⏳ Add floating labels (optional enhancement)
4. Component Polish > 4.3 Tables
Progress: 0/5 (0%)
Pending:
- ⏳ Add row hover effects (already exists)
- ⏳ Add sortable column indicators
- ⏳ Add loading skeleton for data tables
- ⏳ Improve mobile table responsiveness (card view)
- ⏳ Add empty state illustration
4. Component Polish > 4.4 Cards
Progress: 0/4 (0%)
Pending:
- ⏳ Add subtle shadow on hover
- ⏳ Ensure consistent border radius
- ⏳ Add loading skeleton variant
- ⏳ Test card layouts on mobile
4. Component Polish > 4.5 Sidebar
Progress: 0/5 (0%)
Pending:
- ⏳ Polish active state (already uses primary color)
- ⏳ Add smooth collapse animation
- ⏳ Improve search input styling
- ⏳ Add keyboard navigation support
- ⏳ Test mobile drawer behavior
4. Component Polish > 4.6 Navbar
Progress: 0/4 (0%)
Pending:
- ⏳ Polish search bar styling
- ⏳ Add user menu dropdown
- ⏳ Add notification badge
- ⏳ Ensure consistent height (56px)
5. Animations & Micro-interactions > 5.1 Add CSS Transitions
Progress: 0/5 (0%)
Pending:
- ⏳ Button hover effects (0.15s ease)
- ⏳ Input focus transitions (0.15s ease)
- ⏳ Sidebar item hover (0.15s ease)
- ⏳ Card hover effects (subtle lift)
- ⏳ Modal/drawer slide-in animations
5. Animations & Micro-interactions > 5.2 Loading States
Progress: 0/6 (0%)
Pending:
- ⏳ Add skeleton loaders for:
- ⏳ List view (table rows)
- ⏳ Form view (form fields)
- ⏳ Dashboard (cards)
- ⏳ Add spinner component for buttons
- ⏳ Add page transition fade
5. Animations & Micro-interactions > 5.3 Optimistic UI Updates
Progress: 0/4 (0%)
Pending:
- ⏳ Instant feedback on create (fade in new row)
- ⏳ Instant feedback on update (highlight changed row)
- ⏳ Instant feedback on delete (fade out row)
- ⏳ Rollback on error with toast notification
6. Mobile Optimization > 6.1 Responsive Layouts
Progress: 0/8 (0%)
Pending:
- ⏳ Test all screens on mobile viewports:
- ⏳ 320px (iPhone SE)
- ⏳ 375px (iPhone 12/13)
- ⏳ 414px (iPhone 12 Pro Max)
- ⏳ 768px (iPad)
- ⏳ Ensure sidebar collapses to drawer on mobile
- ⏳ Test table responsiveness (switch to card view)
- ⏳ Ensure touch targets are min 44px
6. Mobile Optimization > 6.2 Mobile-Specific Enhancements
Progress: 0/4 (0%)
Pending:
- ⏳ Add swipe gestures for sidebar drawer
- ⏳ Optimize form layouts for mobile (single column)
- ⏳ Add bottom navigation (optional)
- ⏳ Test keyboard behavior on mobile browsers
7. Accessibility (WCAG 2.1 AA) > 7.1 Color Contrast
Progress: 0/4 (0%)
Pending:
- ⏳ Run automated contrast checks (Lighthouse)
- ⏳ Fix any failing combinations
- ⏳ Ensure all interactive elements meet 3:1 minimum
- ⏳ Test with color blindness simulators
7. Accessibility (WCAG 2.1 AA) > 7.2 Keyboard Navigation
Progress: 0/8 (0%)
Pending:
- ⏳ Test tab order for all pages
- ⏳ Add visible focus indicators (already has some)
- ⏳ Implement keyboard shortcuts:
- ⏳
Ctrl+Kfor command palette (already exists) - ⏳
Escto close modals/drawers - ⏳ Arrow keys for table navigation
- ⏳
Enterto activate buttons - ⏳ Add skip navigation links
7. Accessibility (WCAG 2.1 AA) > 7.3 Screen Reader Support
Progress: 0/7 (0%)
Pending:
- ⏳ Add ARIA labels to all interactive elements
- ⏳ Add ARIA live regions for dynamic content (toasts, notifications)
- ⏳ Test with screen readers:
- ⏳ NVDA (Windows)
- ⏳ JAWS (Windows)
- ⏳ VoiceOver (macOS/iOS)
- ⏳ Add meaningful alt text for images/icons
7. Accessibility (WCAG 2.1 AA) > 7.4 Form Accessibility
Progress: 0/4 (0%)
Pending:
- ⏳ Ensure all inputs have associated labels
- ⏳ Add ARIA descriptions for error messages
- ⏳ Add required field indicators (
*or "required" text) - ⏳ Add field help text with
aria-describedby
8. Missing Components > 8.1 Add Essential Components
Progress: 0/8 (0%)
Pending:
- ⏳ Tooltip - For icon buttons and help text
- ⏳ Dropdown Menu - For user menu, actions
- ⏳ Toast Notifications - For success/error messages
- ⏳ Modal Dialog - For confirmations, forms
- ⏳ Badge - For counts, status indicators
- ⏳ Alert - For warnings, errors, info messages
- ⏳ Tabs - For multi-section forms/views
- ⏳ Accordion - For collapsible sections
8. Missing Components > 8.2 Implementation Approach
Progress: 0/4 (0%)
Pending:
- ⏳ Use vanilla CSS + React state (no library)
- ⏳ Follow existing design token patterns
- ⏳ Ensure dark mode support
- ⏳ Add to component library documentation
9. Documentation > 9.1 Design System Documentation
Progress: 0/7 (0%)
Pending:
- ⏳ Create
docs/design-system.md: - ⏳ Color palette with hex codes
- ⏳ Typography scale
- ⏳ Spacing system
- ⏳ Component patterns
- ⏳ Animation principles
- ⏳ Accessibility guidelines
9. Documentation > 9.2 Component Documentation
Progress: 0/5 (0%)
Pending:
- ⏳ Document each component with:
- ⏳ Usage examples
- ⏳ Props/variants
- ⏳ Accessibility notes
- ⏳ Code snippets
9. Documentation > 9.3 Storybook (Optional)
Progress: 0/4 (0%)
Pending:
- ⏳ Set up Storybook for component showcase
- ⏳ Create stories for all components
- ⏳ Add dark mode toggle in Storybook
- ⏳ Deploy Storybook for team reference
10. Performance Optimization > 10.1 CSS Optimization
Progress: 0/4 (0%)
Pending:
- ⏳ Remove unused CSS rules
- ⏳ Minimize CSS file size
- ⏳ Use CSS containment where applicable
- ⏳ Optimize font loading (already using Google Fonts)
10. Performance Optimization > 10.2 Bundle Size
Progress: 0/4 (0%)
Pending:
- ⏳ Analyze bundle size with Vite build
- ⏳ Code-split large components
- ⏳ Lazy load routes
- ⏳ Optimize images (use WebP, lazy loading)
10. Performance Optimization > 10.3 Runtime Performance
Progress: 0/4 (0%)
Pending:
- ⏳ Test First Contentful Paint (FCP) - target
< 1.5s - ⏳ Test Time to Interactive (TTI) - target
< 3s - ⏳ Test Largest Contentful Paint (LCP) - target
< 2.5s - ⏳ Optimize re-renders (React.memo, useMemo)
11. Testing > 11.1 Visual Regression Testing
Progress: 0/7 (0%)
Pending:
- ⏳ Set up Chromatic or Percy (optional)
- ⏳ Create visual snapshots for key pages
- ⏳ Test across browsers:
- ⏳ Chrome
- ⏳ Firefox
- ⏳ Safari
- ⏳ Edge
11. Testing > 11.2 Accessibility Testing
Progress: 0/4 (0%)
Pending:
- ⏳ Run Lighthouse accessibility audit (target 100)
- ⏳ Run axe-core automated tests
- ⏳ Manual keyboard-only testing
- ⏳ Manual screen reader testing
11. Testing > 11.3 Cross-Browser Testing
Progress: 0/4 (0%)
Pending:
- ⏳ Test on Windows (Chrome, Firefox, Edge)
- ⏳ Test on macOS (Chrome, Firefox, Safari)
- ⏳ Test on iOS (Safari, Chrome)
- ⏳ Test on Android (Chrome)
12. Example Screens Enhancement > 12.1 Polish Reference Screens
Progress: 0/5 (0%)
Pending:
- ⏳ Dashboard - Add chart widgets, metric cards
- ⏳ List View - Polish filters, search, pagination
- ⏳ Form View - Polish validation, error states
- ⏳ Detail View - Add tabs, related lists
- ⏳ Settings Page - Add sections, save states
12. Example Screens Enhancement > 12.2 Create Demo Content
Progress: 0/6 (0%)
Pending:
- ⏳ Add sample data for screenshots
- ⏳ Create video walkthrough showing:
- ⏳ Dark mode toggle
- ⏳ Mobile responsiveness
- ⏳ Smooth animations
- ⏳ Accessibility features
Validation Checklist
Progress: 0/8 (0%)
Pending:
- ⏳ Deep blue color palette is consistently applied
- ⏳ Dark mode works perfectly across all screens
- ⏳ Mobile responsiveness is 100% (tested on real devices)
- ⏳ WCAG 2.1 AA compliance verified (Lighthouse score 100)
- ⏳ All animations are smooth (60fps)
- ⏳ No UI library dependencies (pure CSS + React)
- ⏳ Design system is documented
- ⏳ Developers say: "Wow, this looks professional!"
Phase 14: Studio Enhancements
Phase: 14 Objective: Add advanced features to Studio for improved developer experience, including live preview, sandbox mode, and hot reload. Status: 0% Complete
1. Live Preview & Sandbox Mode > 1.2 Branch Selector
Progress: 0/4 (0%)
Pending:
- ⏳ Add branch selector to Studio UI
- ⏳ Allow switching between branches
- ⏳ Show current branch in header
- ⏳ Warn before switching with unsaved changes
1. Live Preview & Sandbox Mode > 1.3 Preview Tab Implementation
Progress: 0/3 (0%)
Pending:
- ⏳ Add "Preview" tab to DocType editor
- ⏳ Toggle between "Schema Editor" and "Sandbox"
- ⏳ Preserve editor state when switching tabs
1. Live Preview & Sandbox Mode > 1.4 Mock Data Generation
Progress: 0/10 (0%)
Pending:
- ⏳ Install
@faker-js/fakerfor mock data - ⏳ Create mock data generator service:
- ⏳ Generate data based on field types:
- ⏳ String → faker.lorem.words()
- ⏳ Number → faker.number.int()
- ⏳ Date → faker.date.recent()
- ⏳ Email → faker.internet.email()
- ⏳ Link → Random ID from related DocType
- ⏳ Respect field constraints (min, max, required)
- ⏳ Generate 5-100 mock records
1. Live Preview & Sandbox Mode > 1.5 Form Preview
Progress: 0/4 (0%)
Pending:
- ⏳ Render
AutoFormcomponent with mock document - ⏳ Show validation errors for required fields
- ⏳ Allow editing mock data
- ⏳ Show save/cancel buttons (non-functional)
1. Live Preview & Sandbox Mode > 1.6 List Preview
Progress: 0/4 (0%)
Pending:
- ⏳ Render
AutoTablecomponent with mock rows - ⏳ Show 5-10 rows by default
- ⏳ Add pagination controls
- ⏳ Show filters and search (non-functional)
1. Live Preview & Sandbox Mode > 1.7 In-Memory Schema Source
Progress: 0/4 (0%)
Pending:
- ⏳ Use in-memory schema (not saved file)
- ⏳ Allow instant preview without saving
- ⏳ Update preview on field changes
- ⏳ Debounce preview updates (500ms)
2. Interactive Sandbox (CRUD Simulation) > 2.1 In-Memory Data Store
Progress: 0/4 (0%)
Pending:
- ⏳ Create in-memory store for mock documents
- ⏳ Store per DocType (isolated)
- ⏳ Reset on page reload
- ⏳ Support up to 1000 mock records
2. Interactive Sandbox (CRUD Simulation) > 2.2 CRUD Operations
Progress: 0/16 (0%)
Pending:
- ⏳ Create: Add new mock document
- ⏳ Validate required fields
- ⏳ Show validation errors
- ⏳ Add to in-memory store
- ⏳ Show success message
- ⏳ Read: View mock document details
- ⏳ Render form in read-only mode
- ⏳ Show all field values
- ⏳ Update: Edit existing mock document
- ⏳ Validate changes
- ⏳ Update in-memory store
- ⏳ Show success message
- ⏳ Delete: Remove mock document
- ⏳ Show confirmation dialog
- ⏳ Remove from in-memory store
- ⏳ Show success message
2. Interactive Sandbox (CRUD Simulation) > 2.3 List Operations
Progress: 0/7 (0%)
Pending:
- ⏳ List (Few): Show 5 rows
- ⏳ Test basic list rendering
- ⏳ Test row actions (edit, delete)
- ⏳ List (Many): Generate 100+ rows
- ⏳ Test pagination
- ⏳ Test performance
- ⏳ Test scroll behavior
2. Interactive Sandbox (CRUD Simulation) > 2.4 Filter & Search
Progress: 0/4 (0%)
Pending:
- ⏳ Implement client-side filtering
- ⏳ Implement client-side search
- ⏳ Show filtered results count
- ⏳ Test filter combinations
2. Interactive Sandbox (CRUD Simulation) > 2.5 Validation Testing
Progress: 0/4 (0%)
Pending:
- ⏳ Submit form with missing required fields
- ⏳ Show field-level error messages
- ⏳ Show form-level error summary
- ⏳ Test custom validation rules
3. Local Hot Reload (Advanced) > 3.1 Prerequisites
Progress: 0/3 (0%)
Pending:
- ⏳ Local Postgres/SQLite running
- ⏳
m startrunning on localhost - ⏳ Database connection configured
3. Local Hot Reload (Advanced) > 3.2 File Watcher Setup
Progress: 0/4 (0%)
Pending:
- ⏳ Install
chokidarfor file watching - ⏳ Watch DocType files for changes
- ⏳ Debounce file change events (1s)
- ⏳ Ignore temporary files (.swp, .tmp)
3. Local Hot Reload (Advanced) > 3.3 Schema Sync Trigger
Progress: 0/4 (0%)
Pending:
- ⏳ Detect DocType file changes
- ⏳ Parse updated DocType
- ⏳ Generate schema diff
- ⏳ Send sync request to backend
3. Local Hot Reload (Advanced) > 3.4 Backend Schema Sync Endpoint
Progress: 0/6 (0%)
Pending:
- ⏳ Create
POST /studio/api/sync-schema - ⏳ Accept DocType schema
- ⏳ Generate SQLAlchemy table
- ⏳ Run ALTER TABLE if table exists
- ⏳ Create table if new
- ⏳ Return sync status
3. Local Hot Reload (Advanced) > 3.5 Real CRUD Operations
Progress: 0/4 (0%)
Pending:
- ⏳ Switch from mock data to real API calls
- ⏳ Use Framework M API (
/api/v1/{doctype}) - ⏳ Show real validation errors
- ⏳ Persist data to local database
3. Local Hot Reload (Advanced) > 3.6 Hot Reload UI
Progress: 0/4 (0%)
Pending:
- ⏳ Add "Hot Reload" toggle in Studio settings
- ⏳ Show connection status indicator
- ⏳ Show sync progress
- ⏳ Show sync errors
4. Advanced Preview Features > 4.1 Responsive Preview
Progress: 0/6 (0%)
Pending:
- ⏳ Add device size selector:
- ⏳ Desktop (1920px)
- ⏳ Tablet (768px)
- ⏳ Mobile (375px)
- ⏳ Resize preview iframe
- ⏳ Test responsive layouts
4. Advanced Preview Features > 4.2 Dark Mode Preview
Progress: 0/3 (0%)
Pending:
- ⏳ Add dark mode toggle in preview
- ⏳ Test components in both modes
- ⏳ Ensure contrast compliance
4. Advanced Preview Features > 4.3 Accessibility Preview
Progress: 0/4 (0%)
Pending:
- ⏳ Add accessibility checker
- ⏳ Show WCAG violations
- ⏳ Highlight problematic elements
- ⏳ Suggest fixes
4. Advanced Preview Features > 4.4 Performance Preview
Progress: 0/4 (0%)
Pending:
- ⏳ Show render time
- ⏳ Show component count
- ⏳ Show bundle size estimate
- ⏳ Warn on performance issues
5. Collaboration Features > 5.1 Real-Time Collaboration (Optional)
Progress: 0/4 (0%)
Pending:
- ⏳ Add WebSocket support
- ⏳ Show other users editing same DocType
- ⏳ Show cursor positions
- ⏳ Implement operational transformation (OT)
5. Collaboration Features > 5.2 Change Tracking
Progress: 0/4 (0%)
Pending:
- ⏳ Show unsaved changes indicator
- ⏳ Show diff view (before/after)
- ⏳ Allow reverting changes
- ⏳ Show change history
5. Collaboration Features > 5.3 Comments & Annotations
Progress: 0/4 (0%)
Pending:
- ⏳ Add comment threads on fields
- ⏳ Show unresolved comments count
- ⏳ Allow @mentions
- ⏳ Integrate with Git PR comments
6. Schema Change Detection (Developer Guardrails)
Progress: 0/13 (0%)
Pending:
- ⏳ Implement
SchemaAnalyzerclass: - ⏳ Compare Pydantic models with current DB schema
- ⏳ Classify changes: SAFE, WARNING, DANGEROUS
- ⏳ Generate actionable messages with docs links
- ⏳ CLI integration (
m migrate:create): - ⏳ Show analysis before generating migration
- ⏳ Block on DANGEROUS changes (cannot auto-generate)
- ⏳ Warn on WARNING changes (require
--force) - ⏳ Link to migration pattern documentation
- ⏳ Studio UI integration:
- ⏳ Show warnings when saving DocType
- ⏳ Recommend safer alternatives (nullable, defaults)
- ⏳ "Save Anyway" escape hatch
7. DocType Discovery & Scanning
Progress: 0/4 (0%)
Pending:
- ⏳ Optimize DocType scanning performance
- ⏳ Implement AST-based parsing
- ⏳ Handle large codebases (1000+ DocTypes)
- ⏳ Add caching strategy for development mode
9. Desk View Configuration
Progress: 0/11 (0%)
Pending:
- ⏳ Workspace Configurator:
- ⏳ UI to creating/managing workspaces (Sidebar items)
- ⏳ Assign DocTypes to workspaces
- ⏳ Define workspace shortcuts and charts
- ⏳ Configure sidebar ordering and visibility
- ⏳ Role-based workspace access permissions
- ⏳ View Builders:
- ⏳ Kanban View configurator (columns, cards)
- ⏳ Calendar View configurator (start/end fields)
- ⏳ Gantt View configurator (dependencies)
- ⏳ Map View configurator (geo fields)
10. Portal Builder (Puck Integration)
Progress: 0/14 (0%)
Pending:
- ⏳ Puck Integration:
- ⏳ Create
PuckEditorwrapper component in Studio - ⏳ Implement
StorageAdapterto save pages asWebPageDocType - ⏳ Implement
ViewAdapterto render published pages - ⏳ Component Bridge (The "Design System"):
- ⏳ Map Framework M UI components to Puck Config
- ⏳ Create
Herocomponent (Title, Subtitle, Image, CTA) - ⏳ Create
CardGridcomponent (Dynamic List) - ⏳ Create
Formcomponent (Connect to DocType) - ⏳ Create
Logincomponent - ⏳ Data Binding (Advanced):
- ⏳ Create
FrameworkMDataProviderfor Puck "Root" - ⏳ Fetch data from
/api/v1/content/:slug - ⏳ Pass data into Puck zones/components
11. Testing > 11.1 Unit Tests
Progress: 0/4 (0%)
Pending:
- ⏳ Test mock data generator
- ⏳ Test in-memory CRUD operations
- ⏳ Test file watcher
- ⏳ Test schema sync logic
11. Testing > 11.2 Integration Tests
Progress: 0/4 (0%)
Pending:
- ⏳ Test full sandbox workflow
- ⏳ Test hot reload with real database
- ⏳ Test preview rendering
- ⏳ Test collaboration features
12. Validation Checklist
Progress: 0/6 (0%)
Pending:
- ⏳ Sandbox preview works for all field types
- ⏳ Mock data generation is realistic
- ⏳ CRUD operations work in sandbox
- ⏳ Hot reload syncs schema correctly
- ⏳ Preview is responsive and accessible
- ⏳ File watcher is reliable