forgeui 0.1.0a2__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 (150) hide show
  1. forgeui-0.1.0a2/.dockerignore +15 -0
  2. forgeui-0.1.0a2/.env.example +28 -0
  3. forgeui-0.1.0a2/.github/workflows/ci.yml +81 -0
  4. forgeui-0.1.0a2/.github/workflows/publish.yml +82 -0
  5. forgeui-0.1.0a2/.gitignore +23 -0
  6. forgeui-0.1.0a2/.impeccable.md +56 -0
  7. forgeui-0.1.0a2/.python-version +1 -0
  8. forgeui-0.1.0a2/AGENTS.local.example.md +6 -0
  9. forgeui-0.1.0a2/AGENTS.md +14 -0
  10. forgeui-0.1.0a2/CHANGELOG.md +55 -0
  11. forgeui-0.1.0a2/CONTRIBUTING.md +27 -0
  12. forgeui-0.1.0a2/Dockerfile +45 -0
  13. forgeui-0.1.0a2/LICENSE +21 -0
  14. forgeui-0.1.0a2/PKG-INFO +277 -0
  15. forgeui-0.1.0a2/README.md +209 -0
  16. forgeui-0.1.0a2/SECURITY.md +27 -0
  17. forgeui-0.1.0a2/THIRD_PARTY_NOTICES.md +25 -0
  18. forgeui-0.1.0a2/compose.ollama.yaml +24 -0
  19. forgeui-0.1.0a2/compose.yaml +46 -0
  20. forgeui-0.1.0a2/docs/adr/0001-strict-manifest.md +13 -0
  21. forgeui-0.1.0a2/docs/adr/0002-server-owned-state.md +13 -0
  22. forgeui-0.1.0a2/docs/adr/0003-design-profiles.md +11 -0
  23. forgeui-0.1.0a2/docs/adr/0004-trusted-integrations.md +14 -0
  24. forgeui-0.1.0a2/docs/adr/0005-assets.md +12 -0
  25. forgeui-0.1.0a2/docs/adr/0006-bounded-repair.md +14 -0
  26. forgeui-0.1.0a2/docs/adr/0007-distribution-boundaries.md +19 -0
  27. forgeui-0.1.0a2/docs/adr/README.md +9 -0
  28. forgeui-0.1.0a2/docs/api.md +123 -0
  29. forgeui-0.1.0a2/docs/architecture.md +85 -0
  30. forgeui-0.1.0a2/docs/components.md +62 -0
  31. forgeui-0.1.0a2/docs/data-sources.md +119 -0
  32. forgeui-0.1.0a2/docs/deployment.md +105 -0
  33. forgeui-0.1.0a2/docs/distribution.md +162 -0
  34. forgeui-0.1.0a2/docs/embedding.md +131 -0
  35. forgeui-0.1.0a2/docs/footprint.md +63 -0
  36. forgeui-0.1.0a2/docs/implementation-plan.md +141 -0
  37. forgeui-0.1.0a2/docs/manifest.md +99 -0
  38. forgeui-0.1.0a2/docs/releases/0.1.0a1.md +37 -0
  39. forgeui-0.1.0a2/docs/releases/0.1.0a2.md +44 -0
  40. forgeui-0.1.0a2/docs/security.md +81 -0
  41. forgeui-0.1.0a2/docs/surfaces.md +106 -0
  42. forgeui-0.1.0a2/examples/ai_search_host.py +105 -0
  43. forgeui-0.1.0a2/examples/data/device-health-empty.json +18 -0
  44. forgeui-0.1.0a2/examples/data/device-health-stale.json +54 -0
  45. forgeui-0.1.0a2/examples/data/device-health.json +135 -0
  46. forgeui-0.1.0a2/examples/manifests/device-detail.json +232 -0
  47. forgeui-0.1.0a2/examples/manifests/fleet-overview.json +289 -0
  48. forgeui-0.1.0a2/examples/manifests/resource-pressure.json +175 -0
  49. forgeui-0.1.0a2/examples/prompts/device-detail.txt +3 -0
  50. forgeui-0.1.0a2/examples/prompts/fleet-overview.txt +3 -0
  51. forgeui-0.1.0a2/examples/prompts/resource-pressure.txt +3 -0
  52. forgeui-0.1.0a2/pyproject.toml +151 -0
  53. forgeui-0.1.0a2/src/forgeui/__init__.py +10 -0
  54. forgeui-0.1.0a2/src/forgeui/a2ui/README.md +68 -0
  55. forgeui-0.1.0a2/src/forgeui/a2ui/__init__.py +36 -0
  56. forgeui-0.1.0a2/src/forgeui/a2ui/adapter.py +486 -0
  57. forgeui-0.1.0a2/src/forgeui/a2ui/errors.py +54 -0
  58. forgeui-0.1.0a2/src/forgeui/a2ui/models.py +116 -0
  59. forgeui-0.1.0a2/src/forgeui/app.py +465 -0
  60. forgeui-0.1.0a2/src/forgeui/catalog/__init__.py +5 -0
  61. forgeui-0.1.0a2/src/forgeui/catalog/registry.py +552 -0
  62. forgeui-0.1.0a2/src/forgeui/cli.py +38 -0
  63. forgeui-0.1.0a2/src/forgeui/config.py +120 -0
  64. forgeui-0.1.0a2/src/forgeui/container.py +135 -0
  65. forgeui-0.1.0a2/src/forgeui/data/__init__.py +6 -0
  66. forgeui-0.1.0a2/src/forgeui/data/database.py +103 -0
  67. forgeui-0.1.0a2/src/forgeui/data/models.py +175 -0
  68. forgeui-0.1.0a2/src/forgeui/data/repositories.py +444 -0
  69. forgeui-0.1.0a2/src/forgeui/domain/__init__.py +23 -0
  70. forgeui-0.1.0a2/src/forgeui/domain/device_health.py +213 -0
  71. forgeui-0.1.0a2/src/forgeui/domain/models.py +217 -0
  72. forgeui-0.1.0a2/src/forgeui/expressions/__init__.py +14 -0
  73. forgeui-0.1.0a2/src/forgeui/expressions/ast.py +126 -0
  74. forgeui-0.1.0a2/src/forgeui/expressions/evaluator.py +231 -0
  75. forgeui-0.1.0a2/src/forgeui/icons.py +126 -0
  76. forgeui-0.1.0a2/src/forgeui/llm/__init__.py +51 -0
  77. forgeui-0.1.0a2/src/forgeui/llm/fake.py +31 -0
  78. forgeui-0.1.0a2/src/forgeui/llm/generation.py +218 -0
  79. forgeui-0.1.0a2/src/forgeui/llm/ollama.py +118 -0
  80. forgeui-0.1.0a2/src/forgeui/llm/prompting.py +113 -0
  81. forgeui-0.1.0a2/src/forgeui/llm/types.py +103 -0
  82. forgeui-0.1.0a2/src/forgeui/logging.py +42 -0
  83. forgeui-0.1.0a2/src/forgeui/observability.py +62 -0
  84. forgeui-0.1.0a2/src/forgeui/py.typed +1 -0
  85. forgeui-0.1.0a2/src/forgeui/renderer/__init__.py +12 -0
  86. forgeui-0.1.0a2/src/forgeui/renderer/renderer.py +839 -0
  87. forgeui-0.1.0a2/src/forgeui/runtime.py +114 -0
  88. forgeui-0.1.0a2/src/forgeui/security.py +57 -0
  89. forgeui-0.1.0a2/src/forgeui/services/__init__.py +40 -0
  90. forgeui-0.1.0a2/src/forgeui/services/actions.py +413 -0
  91. forgeui-0.1.0a2/src/forgeui/services/apps.py +207 -0
  92. forgeui-0.1.0a2/src/forgeui/services/audit.py +79 -0
  93. forgeui-0.1.0a2/src/forgeui/services/capabilities.py +159 -0
  94. forgeui-0.1.0a2/src/forgeui/services/devices.py +166 -0
  95. forgeui-0.1.0a2/src/forgeui/services/exceptions.py +27 -0
  96. forgeui-0.1.0a2/src/forgeui/services/jobs.py +170 -0
  97. forgeui-0.1.0a2/src/forgeui/services/state.py +131 -0
  98. forgeui-0.1.0a2/src/forgeui/sources/__init__.py +29 -0
  99. forgeui-0.1.0a2/src/forgeui/sources/http.py +122 -0
  100. forgeui-0.1.0a2/src/forgeui/sources/registry.py +358 -0
  101. forgeui-0.1.0a2/src/forgeui/surfaces.py +64 -0
  102. forgeui-0.1.0a2/src/forgeui/validation/__init__.py +30 -0
  103. forgeui-0.1.0a2/src/forgeui/validation/parser.py +82 -0
  104. forgeui-0.1.0a2/src/forgeui/validation/repair.py +68 -0
  105. forgeui-0.1.0a2/src/forgeui/validation/validator.py +653 -0
  106. forgeui-0.1.0a2/src/forgeui/web/__init__.py +5 -0
  107. forgeui-0.1.0a2/src/forgeui/web/router.py +1083 -0
  108. forgeui-0.1.0a2/src/forgeui/web/static/favicon.svg +4 -0
  109. forgeui-0.1.0a2/src/forgeui/web/static/forgeui-embed.js +38 -0
  110. forgeui-0.1.0a2/src/forgeui/web/static/forgeui.css +1780 -0
  111. forgeui-0.1.0a2/src/forgeui/web/static/forgeui.js +300 -0
  112. forgeui-0.1.0a2/src/forgeui/web/templates/base.html +53 -0
  113. forgeui-0.1.0a2/src/forgeui/web/templates/components/_component.html +88 -0
  114. forgeui-0.1.0a2/tests/contracts/a2ui/fixtures/device_health_dashboard_v0_9_1.jsonl +3 -0
  115. forgeui-0.1.0a2/tests/contracts/a2ui/test_adapter_v0_9_1.py +430 -0
  116. forgeui-0.1.0a2/tests/contracts/test_catalog_templates.py +142 -0
  117. forgeui-0.1.0a2/tests/contracts/test_distribution.py +46 -0
  118. forgeui-0.1.0a2/tests/contracts/test_examples.py +23 -0
  119. forgeui-0.1.0a2/tests/contracts/test_footprint.py +57 -0
  120. forgeui-0.1.0a2/tests/integration/test_custom_runtime.py +202 -0
  121. forgeui-0.1.0a2/tests/integration/test_web.py +703 -0
  122. forgeui-0.1.0a2/tests/llm_gauntlet/test_live_ollama.py +29 -0
  123. forgeui-0.1.0a2/tests/security/test_renderer_security.py +41 -0
  124. forgeui-0.1.0a2/tests/security/test_web_security.py +24 -0
  125. forgeui-0.1.0a2/tests/unit/catalog/__init__.py +1 -0
  126. forgeui-0.1.0a2/tests/unit/catalog/test_registry.py +82 -0
  127. forgeui-0.1.0a2/tests/unit/data/test_repository.py +70 -0
  128. forgeui-0.1.0a2/tests/unit/domain/test_device_health.py +60 -0
  129. forgeui-0.1.0a2/tests/unit/expressions/test_evaluator.py +112 -0
  130. forgeui-0.1.0a2/tests/unit/expressions/test_evaluator_matrix.py +168 -0
  131. forgeui-0.1.0a2/tests/unit/llm/test_generation.py +121 -0
  132. forgeui-0.1.0a2/tests/unit/llm/test_ollama.py +125 -0
  133. forgeui-0.1.0a2/tests/unit/llm/test_prompting.py +48 -0
  134. forgeui-0.1.0a2/tests/unit/renderer/test_renderer.py +471 -0
  135. forgeui-0.1.0a2/tests/unit/services/conftest.py +65 -0
  136. forgeui-0.1.0a2/tests/unit/services/test_apps_state_actions.py +103 -0
  137. forgeui-0.1.0a2/tests/unit/services/test_capabilities.py +89 -0
  138. forgeui-0.1.0a2/tests/unit/services/test_jobs_devices.py +127 -0
  139. forgeui-0.1.0a2/tests/unit/sources/__init__.py +1 -0
  140. forgeui-0.1.0a2/tests/unit/sources/test_http.py +74 -0
  141. forgeui-0.1.0a2/tests/unit/sources/test_registry.py +150 -0
  142. forgeui-0.1.0a2/tests/unit/test_cli.py +16 -0
  143. forgeui-0.1.0a2/tests/unit/test_config.py +57 -0
  144. forgeui-0.1.0a2/tests/unit/test_icons.py +40 -0
  145. forgeui-0.1.0a2/tests/unit/test_logging.py +27 -0
  146. forgeui-0.1.0a2/tests/unit/test_security.py +24 -0
  147. forgeui-0.1.0a2/tests/unit/validation/test_manifest_validation.py +264 -0
  148. forgeui-0.1.0a2/tests/unit/validation/test_parser.py +17 -0
  149. forgeui-0.1.0a2/tests/unit/validation/test_repair.py +135 -0
  150. forgeui-0.1.0a2/uv.lock +1782 -0
@@ -0,0 +1,15 @@
1
+ .git
2
+ .github
3
+ .pytest_cache
4
+ .mypy_cache
5
+ .ruff_cache
6
+ .venv
7
+ __pycache__
8
+ *.py[cod]
9
+ *.db
10
+ *.sqlite*
11
+ .env
12
+ /data
13
+ tests
14
+ docs
15
+ examples
@@ -0,0 +1,28 @@
1
+ FORGEUI_ENVIRONMENT=development
2
+ FORGEUI_HOST=0.0.0.0
3
+ FORGEUI_PORT=8000
4
+ FORGEUI_DATABASE_URL=sqlite:////data/forgeui.db
5
+ FORGEUI_DATA_DIR=/data
6
+ # Generate unique production values, for example: openssl rand -hex 32
7
+ FORGEUI_SECRET_KEY=replace-with-a-long-random-value
8
+ FORGEUI_ADMIN_TOKEN=replace-with-an-admin-token
9
+ FORGEUI_ALLOW_PUBLIC_READ=true
10
+ # Set true behind HTTPS. Compose defaults this to true.
11
+ FORGEUI_SECURE_COOKIES=false
12
+ # JSON list, not a comma-separated string.
13
+ FORGEUI_TRUSTED_HOSTS=["localhost","127.0.0.1"]
14
+ # Exact origins permitted to frame /embed and /artifact views. Keep self-only unless needed.
15
+ FORGEUI_FRAME_ANCESTORS=["'self'"]
16
+
17
+ # Ollama is expected to run separately. On Docker Desktop this reaches the host.
18
+ FORGEUI_OLLAMA_BASE_URL=http://host.docker.internal:11434
19
+ FORGEUI_OLLAMA_MODEL=qwen3.5:9b
20
+ FORGEUI_OLLAMA_CONNECT_TIMEOUT_SECONDS=5
21
+ FORGEUI_OLLAMA_RESPONSE_TIMEOUT_SECONDS=90
22
+ FORGEUI_OLLAMA_MAX_CONCURRENCY=1
23
+ FORGEUI_OLLAMA_TEMPERATURE=0.1
24
+ FORGEUI_OLLAMA_SEED=42
25
+
26
+ FORGEUI_ASSET_MODE=self-hosted
27
+ FORGEUI_LOG_LEVEL=INFO
28
+ FORGEUI_JSON_LOGS=false
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ quality:
12
+ runs-on: ubuntu-latest
13
+ timeout-minutes: 15
14
+ steps:
15
+ - uses: actions/checkout@v7.0.1
16
+ - uses: astral-sh/setup-uv@v10.0.1
17
+ with:
18
+ python-version: "3.12"
19
+ enable-cache: true
20
+ - run: uv sync --frozen --all-extras
21
+ - run: uv run ruff format --check .
22
+ - run: uv run ruff check .
23
+ - run: uv run mypy src/forgeui
24
+ - run: uv run bandit -q -r src/forgeui
25
+ - run: >-
26
+ uv run pytest -q -m "not browser and not docker and not ollama"
27
+ --cov=forgeui --cov-report=term-missing:skip-covered
28
+ - run: uv build
29
+ - run: uv run twine check dist/*
30
+ - name: Smoke-test base, HTTP adapter, mounted-web, and complete wheels
31
+ run: |
32
+ WHEEL=$(find dist -name 'forgeui-*.whl' -print -quit)
33
+ WHEEL_BYTES=$(wc -c < "$WHEEL")
34
+ if [ "$WHEEL_BYTES" -gt $((128 * 1024)) ]; then
35
+ echo "Wheel size $WHEEL_BYTES bytes exceeds the 128 KiB budget"
36
+ exit 1
37
+ fi
38
+ PACKAGE_SMOKE_DIR=$(mktemp -d)
39
+ uv venv "$PACKAGE_SMOKE_DIR/base"
40
+ uv pip install --python "$PACKAGE_SMOKE_DIR/base/bin/python" "$WHEEL"
41
+ "$PACKAGE_SMOKE_DIR/base/bin/python" -c \
42
+ "import importlib.util; from forgeui.a2ui import adapt_a2ui_jsonl; from forgeui.renderer import Renderer; from forgeui.validation import validate_manifest; assert importlib.util.find_spec('fastapi') is None; assert importlib.util.find_spec('httpx') is None; assert importlib.util.find_spec('sqlalchemy') is None"
43
+ if BASE_CLI_OUTPUT=$("$PACKAGE_SMOKE_DIR/base/bin/forgeui" serve 2>&1); then
44
+ echo "Base CLI unexpectedly started without the app extra"
45
+ exit 1
46
+ fi
47
+ if ! grep -q "forgeui\[app\]" <<< "$BASE_CLI_OUTPUT"; then
48
+ echo "Base CLI did not explain the missing app extra"
49
+ exit 1
50
+ fi
51
+ uv venv "$PACKAGE_SMOKE_DIR/http"
52
+ uv pip install --python "$PACKAGE_SMOKE_DIR/http/bin/python" "${WHEEL}[http]"
53
+ "$PACKAGE_SMOKE_DIR/http/bin/python" -c \
54
+ "import importlib.util; from forgeui.sources.http import HttpDataSource; assert importlib.util.find_spec('sqlalchemy') is None"
55
+ uv venv "$PACKAGE_SMOKE_DIR/web"
56
+ uv pip install --python "$PACKAGE_SMOKE_DIR/web/bin/python" "${WHEEL}[web]"
57
+ "$PACKAGE_SMOKE_DIR/web/bin/python" -c \
58
+ "import importlib.util; from forgeui.app import mount_forgeui; from forgeui.data import Database; assert importlib.util.find_spec('httpx') is None"
59
+ uv venv "$PACKAGE_SMOKE_DIR/app"
60
+ uv pip install --python "$PACKAGE_SMOKE_DIR/app/bin/python" "${WHEEL}[app]"
61
+ "$PACKAGE_SMOKE_DIR/app/bin/python" -c \
62
+ "from forgeui.app import create_app; from forgeui.data import Database; from forgeui.llm import OllamaProvider"
63
+
64
+ compatibility:
65
+ name: Python ${{ matrix.python-version }} compatibility
66
+ runs-on: ubuntu-latest
67
+ timeout-minutes: 15
68
+ strategy:
69
+ fail-fast: false
70
+ matrix:
71
+ python-version: ["3.11", "3.13"]
72
+ steps:
73
+ - uses: actions/checkout@v7.0.1
74
+ with:
75
+ persist-credentials: false
76
+ - uses: astral-sh/setup-uv@v10.0.1
77
+ with:
78
+ python-version: ${{ matrix.python-version }}
79
+ enable-cache: true
80
+ - run: uv sync --frozen --all-extras
81
+ - run: uv run pytest -q -m "not browser and not docker and not ollama"
@@ -0,0 +1,82 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ name: Build and verify distribution
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 15
15
+ steps:
16
+ - uses: actions/checkout@v7.0.1
17
+ with:
18
+ persist-credentials: false
19
+ - uses: astral-sh/setup-uv@v10.0.1
20
+ with:
21
+ python-version: "3.12"
22
+ enable-cache: true
23
+ - name: Check release tag matches package version
24
+ run: |
25
+ PACKAGE_VERSION=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
26
+ RELEASE_VERSION=${GITHUB_REF_NAME#v}
27
+ if [ "$PACKAGE_VERSION" != "$RELEASE_VERSION" ]; then
28
+ echo "Release tag $GITHUB_REF_NAME does not match package version $PACKAGE_VERSION"
29
+ exit 1
30
+ fi
31
+ - run: uv sync --frozen --all-extras
32
+ - run: uv run ruff format --check .
33
+ - run: uv run ruff check .
34
+ - run: uv run mypy src/forgeui
35
+ - run: uv run bandit -q -r src/forgeui
36
+ - run: >-
37
+ uv run pytest -q -m "not browser and not docker and not ollama"
38
+ --cov=forgeui --cov-report=term-missing:skip-covered
39
+ - run: uv build
40
+ - run: uv run twine check dist/*
41
+ - name: Enforce wheel budget
42
+ run: |
43
+ WHEEL=$(find dist -name 'forgeui-*.whl' -print -quit)
44
+ WHEEL_BYTES=$(wc -c < "$WHEEL")
45
+ if [ "$WHEEL_BYTES" -gt $((128 * 1024)) ]; then
46
+ echo "Wheel size $WHEEL_BYTES bytes exceeds the 128 KiB budget"
47
+ exit 1
48
+ fi
49
+ - name: Smoke-test the exact release wheel
50
+ run: |
51
+ WHEEL=$(find dist -name 'forgeui-*.whl' -print -quit)
52
+ RELEASE_SMOKE_DIR=$(mktemp -d)
53
+ uv venv "$RELEASE_SMOKE_DIR/venv"
54
+ uv pip install --python "$RELEASE_SMOKE_DIR/venv/bin/python" "${WHEEL}[app]"
55
+ "$RELEASE_SMOKE_DIR/venv/bin/python" -c \
56
+ "from forgeui import __version__; from forgeui.app import create_app; assert __version__ == '${GITHUB_REF_NAME#v}'"
57
+ - name: Store distributions
58
+ uses: actions/upload-artifact@v7.0.1
59
+ with:
60
+ name: python-package-distributions
61
+ path: dist/
62
+ if-no-files-found: error
63
+ retention-days: 7
64
+
65
+ publish:
66
+ name: Publish verified distribution
67
+ needs: build
68
+ runs-on: ubuntu-latest
69
+ timeout-minutes: 10
70
+ environment:
71
+ name: pypi
72
+ url: https://pypi.org/p/forgeui
73
+ permissions:
74
+ id-token: write
75
+ steps:
76
+ - name: Retrieve distributions
77
+ uses: actions/download-artifact@v8.0.1
78
+ with:
79
+ name: python-package-distributions
80
+ path: dist/
81
+ - name: Publish with PyPI Trusted Publishing
82
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,23 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .coverage
5
+ .env
6
+ .hypothesis/
7
+ .mypy_cache/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .venv/
11
+ build/
12
+ dist/
13
+ htmlcov/
14
+ playwright-report/
15
+ test-results/
16
+ /data/
17
+ *.db
18
+ *.db-shm
19
+ *.db-wal
20
+ .DS_Store
21
+
22
+ # Machine-specific agent instructions may contain local paths or other private context.
23
+ AGENTS.local.md
@@ -0,0 +1,56 @@
1
+ ## Design Context
2
+
3
+ ### Users
4
+
5
+ ForgeUI serves two connected groups:
6
+
7
+ - Operations engineers, fleet administrators, and support staff who scan device health, identify
8
+ exceptions, and act under time pressure. They need dense information to remain legible and
9
+ trustworthy at a glance.
10
+ - Application developers who embed ForgeUI into a FastAPI service and use a small local model to
11
+ assemble dashboards from an approved catalog. They need the generated UI to feel intentional
12
+ without granting the model arbitrary styling or executable output.
13
+
14
+ The first job is to turn a normalized device-health report into a useful fleet overview, resource
15
+ pressure view, or device detail page. Existing dashboards must remain useful when Ollama is
16
+ offline.
17
+
18
+ ### Brand Personality
19
+
20
+ Calm, dependable, precise. The interface should create confidence through restraint, clear status
21
+ hierarchy, exact labels, and visible system state. Urgency comes from actual warning and critical
22
+ data, not decorative intensity. Copy is concise, direct, and helpful.
23
+
24
+ ### Aesthetic Direction
25
+
26
+ The default visual language is a compact system-font interface with deep teal actions,
27
+ cool-neutral page and card surfaces, 6-pixel control/card radii, restrained
28
+ elevation, strong table structure, and a charcoal application bar with a teal rule. It should feel
29
+ like a dependable operational tool, not an editorial showcase or a generic marketing dashboard.
30
+
31
+ Support light, dark, and system themes as first-class modes. Dark mode uses distinct lifted
32
+ surfaces instead of inverting the light palette. Use the system stack
33
+ (`system-ui`, `-apple-system`, `Segoe UI`, `Roboto`) for predictable embedding. Avoid
34
+ neon-on-dark styling, cyan/purple gradients, glassmorphism, excessive rounding and shadows,
35
+ nested cards, ornamental sparklines, gradient text, oversized display headings, and large icon
36
+ tiles.
37
+
38
+ The four safe model-selectable design profiles may vary density and composition, but all inherit
39
+ the same semantic tokens, accessible status language, typography discipline, and trusted shell:
40
+
41
+ - `ops-compact`: dense, ruled, exception-first monitoring.
42
+ - `signal-cards`: stronger visual metric and chart emphasis without decorative effects.
43
+ - `executive-summary`: spacious synthesis with fewer simultaneous details.
44
+ - `calm-neutral`: quiet reading and detail review.
45
+
46
+ ### Design Principles
47
+
48
+ 1. Signal before decoration. Color, weight, and motion explain state changes or urgency.
49
+ 2. Dense does not mean cramped. Use varied rhythm, hairline separators, and tabular alignment to
50
+ make operational data scannable.
51
+ 3. The shell is trusted. Theme controls, focus behavior, error states, and interaction patterns do
52
+ not depend on model output.
53
+ 4. Profiles are complete systems, not bags of knobs. The model chooses a tested bundle and cannot
54
+ mix arbitrary colors, classes, fonts, radii, or layout values.
55
+ 5. Accessibility is visible quality. Preserve semantic HTML, 44-pixel touch targets, keyboard
56
+ focus, non-color status cues, reduced motion, AA contrast, and mobile adaptations.
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,6 @@
1
+ # ForgeUI local agent rules
2
+
3
+ Copy this file to `AGENTS.local.md` and add only machine-specific instructions that should not be
4
+ published, such as absolute paths to adjacent checkouts. `AGENTS.local.md` is ignored by Git.
5
+
6
+ - Treat `<absolute-path-to-adjacent-checkout>` as read-only; it may contain user changes.
@@ -0,0 +1,14 @@
1
+ # ForgeUI agent rules
2
+
3
+ - If `AGENTS.local.md` exists, read it before starting work. It contains machine-specific rules and
4
+ must remain untracked.
5
+ - ForgeUI is a standalone Python project.
6
+ - Keep the model boundary strict: manifests never contain HTML, JavaScript, CSS, Tailwind classes, URLs, SQL, file paths, or arbitrary executable expressions.
7
+ - Keep the component catalog, Pydantic models, JSON Schema, renderer dispatch, and prompt documentation in sync.
8
+ - Reject invalid manifests before persistence or rendering. Do not silently weaken security rules while repairing output.
9
+ - Prefer server-owned state, immutable manifest revisions, and trusted capability/data-source registries.
10
+ - Keep UI behavior accessible: semantic HTML, visible focus, labelled inputs, keyboard support, reduced motion, and tested light/dark themes.
11
+ - Treat adjacent checkouts as read-only; they may contain user changes.
12
+ - Agents working concurrently must have disjoint file ownership.
13
+ - Run focused tests for changed code and report exact commands and failures.
14
+ - Avoid vague production-readiness claims. State implemented controls, checks, and remaining risks precisely.
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ All notable changes to ForgeUI are documented here. Versions follow
4
+ [PEP 440](https://peps.python.org/pep-0440/).
5
+
6
+ ## 0.1.0a2 — 2026-09-01
7
+
8
+ First published public alpha.
9
+
10
+ ### Fixed
11
+
12
+ - Raised light-theme timeline timestamp contrast above the WCAG AA text threshold.
13
+ - Made the shell wordmark a 44-pixel touch target at mobile widths.
14
+ - Added a small self-hosted favicon so standalone pages do not generate a missing-asset request.
15
+ - Replaced the segmented theme selector with one compact system-default light/dark toggle.
16
+ - Added trusted axis titles, tick labels, scales, and formatted summaries to operational charts.
17
+ - Added hover/focus chart inspection with bounded keyboard stops and an accessible data summary.
18
+ - Added explicit dashboard drill-down affordances and host-allowlisted navigation destination IDs.
19
+
20
+ ## 0.1.0a1 — 2026-09-01
21
+
22
+ Initial release candidate.
23
+
24
+ ### Added
25
+
26
+ - Strict `forgeui/1` manifests with a server-owned catalog, Pydantic models, JSON Schema,
27
+ semantic validation, graph limits, and a pure bounded expression AST.
28
+ - Safe server rendering through Jinja2 with 46 catalog components, four complete design profiles,
29
+ accessible light/dark/system themes, and trusted SVG charts.
30
+ - Stateful and stateless dashboard, standalone, desktop, mobile, embedded-card, and chat-artifact
31
+ surfaces using FastAPI and HTMX.
32
+ - Immutable SQLite manifest revisions, server-owned state, optimistic concurrency, audit events,
33
+ device snapshots, and bounded in-process generation jobs.
34
+ - Qwen/Ollama structured generation with strict parsing, dry rendering, duplicate detection, and
35
+ at most two repair attempts after the initial candidate.
36
+ - Frozen data-contract, data-source, and capability registries for explicit host integrations.
37
+ - A bounded Google A2UI v0.9.1 JSONL importer.
38
+ - Three device-health example manifests, an AI-search host example, Docker/Compose support, and
39
+ package extras for base, web, HTTP sources, Ollama, serving, and the complete app.
40
+ - Secretless PyPI Trusted Publishing workflow with release-version and wheel-size gates.
41
+
42
+ ### Security boundaries
43
+
44
+ - Manifests cannot contain HTML, Jinja, JavaScript, CSS, Tailwind classes, URLs, SQL, file paths,
45
+ SVG paths, callbacks, or arbitrary executable expressions.
46
+ - Invalid generated candidates are rejected before persistence and rendering.
47
+ - Host code owns credentials, endpoints, authorization, data access, and side-effect handlers.
48
+
49
+ ### Known alpha limitations
50
+
51
+ - SQLite persistence and the in-process job worker support one ForgeUI process/replica per database.
52
+ - The live Ollama gauntlet requires an explicitly configured Ollama service and is not part of the
53
+ ordinary offline test suite.
54
+ - Google A2UI support is an allowlisted v0.9.1 snapshot importer, not a general A2UI client.
55
+ - APIs and the `forgeui/1` contract may change incompatibly before the first stable release.
@@ -0,0 +1,27 @@
1
+ # Contributing
2
+
3
+ ForgeUI keeps its manifest and rendering boundary deliberately narrow. Before proposing a change,
4
+ read [the architecture](docs/architecture.md), [manifest contract](docs/manifest.md), and
5
+ [security boundaries](docs/security.md).
6
+
7
+ ## Development
8
+
9
+ ```bash
10
+ uv sync --frozen --all-extras
11
+ uv run ruff format --check .
12
+ uv run ruff check .
13
+ uv run mypy src/forgeui
14
+ uv run pytest -q --cov=forgeui --cov-fail-under=85
15
+ uv build
16
+ uv run twine check dist/*
17
+ ```
18
+
19
+ Changes to a component must keep its catalog entry, strict Pydantic props, generated schema and
20
+ prompt documentation, renderer template, examples, and tests synchronized. New model-controlled
21
+ HTML, CSS, classes, URLs, paths, executable expressions, or generic transport capabilities are not
22
+ accepted.
23
+
24
+ Use focused tests while developing and run the full suite before opening a pull request. Live
25
+ Ollama, browser, and Docker checks have explicit markers because they require external runtimes.
26
+
27
+ Report security issues privately as described in [SECURITY.md](SECURITY.md).
@@ -0,0 +1,45 @@
1
+ # syntax=docker/dockerfile:1
2
+ # Build a small, reproducible runtime image from the committed uv lockfile.
3
+ FROM ghcr.io/astral-sh/uv:0.12.8 AS uv
4
+
5
+ FROM python:3.12-slim AS builder
6
+
7
+ COPY --from=uv /uv /uvx /bin/
8
+ WORKDIR /build
9
+ ENV UV_COMPILE_BYTECODE=1 \
10
+ UV_LINK_MODE=copy \
11
+ UV_NO_CACHE=1
12
+
13
+ COPY pyproject.toml uv.lock README.md LICENSE THIRD_PARTY_NOTICES.md ./
14
+ RUN uv sync --frozen --no-dev --extra app --no-install-project
15
+
16
+ COPY src ./src
17
+ RUN uv sync --frozen --no-dev --extra app
18
+
19
+ FROM python:3.12-slim AS runtime
20
+
21
+ ENV PYTHONDONTWRITEBYTECODE=1 \
22
+ PYTHONUNBUFFERED=1 \
23
+ PYTHONPATH=/app/src \
24
+ VIRTUAL_ENV=/opt/venv \
25
+ PATH=/opt/venv/bin:$PATH \
26
+ FORGEUI_DATA_DIR=/data \
27
+ FORGEUI_DATABASE_URL=sqlite:////data/forgeui.db
28
+
29
+ RUN addgroup --system --gid 10001 forgeui \
30
+ && adduser --system --uid 10001 --ingroup forgeui --home /nonexistent forgeui \
31
+ && mkdir -p /app /data \
32
+ && chown -R forgeui:forgeui /app /data
33
+
34
+ WORKDIR /app
35
+ COPY --from=builder --chown=forgeui:forgeui /build/.venv /opt/venv
36
+ COPY --from=builder --chown=forgeui:forgeui /build/src /app/src
37
+
38
+ USER forgeui
39
+ EXPOSE 8000
40
+
41
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
42
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/api/health/ready', timeout=3)"
43
+
44
+ # The SQLite-backed in-process job worker requires one Uvicorn worker.
45
+ CMD ["uvicorn", "forgeui.app:create_app", "--factory", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ForgeUI contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.