framework-m 0.6.9__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {framework_m-0.6.9 → framework_m-0.7.0}/.gitignore +7 -8
  2. {framework_m-0.6.9 → framework_m-0.7.0}/CHANGELOG.md +11 -1
  3. {framework_m-0.6.9 → framework_m-0.7.0}/PKG-INFO +2 -2
  4. {framework_m-0.6.9 → framework_m-0.7.0}/pyproject.toml +2 -2
  5. framework_m-0.6.9/examples/api_example.py +0 -73
  6. framework_m-0.6.9/examples/run_server.py +0 -136
  7. {framework_m-0.6.9 → framework_m-0.7.0}/LICENSE +0 -0
  8. {framework_m-0.6.9 → framework_m-0.7.0}/README.md +0 -0
  9. {framework_m-0.6.9 → framework_m-0.7.0}/alembic/README +0 -0
  10. {framework_m-0.6.9 → framework_m-0.7.0}/alembic/env.py +0 -0
  11. {framework_m-0.6.9 → framework_m-0.7.0}/alembic/script.py.mako +0 -0
  12. {framework_m-0.6.9 → framework_m-0.7.0}/alembic.ini +0 -0
  13. {framework_m-0.6.9 → framework_m-0.7.0}/docs/ports.md +0 -0
  14. {framework_m-0.6.9 → framework_m-0.7.0}/src/framework_m/__init__.py +0 -0
  15. {framework_m-0.6.9 → framework_m-0.7.0}/src/framework_m/cli/__init__.py +0 -0
  16. {framework_m-0.6.9 → framework_m-0.7.0}/src/framework_m/cli/main.py +0 -0
  17. {framework_m-0.6.9 → framework_m-0.7.0}/src/framework_m/py.typed +0 -0
  18. {framework_m-0.6.9 → framework_m-0.7.0}/tests/adapters/auth/test_oauth_adapter.py +0 -0
  19. {framework_m-0.6.9 → framework_m-0.7.0}/tests/adapters/read_model/test_projector.py +0 -0
  20. {framework_m-0.6.9 → framework_m-0.7.0}/tests/architecture/fixtures/ci_dummy_index.html +0 -0
  21. {framework_m-0.6.9 → framework_m-0.7.0}/tests/architecture/test_frontend_bootstrap.py +0 -0
  22. {framework_m-0.6.9 → framework_m-0.7.0}/tests/architecture/test_package_separation.py +0 -0
  23. {framework_m-0.6.9 → framework_m-0.7.0}/tests/conftest.py +0 -0
  24. {framework_m-0.6.9 → framework_m-0.7.0}/tests/core/interfaces/test_read_model.py +0 -0
  25. {framework_m-0.6.9 → framework_m-0.7.0}/tests/core/interfaces/test_report_engine.py +0 -0
  26. {framework_m-0.6.9 → framework_m-0.7.0}/tests/helpers/__init__.py +0 -0
  27. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/__init__.py +0 -0
  28. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_api_endpoints.py +0 -0
  29. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_app_ports.py +0 -0
  30. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_child_table_integration.py +0 -0
  31. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_crud_flow.py +0 -0
  32. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_jobs_events_webhooks.py +0 -0
  33. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_migration_flow.py +0 -0
  34. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_override_migration.py +0 -0
  35. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_postgres_flow.py +0 -0
  36. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_real_http_client.py +0 -0
  37. {framework_m-0.6.9 → framework_m-0.7.0}/tests/integration/test_workflow_lifecycle.py +0 -0
  38. {framework_m-0.6.9 → framework_m-0.7.0}/tests/test_meta.py +0 -0
@@ -114,15 +114,14 @@ yarn-error.log*
114
114
  *.sublime-workspace
115
115
 
116
116
  # Generated Documentation
117
- docs/developer/generated/
118
- docs/developer/generated-core/
119
- docs/user/generated/
117
+ docs/reference/generated/
118
+ docs/reference/generated-core/
120
119
  docs/machine/
121
- docs/adr/index.md
122
- docs/adr/_sidebar.json
123
- docs/rfcs/index.md
124
- docs/rfcs/_sidebar.json
125
- docs/rfcs/_category_.json
120
+ docs/architecture/09_architecture_decisions/index.md
121
+ docs/architecture/09_architecture_decisions/_sidebar.json
122
+ docs/governance/index.md
123
+ docs/governance/_sidebar.json
124
+ docs/governance/_category_.json
126
125
 
127
126
  # Website
128
127
  website/.docusaurus/
@@ -1,4 +1,14 @@
1
- **framework-m** v0.6.9: internal dependency bump due to **framework-m-standard** update## framework-m v0.6.8
1
+ ## framework-m v0.7.0
2
+
3
+ ### Features
4
+
5
+ - implement phase 14 (ca41d3a)
6
+
7
+ ### Bug Fixes
8
+
9
+ - update docs and build script (181f55b)
10
+
11
+ **framework-m** v0.6.10: internal dependency bump due to **framework-m-studio** update**framework-m** v0.6.9: internal dependency bump due to **framework-m-standard** update## framework-m v0.6.8
2
12
 
3
13
  ### Bug Fixes
4
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: framework-m
3
- Version: 0.6.9
3
+ Version: 0.7.0
4
4
  Summary: A modular, metadata-driven business application framework
5
5
  Project-URL: Homepage, https://gitlab.com/castlecraft/framework-m
6
6
  Project-URL: Documentation, https://gitlab.com/castlecraft/framework-m#readme
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Typing :: Typed
20
20
  Requires-Python: >=3.12
21
21
  Requires-Dist: framework-m-core>=0.11.4
22
- Requires-Dist: framework-m-standard>=0.7.0
22
+ Requires-Dist: framework-m-standard>=0.8.0
23
23
  Description-Content-Type: text/markdown
24
24
 
25
25
  # Framework M
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "framework-m"
3
- version = "0.6.9"
3
+ version = "0.7.0"
4
4
  description = "A modular, metadata-driven business application framework"
5
5
  readme = "README.md"
6
6
  license = { text = "Apache-2.0" }
@@ -22,7 +22,7 @@ classifiers = [
22
22
 
23
23
  dependencies = [
24
24
  "framework-m-core>=0.11.4",
25
- "framework-m-standard>=0.7.0",
25
+ "framework-m-standard>=0.8.0",
26
26
  ]
27
27
 
28
28
  [tool.uv.sources]
@@ -1,73 +0,0 @@
1
- """Test script to call the API with httpx.
2
-
3
- Usage:
4
- 1. First start the server:
5
- cd /Users/ansh/Desktop/CastleCraft/m/libs/framework-m
6
- uv run python scripts/run_server.py
7
-
8
- 2. Then in another terminal, run this script:
9
- cd /Users/ansh/Desktop/CastleCraft/m/libs/framework-m
10
- uv run python scripts/test_api.py
11
- """
12
-
13
- import asyncio
14
-
15
- import httpx
16
-
17
-
18
- async def test_api() -> None:
19
- """Test the API endpoints."""
20
- base_url = "http://localhost:8000"
21
-
22
- async with httpx.AsyncClient() as client:
23
- print("=" * 60)
24
- print("Testing Framework M API")
25
- print("=" * 60)
26
-
27
- # Test 1: List todos (should be empty)
28
- print("\n1. GET /api/v1/Todo (list)")
29
- response = await client.get(f"{base_url}/api/v1/Todo")
30
- print(f" Status: {response.status_code}")
31
- print(f" Response: {response.json()}")
32
-
33
- # Test 2: Create a todo (as Employee)
34
- print("\n2. POST /api/v1/Todo (create as Employee)")
35
- response = await client.post(
36
- f"{base_url}/api/v1/Todo",
37
- json={"title": "Test Todo"},
38
- headers={"x-user-id": "user123", "x-roles": "Employee"},
39
- )
40
- print(f" Status: {response.status_code}")
41
- if response.status_code < 500:
42
- print(f" Response: {response.json()}")
43
- else:
44
- print(f" Response: {response.text[:200]}")
45
-
46
- # Test 3: Create a todo without permission (as Guest)
47
- print("\n3. POST /api/v1/Todo (create as Guest - should fail)")
48
- response = await client.post(
49
- f"{base_url}/api/v1/Todo",
50
- json={"title": "Test Todo"},
51
- headers={"x-user-id": "guest", "x-roles": "Guest"},
52
- )
53
- print(f" Status: {response.status_code}")
54
- if response.status_code < 500:
55
- print(f" Response: {response.json()}")
56
-
57
- # Test 4: Get metadata
58
- print("\n4. GET /api/meta/Todo (metadata)")
59
- response = await client.get(f"{base_url}/api/meta/Todo")
60
- print(f" Status: {response.status_code}")
61
- data = response.json()
62
- print(f" DocType: {data.get('doctype')}")
63
- print(f" Has schema: {'schema' in data}")
64
- print(f" Has layout: {'layout' in data}")
65
- print(f" Has permissions: {'permissions' in data}")
66
-
67
- print("\n" + "=" * 60)
68
- print("API tests complete!")
69
- print("=" * 60)
70
-
71
-
72
- if __name__ == "__main__":
73
- asyncio.run(test_api())
@@ -1,136 +0,0 @@
1
- """Run the Framework M API server for manual testing.
2
-
3
- Usage:
4
- cd /Users/ansh/Desktop/CastleCraft/m/libs/framework-m
5
- uv run python scripts/run_server.py
6
-
7
- Then test with:
8
- curl http://localhost:8000/api/v1/Todo
9
- OR use the test_api.py script
10
- """
11
-
12
- from typing import Any, ClassVar
13
-
14
- import uvicorn
15
- from framework_m_standard.adapters.web.meta_router import create_meta_router
16
- from framework_m_standard.adapters.web.meta_routes import meta_routes_router
17
- from framework_m_standard.adapters.web.rpc_routes import rpc_router
18
- from litestar import Litestar, Response
19
- from litestar.status_codes import HTTP_403_FORBIDDEN
20
- from litestar.types import ASGIApp, Receive, Scope, Send
21
-
22
- from framework_m.core.domain.base_doctype import BaseDocType, Field
23
- from framework_m.core.exceptions import PermissionDeniedError
24
- from framework_m.core.interfaces.auth_context import UserContext
25
- from framework_m.core.registry import MetaRegistry
26
-
27
- # =============================================================================
28
- # Test DocType for Manual Testing
29
- # =============================================================================
30
-
31
-
32
- class Todo(BaseDocType):
33
- """Todo DocType for testing."""
34
-
35
- title: str = Field(title="Title", description="Todo title")
36
- completed: bool = Field(default=False)
37
-
38
- class Meta:
39
- api_resource: ClassVar[bool] = True
40
- requires_auth: ClassVar[bool] = False # Allow guest for easy testing
41
- apply_rls: ClassVar[bool] = False
42
- permissions: ClassVar[dict[str, list[str]]] = {
43
- "read": ["Guest", "Employee", "Manager", "Admin"],
44
- "write": ["Employee", "Manager", "Admin"],
45
- "create": ["Employee", "Manager", "Admin"],
46
- "delete": ["Admin"],
47
- }
48
-
49
-
50
- # =============================================================================
51
- # Auth Middleware
52
- # =============================================================================
53
-
54
-
55
- def create_auth_middleware(app: ASGIApp) -> ASGIApp:
56
- """Create middleware that parses x-user-id and x-roles headers."""
57
-
58
- async def middleware(scope: Scope, receive: Receive, send: Send) -> None:
59
- if scope["type"] in ("http", "websocket"):
60
- headers = dict(scope.get("headers", []))
61
- user_id = headers.get(b"x-user-id", b"anonymous").decode()
62
- roles_str = headers.get(b"x-roles", b"Guest").decode()
63
- roles = [r.strip() for r in roles_str.split(",")]
64
-
65
- # Set both the UserContext AND the individual attributes
66
- # The meta_router looks for user_id, user_roles, user_teams
67
- scope["state"]["user"] = UserContext(
68
- id=user_id,
69
- email=f"{user_id}@example.com",
70
- roles=roles,
71
- )
72
- scope["state"]["user_id"] = user_id
73
- scope["state"]["user_roles"] = roles
74
- scope["state"]["user_teams"] = []
75
- await app(scope, receive, send)
76
-
77
- return middleware
78
-
79
-
80
- def permission_denied_handler(
81
- request: Any, exc: PermissionDeniedError
82
- ) -> Response[dict[str, str]]:
83
- """Handle permission denied errors."""
84
- return Response(
85
- content={"error": "PermissionDenied", "message": str(exc)},
86
- status_code=HTTP_403_FORBIDDEN,
87
- )
88
-
89
-
90
- # =============================================================================
91
- # Server Setup
92
- # =============================================================================
93
-
94
-
95
- def create_test_app() -> Litestar:
96
- """Create the test application."""
97
- # Register DocType
98
- registry = MetaRegistry.get_instance()
99
- registry.clear()
100
- registry.register_doctype(Todo)
101
-
102
- # Create routers
103
- crud_router = create_meta_router()
104
-
105
- # Create app with middleware and exception handlers
106
- app = Litestar(
107
- route_handlers=[crud_router, rpc_router, meta_routes_router],
108
- middleware=[create_auth_middleware],
109
- exception_handlers={PermissionDeniedError: permission_denied_handler},
110
- debug=True,
111
- )
112
-
113
- return app
114
-
115
-
116
- if __name__ == "__main__":
117
- print("Starting Framework M API server...")
118
- print("Server running at: http://localhost:8000")
119
- print("")
120
- print("Available endpoints:")
121
- print(" GET /api/v1/Todo - List todos")
122
- print(" POST /api/v1/Todo - Create todo")
123
- print(" GET /api/v1/Todo/{id} - Get todo")
124
- print(" PUT /api/v1/Todo/{id} - Update todo")
125
- print(" DELETE /api/v1/Todo/{id} - Delete todo")
126
- print(" GET /api/meta/Todo - Get Todo metadata")
127
- print("")
128
- print("Authentication headers:")
129
- print(" x-user-id: user123")
130
- print(" x-roles: Employee,Manager")
131
- print("")
132
- print("Press Ctrl+C to stop the server")
133
- print("")
134
-
135
- app = create_test_app()
136
- uvicorn.run(app, host="0.0.0.0", port=8000) # nosec B104
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes