toolframe-core 0.6.4__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.
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/publish.yml +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/CHANGELOG.md +8 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/Cargo.lock +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/Cargo.toml +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/PKG-INFO +6 -6
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/README.md +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/architecture.md +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/authentication.md +10 -10
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/mcp-authentication.md +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/object-storage.md +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/offline-maintenance.md +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/postgresql-state.md +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/releasing.md +4 -4
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/sql-storage.md +10 -10
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/testing.md +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/pyproject.toml +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/check-postgres.py +1 -1
- toolframe_core-0.7.0/scripts/ci/dependencies.json +14 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/validate.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/dev-wheelhouse.sh +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-dependencies.py +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-release.py +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-scaffold.py +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/main.rs +8 -8
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/__init__.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/SKILL.md +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/pyproject.toml +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/plugin.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/service.py +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/operations.md +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/plugin-api.md +4 -4
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/cli.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/graph.py +6 -6
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/host.py +13 -13
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/maintenance.py +7 -7
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/stores.py +3 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/templates.json +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_acceptance.py +6 -8
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_architecture.py +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_auth.py +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_diagnostics.py +13 -19
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_foundations.py +2 -2
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_host.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_maintenance.py +18 -18
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_mixed_storage.py +13 -13
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_scaffold.py +1 -1
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_skills.py +6 -3
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_storage_bindings.py +15 -15
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/uv.lock +2 -2
- toolframe_core-0.6.4/scripts/ci/dependencies.json +0 -14
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.dockerignore +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/actions/scan-container/action.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/dependabot.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/ci.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/container-security.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/container.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/launcher.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/pr-policy.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/quality.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.github/workflows/validate.yml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.gitignore +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/.pre-commit-config.yaml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/CONTRIBUTING.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/Dockerfile +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/LICENSE +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/NOTICE +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/cchk.toml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/companion-wheels.txt +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0001-explicit-dashboard-access-mode.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0002-scoped-passwords-and-public-business-entrances.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0003-public-fallback-on-auth-error-or-disablement.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0004-separate-auth-ownership-from-dashboard-presentation.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0005-password-only-login-and-secret-reuse.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0006-require-explicit-plugin-authorization-contracts.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0007-independent-mcp-bearer-authentication.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0008-shared-oidc-authentication.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0009-replaceable-core-journal.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0010-multiple-sql-providers.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0011-safe-new-application-access.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0012-optional-runtime-tracing.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/adr/0013-context-logging.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/artifacts.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/ci.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/container.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/dependency-graph.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/glossary.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/intel-companion.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/oidc-authentication.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/runtime.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/docs/tracing.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/packaging/launcher/NOTICE +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/packaging/launcher/README.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/packaging/launcher/pyproject.toml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/build-launcher.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/build-release.sh +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/check-container-security.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/check_branch_name.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/artifacts.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/check-launcher-wheel.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/check-release.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/intel-companion.json +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/intel_companion.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/ci/prepare-launcher.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/container-healthcheck.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/harden-container.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/prepare-container.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-auth-upgrade.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-auth.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-container.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-network.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-operation-history.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-retained-plugins.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/scripts/verify-skill.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/companions.rs +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/_state_postgres.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/_state_sqlite.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/access.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/api.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/LICENSE +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/agents/openai.yaml +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/LICENSE +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/__init__.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/docs/usage.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/migrations/0001_init.sql +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/page.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/evals/cases.json +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/design.md +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/config.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/diagnostics.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/mcp_access.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/network.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/oidc_access.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/packages.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/process.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/redaction.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/scaffold.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/skills.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/state.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/state_admin.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/toolframe_core/templates.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/src/uv.rs +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_access_policy.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_bundles.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_ci_artifacts.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_cli.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_container_release.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_container_security.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_core_state.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_intel_companion.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_managed_tasks.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_mcp_auth.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_network.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_object_store.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_oidc.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_operation_history.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_process.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_redaction.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_retained_plugins.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/tests/test_tracing.py +0 -0
- {toolframe_core-0.6.4 → toolframe_core-0.7.0}/uv-release-manifest.txt +0 -0
|
@@ -86,7 +86,7 @@ jobs:
|
|
|
86
86
|
repository-url: ${{ inputs.index == 'testpypi' && 'https://test.pypi.org/legacy/' || 'https://upload.pypi.org/legacy/' }}
|
|
87
87
|
|
|
88
88
|
publish-launcher:
|
|
89
|
-
needs: [release-tag, validate]
|
|
89
|
+
needs: [release-tag, validate, publish-core]
|
|
90
90
|
runs-on: ubuntu-24.04
|
|
91
91
|
timeout-minutes: 10
|
|
92
92
|
environment:
|
|
@@ -5,6 +5,14 @@ imply that its distributions have been published or every target is qualified.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.7.0
|
|
9
|
+
|
|
10
|
+
- Rename the SQL providers to `toolframe-sql-sqlite` and `toolframe-sql-postgres`,
|
|
11
|
+
with plugin IDs `sql-sqlite` and `sql-postgres`.
|
|
12
|
+
- Adopt SDK 0.4's `RuntimeContext.sql()`, `SqlClient`, and `toolframe.sql` service
|
|
13
|
+
contract throughout Core, templates, and plugin documentation. Install the
|
|
14
|
+
matching SDK 0.4-compatible plugin releases together.
|
|
15
|
+
|
|
8
16
|
## 0.6.4
|
|
9
17
|
|
|
10
18
|
- Refresh the container runtime packages to include Debian
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: toolframe-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Persistent control host for isolated Toolframe plugins
|
|
5
5
|
Project-URL: Homepage, https://github.com/toolframe/toolframe-core
|
|
6
6
|
Project-URL: Repository, https://github.com/toolframe/toolframe-core
|
|
@@ -19,14 +19,14 @@ Requires-Dist: httpx<1,>=0.28
|
|
|
19
19
|
Requires-Dist: packaging>=25
|
|
20
20
|
Requires-Dist: pyyaml<7,>=6
|
|
21
21
|
Requires-Dist: tomlkit<1,>=0.13
|
|
22
|
-
Requires-Dist: toolframe-sdk==0.
|
|
22
|
+
Requires-Dist: toolframe-sdk==0.4.0
|
|
23
23
|
Requires-Dist: uvicorn==0.42.0
|
|
24
24
|
Requires-Dist: watchfiles<2,>=1
|
|
25
25
|
Requires-Dist: websockets<17,>=15
|
|
26
26
|
Provides-Extra: postgres
|
|
27
27
|
Requires-Dist: psycopg[binary]<4,>=3.3; extra == 'postgres'
|
|
28
28
|
Provides-Extra: tracing
|
|
29
|
-
Requires-Dist: toolframe-sdk[tracing]==0.
|
|
29
|
+
Requires-Dist: toolframe-sdk[tracing]==0.4.0; extra == 'tracing'
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
|
|
32
32
|
# Toolframe core
|
|
@@ -38,7 +38,7 @@ Description-Content-Type: text/markdown
|
|
|
38
38
|
Toolframe is a persistent local control host for replaceable Python plugins.
|
|
39
39
|
Core owns composition, immutable package environments, worker lifecycles,
|
|
40
40
|
management operations and a durable Core journal. SQLite (`data/core.sqlite`) is
|
|
41
|
-
the default; Core 0.
|
|
41
|
+
the default; Core 0.7 also supports a dedicated PostgreSQL database through runtime
|
|
42
42
|
environment configuration. Dashboard, MCP, llms.txt, business
|
|
43
43
|
storage and Entry Register are independently packaged plugins.
|
|
44
44
|
|
|
@@ -397,8 +397,8 @@ the exit code.
|
|
|
397
397
|
| --- | --- |
|
|
398
398
|
| `toolframe-core` | Persistent FastAPI/Cordis control host, gateway and thin Rust launcher. |
|
|
399
399
|
| `toolframe-sdk` | Public definitions, worker protocol, services, resources and scoped clients. |
|
|
400
|
-
| `toolframe-
|
|
401
|
-
| `toolframe-
|
|
400
|
+
| `toolframe-sql-sqlite` | Local owner databases, SQL authorization, transactions, receipts and migrations. |
|
|
401
|
+
| `toolframe-sql-postgres` | External plugin stores, provisioning, restricted roles, migrations and database backups. |
|
|
402
402
|
| `toolframe-streamlit-dashboard` | Native Streamlit pages, shared navigation and management UI. |
|
|
403
403
|
| `toolframe-fastmcp` | MCP tools and Streamable HTTP transport. |
|
|
404
404
|
| `toolframe-llms-txt` | Index composition and explicitly packaged Markdown assets. |
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Toolframe is a persistent local control host for replaceable Python plugins.
|
|
8
8
|
Core owns composition, immutable package environments, worker lifecycles,
|
|
9
9
|
management operations and a durable Core journal. SQLite (`data/core.sqlite`) is
|
|
10
|
-
the default; Core 0.
|
|
10
|
+
the default; Core 0.7 also supports a dedicated PostgreSQL database through runtime
|
|
11
11
|
environment configuration. Dashboard, MCP, llms.txt, business
|
|
12
12
|
storage and Entry Register are independently packaged plugins.
|
|
13
13
|
|
|
@@ -366,8 +366,8 @@ the exit code.
|
|
|
366
366
|
| --- | --- |
|
|
367
367
|
| `toolframe-core` | Persistent FastAPI/Cordis control host, gateway and thin Rust launcher. |
|
|
368
368
|
| `toolframe-sdk` | Public definitions, worker protocol, services, resources and scoped clients. |
|
|
369
|
-
| `toolframe-
|
|
370
|
-
| `toolframe-
|
|
369
|
+
| `toolframe-sql-sqlite` | Local owner databases, SQL authorization, transactions, receipts and migrations. |
|
|
370
|
+
| `toolframe-sql-postgres` | External plugin stores, provisioning, restricted roles, migrations and database backups. |
|
|
371
371
|
| `toolframe-streamlit-dashboard` | Native Streamlit pages, shared navigation and management UI. |
|
|
372
372
|
| `toolframe-fastmcp` | MCP tools and Streamable HTTP transport. |
|
|
373
373
|
| `toolframe-llms-txt` | Index composition and explicitly packaged Markdown assets. |
|
|
@@ -198,13 +198,13 @@ service. Business implementations remain scope-based.
|
|
|
198
198
|
|
|
199
199
|
## External plugin storage
|
|
200
200
|
|
|
201
|
-
Core 0.
|
|
201
|
+
Core 0.7 and SDK 0.4 allow a storage provider to select explicit PostgreSQL
|
|
202
202
|
migration SQL. Core asks the selected provider whether a plugin store is already
|
|
203
203
|
initialized before generating private keys. If an initialized store's retained
|
|
204
204
|
key is missing, activation requires restoring the key. This works for remote
|
|
205
205
|
stores without relying on a local `data.sqlite` file.
|
|
206
206
|
|
|
207
|
-
Core defaults to `data/core.sqlite`; Core 0.
|
|
207
|
+
Core defaults to `data/core.sqlite`; Core 0.7 can select a dedicated PostgreSQL
|
|
208
208
|
journal at bootstrap. Private keys and package artifacts remain in the application
|
|
209
209
|
home. Plugin-storage credentials can be injected as environment variables inherited
|
|
210
210
|
by trusted plugin workers; Core journal credentials are removed from those worker
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dashboard access and authorization
|
|
2
2
|
|
|
3
|
-
Core 0.
|
|
3
|
+
Core 0.7.0 / SDK 0.4 use explicit scopes. The Entry Register template installs and
|
|
4
4
|
enables `toolframe-auth` and `toolframe-dashboard-auth`. An empty
|
|
5
5
|
`init` remains empty. Updating a binary alone never adds these plugins to an
|
|
6
6
|
existing application's composition.
|
|
@@ -35,14 +35,14 @@ dashboard_auth = "dashboard-auth"
|
|
|
35
35
|
failure_mode = "closed" # new applications keep protected access closed during outages
|
|
36
36
|
|
|
37
37
|
[plugins.auth]
|
|
38
|
-
source = "pypi:toolframe-auth==0.
|
|
38
|
+
source = "pypi:toolframe-auth==0.3.0"
|
|
39
39
|
enabled = true
|
|
40
40
|
[plugins.auth.config]
|
|
41
41
|
session_max_seconds = 604800
|
|
42
42
|
session_idle_seconds = 86400
|
|
43
43
|
|
|
44
44
|
[plugins.dashboard-auth]
|
|
45
|
-
source = "pypi:toolframe-dashboard-auth==0.
|
|
45
|
+
source = "pypi:toolframe-dashboard-auth==0.2.0"
|
|
46
46
|
enabled = true
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -53,7 +53,7 @@ Choose **Deny protected business access** for confidential applications. The
|
|
|
53
53
|
**Access by entrance** panel shows effective/configured Dashboard and MCP policies,
|
|
54
54
|
local-control authority and declared public HTTP methods. A declaration may be
|
|
55
55
|
unavailable when its plugin is stopped; it is not a credential-protected endpoint.
|
|
56
|
-
The failure-policy editor requires Core 0.
|
|
56
|
+
The failure-policy editor requires Core 0.7.0 and Dashboard Auth 0.2.0.
|
|
57
57
|
|
|
58
58
|
If a first-password operation commits its record but the
|
|
59
59
|
composition changed concurrently, its response includes the one-time secret,
|
|
@@ -100,7 +100,7 @@ admission. Healthy reload/restart retains eligible sessions, not Streamlit memor
|
|
|
100
100
|
|
|
101
101
|
## Failure and recovery
|
|
102
102
|
|
|
103
|
-
New applications created with Core 0.
|
|
103
|
+
New applications created with Core 0.7.0 write `access.failure_mode="closed"`.
|
|
104
104
|
Templates receive this value only when they omit it; an explicit template choice
|
|
105
105
|
is preserved. When a protected auth provider or Dashboard Auth integration fails
|
|
106
106
|
or is disabled, closed policy makes protected business access unavailable (HTTP
|
|
@@ -143,9 +143,9 @@ secrets never enter management operation history or exported composition.
|
|
|
143
143
|
All plugins now require `AuthorizationSpec`, explicit method `audience`, method
|
|
144
144
|
scopes for business/system APIs and page scopes. Legacy packages fail validation;
|
|
145
145
|
there is no synthetic whole-plugin permission. Update custom definitions using
|
|
146
|
-
the bundled skill's `references/plugin-api.md` and SDK 0.
|
|
147
|
-
provider wheels before applying the reviewed composition together. Auth 0.
|
|
148
|
-
and Dashboard Auth 0.
|
|
146
|
+
the bundled skill's `references/plugin-api.md` and SDK 0.4. Validate the matching
|
|
147
|
+
provider wheels before applying the reviewed composition together. Auth 0.3.0
|
|
148
|
+
and Dashboard Auth 0.2.0 support the flows described here. Keep the old executable/composition for rollback
|
|
149
149
|
until the new packages validate; ordinary business databases keep their schemas.
|
|
150
150
|
|
|
151
151
|
An upgraded composition without `[access]` adopts public business access once its
|
|
@@ -157,8 +157,8 @@ still apply. Generated `plugins/` business source is never overwritten.
|
|
|
157
157
|
After compatible storage and presentation providers are installed and Core is running:
|
|
158
158
|
|
|
159
159
|
```sh
|
|
160
|
-
toolframe --home APP plugin add pypi:toolframe-auth==0.
|
|
161
|
-
toolframe --home APP plugin add pypi:toolframe-dashboard-auth==0.
|
|
160
|
+
toolframe --home APP plugin add pypi:toolframe-auth==0.3.0 --enable
|
|
161
|
+
toolframe --home APP plugin add pypi:toolframe-dashboard-auth==0.2.0 --enable
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
The standard binary supplies these wheels. Open **Access passwords** through the
|
|
@@ -14,7 +14,7 @@ Selecting another provider does not migrate data.
|
|
|
14
14
|
## Local development installation
|
|
15
15
|
|
|
16
16
|
Build the matching object-storage SDK and Core revision before installing the
|
|
17
|
-
new providers. Existing SDK 0.
|
|
17
|
+
new providers. Existing SDK 0.4.0 releases do not include this development API.
|
|
18
18
|
For sibling development checkouts, build wheels into one directory:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
@@ -47,7 +47,7 @@ rather than rely on ordering of stores or environment locks.
|
|
|
47
47
|
| `application_name` | The composition's display name. |
|
|
48
48
|
| `composition_revision` | SHA256 of the current `toolframe.toml`, matching the lock and the journal's last applied desired revision. |
|
|
49
49
|
| `files` | Array of `{path, role, size, mode, sha256}` for regular files to snapshot. `size` is bytes; `mode` is an integer permission bitmask. `sha256` is the verified digest for required immutable artifacts, otherwise `null`. |
|
|
50
|
-
| `stores` | Array of `{path, owner, provider}`. Core uses `owner: null, provider: "core"`; supported business stores identify their plugin owner and `"
|
|
50
|
+
| `stores` | Array of `{path, owner, provider}`. Core uses `owner: null, provider: "core"`; supported business stores identify their plugin owner and `"sql-sqlite"` provider. |
|
|
51
51
|
| `retained_keys` | Array of `{path, owner, name}` identifying credential files to retain. `owner` is `null` for the management token and undeclared retained key files. No key contents or key hashes are returned. |
|
|
52
52
|
| `dependency_wheels` | Array of `{environment_id, distribution, version, filename, sha256, path}` for recorded dependency wheels. A local `path` is verified against its locked hash; `path: null` is an explicit dependency rehydration prerequisite. |
|
|
53
53
|
| `environment_locks` | Array of `{candidate_id, purpose, environment_id, sha256, python_version, python_implementation, platform_system, platform_machine, requires_python}`. `purpose` is `"backend"` or `"ui"`; the digest identifies the recorded lock text. Interpreter metadata comes from the source environment's regular `pyvenv.cfg`. `python_version` preserves its known precision: `"3.14"` means the source patch version is unknown, while `"3.14.7"` records a full version. Platform fields describe the local source inspection host. |
|
|
@@ -87,7 +87,7 @@ environments without importing Core's private journal layout.
|
|
|
87
87
|
## Supported state and refusal cases
|
|
88
88
|
|
|
89
89
|
Format 1 supports local SQLite Core state, business stores managed by the standard
|
|
90
|
-
`
|
|
90
|
+
`sql-sqlite` provider, and regular files within the application home. It
|
|
91
91
|
validates SQLite integrity and business-store application/owner identities with
|
|
92
92
|
read-only immutable connections. It requires an initialized Core schema version
|
|
93
93
|
1 or 2 and the composition lock recorded by that journal. It never adopts a new
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# PostgreSQL Core state
|
|
2
2
|
|
|
3
|
-
Core 0.
|
|
3
|
+
Core 0.7 can keep its management journal in PostgreSQL instead of `data/core.sqlite`.
|
|
4
4
|
The journal contains candidates, selected plugin versions, operation history,
|
|
5
5
|
idempotency keys and recovery metadata. It is independent of the optional
|
|
6
|
-
`
|
|
6
|
+
`sql-postgres` plugin, which owns business and authentication data.
|
|
7
7
|
|
|
8
8
|
Use one Core process per application, Python 3.14+, and PostgreSQL 16+. SQLite is
|
|
9
9
|
the default and keeps its existing schema history. PostgreSQL uses a **dedicated
|
|
@@ -15,7 +15,7 @@ business databases. Do not provision Core tables in a business-provider database
|
|
|
15
15
|
Install the coordinated Core release with its optional driver:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
pip install 'toolframe-core[postgres]==0.
|
|
18
|
+
pip install 'toolframe-core[postgres]==0.7.0'
|
|
19
19
|
toolframe-core --home ./app init
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -8,17 +8,17 @@ contains no Python wheels; it resolves Core and selected plugins from PyPI.
|
|
|
8
8
|
|
|
9
9
|
## Coordinated first release
|
|
10
10
|
|
|
11
|
-
Publish SDK 0.
|
|
12
|
-
the template packages:
|
|
11
|
+
Publish SDK 0.4.0 first. Cordis 0.2.2 must be available before Core. Then publish
|
|
12
|
+
the template packages: sql-sqlite 0.3.1, auth 0.2.0, dashboard-auth 0.1.3,
|
|
13
13
|
streamlit-dashboard 0.4.2, fastmcp 0.2.1, llms-txt 0.2.1 and
|
|
14
14
|
demo-entry-register 0.3.1. Each repository owns its own tag, validation and
|
|
15
15
|
`publish.yml`. Core's source-validation pins must point to the coordinated
|
|
16
16
|
commits available under the trusted GitHub owner.
|
|
17
17
|
|
|
18
|
-
Publish `toolframe-core==0.
|
|
18
|
+
Publish `toolframe-core==0.7.0` and `toolframe==0.6.4` together through Core's
|
|
19
19
|
workflow after those packages are available. Optional packages can follow:
|
|
20
20
|
object-store-local 0.1.0, object-store-s3 0.1.0, mcp-auth 0.2.0, oidc-auth 0.2.0,
|
|
21
|
-
|
|
21
|
+
sql-postgres 0.1.0, jobs 0.1.0, audit 0.1.0, backup 0.1.0 and testkit 0.1.0.
|
|
22
22
|
Backup's operator extra requires Core. Testkit's pytest integration is an extra.
|
|
23
23
|
|
|
24
24
|
## Publisher setup
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# Multiple SQL storage providers
|
|
2
2
|
|
|
3
3
|
One application can run SQLite and PostgreSQL storage providers together. Each
|
|
4
|
-
plugin owns one managed store and continues to use the SDK's `context.
|
|
4
|
+
plugin owns one managed store and continues to use the SDK's `context.sql()`
|
|
5
5
|
client. The Core journal is configured separately; see
|
|
6
6
|
[PostgreSQL Core state](postgresql-state.md).
|
|
7
7
|
|
|
8
8
|
## Configure a fresh composition
|
|
9
9
|
|
|
10
10
|
Install both providers, then choose bindings before enabling store-owning plugins.
|
|
11
|
-
For example, with `
|
|
11
|
+
For example, with `sql-sqlite` and `sql-postgres` enabled:
|
|
12
12
|
|
|
13
13
|
```toml
|
|
14
14
|
[bindings]
|
|
15
|
-
"toolframe.
|
|
16
|
-
"entry-register/
|
|
15
|
+
"toolframe.sql" = "sql-postgres"
|
|
16
|
+
"entry-register/sql" = "sql-sqlite"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
The service binding selects PostgreSQL by default. The `plugin-id/alias` binding
|
|
20
|
-
overrides it for Entry Register's `
|
|
20
|
+
overrides it for Entry Register's `sql` requirement. Auth and other consumers
|
|
21
21
|
without overrides use PostgreSQL. Provision every PostgreSQL owner and inject its
|
|
22
22
|
runtime credentials before starting the host, following that provider's setup
|
|
23
23
|
guide. SQLite needs no external server. Both providers use SQL service version 1.
|
|
@@ -45,18 +45,18 @@ Keep the SQLite service default and override only new PostgreSQL store owners:
|
|
|
45
45
|
|
|
46
46
|
```toml
|
|
47
47
|
[bindings]
|
|
48
|
-
"toolframe.
|
|
49
|
-
"orders/
|
|
48
|
+
"toolframe.sql" = "sql-sqlite"
|
|
49
|
+
"orders/sql" = "sql-postgres"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
Here `orders` is an example new plugin ID and `
|
|
52
|
+
Here `orders` is an example new plugin ID and `sql` is its SQL requirement
|
|
53
53
|
alias. Use the names declared by the plugin you are installing.
|
|
54
54
|
|
|
55
55
|
1. Back up the application home and its existing stores. Add the bindings while
|
|
56
56
|
the original SQLite provider remains enabled.
|
|
57
57
|
2. Provision the new PostgreSQL owner, supply its runtime environment, and install
|
|
58
58
|
and enable the PostgreSQL provider before enabling that owner.
|
|
59
|
-
3. Review `plan` and confirm that existing owners retain `
|
|
59
|
+
3. Review `plan` and confirm that existing owners retain `sql-sqlite`. Apply
|
|
60
60
|
the reviewed composition, then verify the new plugin through its public service.
|
|
61
61
|
|
|
62
62
|
The existing SQLite data stays in its original stores. If PostgreSQL should later
|
|
@@ -94,7 +94,7 @@ replacement operations. See the [architecture contract](architecture.md#data-own
|
|
|
94
94
|
|
|
95
95
|
## Plugin and lifecycle limits
|
|
96
96
|
|
|
97
|
-
A managed store must declare a required `toolframe.
|
|
97
|
+
A managed store must declare a required `toolframe.sql` dependency. All
|
|
98
98
|
SQL aliases in one plugin must resolve to the same provider. SQL consumers must
|
|
99
99
|
target a storage provider. Plugins needing another owner's data call its service.
|
|
100
100
|
|
|
@@ -29,8 +29,8 @@ provider wheels, so it can run from a worktree without sibling source checkouts.
|
|
|
29
29
|
Use a prepared Core development environment and matching wheels:
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
|
-
TOOLFRAME_SDK_WHEEL=/path/to/toolframe_sdk-0.
|
|
33
|
-
TOOLFRAME_STORAGE_SQLITE_WHEEL=/path/to/
|
|
32
|
+
TOOLFRAME_SDK_WHEEL=/path/to/toolframe_sdk-0.4.0-py3-none-any.whl \
|
|
33
|
+
TOOLFRAME_STORAGE_SQLITE_WHEEL=/path/to/toolframe_sql_sqlite-0.4.0-py3-none-any.whl \
|
|
34
34
|
.venv/bin/python -m pytest -q \
|
|
35
35
|
tests/test_maintenance.py::test_real_core_sqlite_business_shutdown_has_public_inventory
|
|
36
36
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "toolframe-core"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "Persistent control host for isolated Toolframe plugins"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0 AND MIT"
|
|
@@ -16,7 +16,7 @@ license-files = [
|
|
|
16
16
|
authors = [{ name = "byfb", email = "62798989+byfb@users.noreply.github.com" }]
|
|
17
17
|
requires-python = ">=3.14"
|
|
18
18
|
dependencies = [
|
|
19
|
-
"toolframe-sdk==0.
|
|
19
|
+
"toolframe-sdk==0.4.0", "fastapi-cordis==0.2.2", "fastapi==0.135.2",
|
|
20
20
|
"uvicorn==0.42.0", "httpx>=0.28,<1", "websockets>=15,<17",
|
|
21
21
|
"tomlkit>=0.13,<1", "packaging>=25", "watchfiles>=1,<2", "pyyaml>=6,<7",
|
|
22
22
|
]
|
|
@@ -29,7 +29,7 @@ Issues = "https://github.com/toolframe/toolframe-core/issues"
|
|
|
29
29
|
|
|
30
30
|
[project.optional-dependencies]
|
|
31
31
|
postgres = ["psycopg[binary]>=3.3,<4"]
|
|
32
|
-
tracing = ["toolframe-sdk[tracing]==0.
|
|
32
|
+
tracing = ["toolframe-sdk[tracing]==0.4.0"]
|
|
33
33
|
|
|
34
34
|
[project.scripts]
|
|
35
35
|
toolframe-core = "toolframe_core.cli:main"
|
|
@@ -13,7 +13,7 @@ def main():
|
|
|
13
13
|
)
|
|
14
14
|
if importlib.util.find_spec("psycopg") is None:
|
|
15
15
|
raise SystemExit("Install the Core postgres extra before running this check")
|
|
16
|
-
if importlib.util.find_spec("
|
|
16
|
+
if importlib.util.find_spec("toolframe_sql_postgres") is None:
|
|
17
17
|
raise SystemExit(
|
|
18
18
|
"Install the pinned PostgreSQL storage provider before running this check"
|
|
19
19
|
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"toolframe-sdk": "2cd153ec36c585a9adb5ad566effc2985d9e222d",
|
|
3
|
+
"fastapi-cordis": "a132b777a53ee44e4fd02d81b9a2aa9275ca13c0",
|
|
4
|
+
"toolframe-sql-sqlite": "a2764f83840fb8ad71d7eaf138c7e09799ce19bd",
|
|
5
|
+
"toolframe-sql-postgres": "e09f6b468572b980855334786e6b0eed72cf8af6",
|
|
6
|
+
"toolframe-streamlit-dashboard": "f3eff56c436b398bf81fe0bb77b06fa5790fb123",
|
|
7
|
+
"toolframe-fastmcp": "c8286f7cf7cdcf3522466a8df13945cf55fb58b3",
|
|
8
|
+
"toolframe-llms-txt": "d52dd2ed54dd4ee23bb1687d43ec347f459f7b5c",
|
|
9
|
+
"toolframe-demo-entry-register": "638e2163bd1f50f3715e05b418ac9095b4003513",
|
|
10
|
+
"toolframe-auth": "f43c623cafb1483f3387935d7ef2690ca52088c9",
|
|
11
|
+
"toolframe-dashboard-auth": "8175ab2c09979d69f63f17a81a1e28d46c2fb466",
|
|
12
|
+
"toolframe-mcp-auth": "37b53ac0b37637c953cf5e40e59b5dcde8ab2c4b",
|
|
13
|
+
"toolframe-oidc-auth": "5d88289871c7e961216536ddde812510e319a7fe"
|
|
14
|
+
}
|
|
@@ -330,7 +330,7 @@ def postgres_checks(root, core, output, env):
|
|
|
330
330
|
"--no-sources",
|
|
331
331
|
"--find-links",
|
|
332
332
|
root / "workspace/toolframe-sdk/dist",
|
|
333
|
-
root / "workspace/toolframe-
|
|
333
|
+
root / "workspace/toolframe-sql-postgres",
|
|
334
334
|
cwd=core,
|
|
335
335
|
env=env,
|
|
336
336
|
)
|
|
@@ -3,6 +3,6 @@ set -euo pipefail
|
|
|
3
3
|
toolframe_workspace="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
4
4
|
toolframe_wheels="$toolframe_workspace/toolframe-core/wheelhouse"
|
|
5
5
|
mkdir -p "$toolframe_wheels"
|
|
6
|
-
for repository in toolframe-sdk fastapi-cordis toolframe-
|
|
6
|
+
for repository in toolframe-sdk fastapi-cordis toolframe-sql-sqlite toolframe-llms-txt toolframe-fastmcp toolframe-streamlit-dashboard toolframe-demo-entry-register toolframe-auth toolframe-dashboard-auth toolframe-mcp-auth toolframe-oidc-auth toolframe-core; do
|
|
7
7
|
uv build --no-sources --wheel --out-dir "$toolframe_wheels" "$toolframe_workspace/$repository"
|
|
8
8
|
done
|
|
@@ -124,7 +124,7 @@ def main():
|
|
|
124
124
|
for edge in graph["edges"]
|
|
125
125
|
)
|
|
126
126
|
assert any(
|
|
127
|
-
edge["source"] == "entry-register" and edge["target"] == "
|
|
127
|
+
edge["source"] == "entry-register" and edge["target"] == "sql-sqlite"
|
|
128
128
|
for edge in graph["edges"]
|
|
129
129
|
)
|
|
130
130
|
assert {
|
|
@@ -144,7 +144,7 @@ def main():
|
|
|
144
144
|
)
|
|
145
145
|
|
|
146
146
|
for name, action in (
|
|
147
|
-
("
|
|
147
|
+
("sql-sqlite", "reload"),
|
|
148
148
|
("entry-register", "disable"),
|
|
149
149
|
):
|
|
150
150
|
plan = operation("plan", {"id": name, "action": action})
|
|
@@ -279,8 +279,8 @@ def main():
|
|
|
279
279
|
!= by_id(status)["entry-register"]
|
|
280
280
|
)
|
|
281
281
|
assert (
|
|
282
|
-
by_id(after)["
|
|
283
|
-
== by_id(status)["
|
|
282
|
+
by_id(after)["sql-sqlite"]
|
|
283
|
+
== by_id(status)["sql-sqlite"]
|
|
284
284
|
)
|
|
285
285
|
outcome["reload"] = op
|
|
286
286
|
outcome["after_reload"] = {
|
|
@@ -40,7 +40,7 @@ def main():
|
|
|
40
40
|
|
|
41
41
|
def run(*arguments, expected=0, structured=True):
|
|
42
42
|
completed = subprocess.run(
|
|
43
|
-
[str(binary), *map(str, arguments)],
|
|
43
|
+
[str(binary), "--wheelhouse", str(wheels), *map(str, arguments)],
|
|
44
44
|
env=environment,
|
|
45
45
|
cwd=root,
|
|
46
46
|
stdin=subprocess.DEVNULL,
|
|
@@ -194,7 +194,7 @@ def main():
|
|
|
194
194
|
assert inventory(source) == before
|
|
195
195
|
local_wheels = root / "wheelhouse"
|
|
196
196
|
local_wheels.mkdir()
|
|
197
|
-
for name in ("toolframe_sdk", "
|
|
197
|
+
for name in ("toolframe_core", "toolframe_sdk", "toolframe_sql_sqlite"):
|
|
198
198
|
for wheel in wheels.glob(f"{name}-*.whl"):
|
|
199
199
|
shutil.copy2(wheel, local_wheels / wheel.name)
|
|
200
200
|
configuration = home / "toolframe.toml"
|
|
@@ -237,7 +237,7 @@ def main():
|
|
|
237
237
|
after["plugins"] == [] and after["operations"] == status["operations"]
|
|
238
238
|
)
|
|
239
239
|
assert configuration.read_bytes() == composition_before
|
|
240
|
-
storage = next(local_wheels.glob("
|
|
240
|
+
storage = next(local_wheels.glob("toolframe_sql_sqlite-*.whl"))
|
|
241
241
|
run("--home", home, "plugin", "add", storage, "--enable", "--json")
|
|
242
242
|
added = run("--home", home, "plugin", "add", plugin_wheel, "--json")
|
|
243
243
|
assert added["status"] == "succeeded"
|
|
@@ -23,10 +23,10 @@ fn tracing_requested(value: Option<&str>) -> Result<bool> {
|
|
|
23
23
|
|
|
24
24
|
fn core_requirement(postgres: bool, tracing: bool) -> &'static str {
|
|
25
25
|
match (postgres, tracing) {
|
|
26
|
-
(true, true) => "toolframe-core[postgres,tracing]==0.
|
|
27
|
-
(true, false) => "toolframe-core[postgres]==0.
|
|
28
|
-
(false, true) => "toolframe-core[tracing]==0.
|
|
29
|
-
(false, false) => "toolframe-core==0.
|
|
26
|
+
(true, true) => "toolframe-core[postgres,tracing]==0.7.0",
|
|
27
|
+
(true, false) => "toolframe-core[postgres]==0.7.0",
|
|
28
|
+
(false, true) => "toolframe-core[tracing]==0.7.0",
|
|
29
|
+
(false, false) => "toolframe-core==0.7.0",
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -270,18 +270,18 @@ mod tests {
|
|
|
270
270
|
|
|
271
271
|
#[test]
|
|
272
272
|
fn runtime_profiles_select_only_the_requested_extras() {
|
|
273
|
-
assert_eq!(core_requirement(false, false), "toolframe-core==0.
|
|
273
|
+
assert_eq!(core_requirement(false, false), "toolframe-core==0.7.0");
|
|
274
274
|
assert_eq!(
|
|
275
275
|
core_requirement(false, true),
|
|
276
|
-
"toolframe-core[tracing]==0.
|
|
276
|
+
"toolframe-core[tracing]==0.7.0"
|
|
277
277
|
);
|
|
278
278
|
assert_eq!(
|
|
279
279
|
core_requirement(true, false),
|
|
280
|
-
"toolframe-core[postgres]==0.
|
|
280
|
+
"toolframe-core[postgres]==0.7.0"
|
|
281
281
|
);
|
|
282
282
|
assert_eq!(
|
|
283
283
|
core_requirement(true, true),
|
|
284
|
-
"toolframe-core[postgres,tracing]==0.
|
|
284
|
+
"toolframe-core[postgres,tracing]==0.7.0"
|
|
285
285
|
);
|
|
286
286
|
}
|
|
287
287
|
}
|
|
@@ -7,7 +7,7 @@ description: Load when designing, creating, or extending a Toolframe business pl
|
|
|
7
7
|
# Toolframe plugin design
|
|
8
8
|
|
|
9
9
|
Turn the user's business outcome into an independently packaged Toolframe plugin.
|
|
10
|
-
This skill targets Toolframe Core 0.
|
|
10
|
+
This skill targets Toolframe Core 0.7.0 and SDK 0.4. The attached references and
|
|
11
11
|
starter travel with the application; a Toolframe source checkout is optional.
|
|
12
12
|
|
|
13
13
|
## Establish the design
|
|
@@ -9,7 +9,7 @@ description = "Small independently packaged Toolframe notes plugin"
|
|
|
9
9
|
license = "MIT"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
11
11
|
requires-python = ">=3.14"
|
|
12
|
-
dependencies = ["toolframe-sdk==0.
|
|
12
|
+
dependencies = ["toolframe-sdk==0.4.0"]
|
|
13
13
|
|
|
14
14
|
[project.optional-dependencies]
|
|
15
15
|
ui = ["streamlit==1.61.0"]
|
|
@@ -52,7 +52,7 @@ plugin = PluginDefinition(
|
|
|
52
52
|
"sample-notes.write": ScopeSpec(title="Capture notes"),
|
|
53
53
|
}
|
|
54
54
|
),
|
|
55
|
-
requires={"
|
|
55
|
+
requires={"sql": Requirement(service="toolframe.sql")},
|
|
56
56
|
services={
|
|
57
57
|
SERVICE: ServiceSpec(
|
|
58
58
|
methods={
|
|
@@ -12,7 +12,7 @@ class Notes(Plugin):
|
|
|
12
12
|
"note_invalid", "A note needs 1–1000 nonblank characters."
|
|
13
13
|
)
|
|
14
14
|
body = body.strip()
|
|
15
|
-
async with self.context.
|
|
15
|
+
async with self.context.sql().transaction() as tx:
|
|
16
16
|
created = await tx.execute(
|
|
17
17
|
"INSERT INTO notes(body, created_at) VALUES (?, ?)",
|
|
18
18
|
(body, datetime.now(UTC).isoformat()),
|
|
@@ -30,7 +30,7 @@ class Notes(Plugin):
|
|
|
30
30
|
or not 1 <= limit <= 100
|
|
31
31
|
):
|
|
32
32
|
raise PluginError("note_invalid", "limit must be an integer from 1 to 100.")
|
|
33
|
-
notes = await self.context.
|
|
33
|
+
notes = await self.context.sql().query(
|
|
34
34
|
"SELECT id, body, created_at FROM notes ORDER BY id DESC LIMIT ?", (limit,)
|
|
35
35
|
)
|
|
36
36
|
return {"notes": notes, "count": len(notes)}
|
|
@@ -44,5 +44,5 @@ class Notes(Plugin):
|
|
|
44
44
|
raise PluginError("method_not_found", f"Unknown method {service}/{method}")
|
|
45
45
|
|
|
46
46
|
async def health(self):
|
|
47
|
-
await self.context.
|
|
47
|
+
await self.context.sql().query("SELECT id FROM notes LIMIT 1")
|
|
48
48
|
return {"runtime": "ready", "business": "ready"}
|
|
@@ -51,7 +51,7 @@ Run `serve` in a separate terminal. Add required providers to the composition
|
|
|
51
51
|
before enabling a plugin that consumes their services. For a local SQLite wheel:
|
|
52
52
|
|
|
53
53
|
```sh
|
|
54
|
-
toolframe --home APP plugin add /path/to/
|
|
54
|
+
toolframe --home APP plugin add /path/to/toolframe_sql_sqlite-0.4.0-py3-none-any.whl --enable
|
|
55
55
|
toolframe --home APP plugin add APP/plugins/customer-notes
|
|
56
56
|
toolframe --home APP plugin validate customer-notes
|
|
57
57
|
toolframe --home APP plugin validate customer-notes --runtime
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public plugin contract
|
|
2
2
|
|
|
3
|
-
Target: `toolframe-sdk==0.
|
|
3
|
+
Target: `toolframe-sdk==0.4.0`, Core 0.7.0, Python 3.14. Use this packaged reference
|
|
4
4
|
and the starter when the source workspace is unavailable. If the installed SDK
|
|
5
5
|
version differs, inspect its public definitions before adapting these examples.
|
|
6
6
|
|
|
@@ -99,7 +99,7 @@ passwords and management tokens are not MCP keys. Protected MCP stays unavailabl
|
|
|
99
99
|
if its verifier is absent or fails, independently of Dashboard fallback. New Core
|
|
100
100
|
applications write `failure_mode="closed"`; older files omitting it retain legacy
|
|
101
101
|
public fallback. Review existing choices before changing them. The access-password
|
|
102
|
-
page shows entrance states; its failure-policy editor requires Core 0.
|
|
102
|
+
page shows entrance states; its failure-policy editor requires Core 0.7.0.
|
|
103
103
|
|
|
104
104
|
Scopes authorize methods, not individual rows. Password labels identify grants,
|
|
105
105
|
not people. Per-person or tenant data needs a trusted identity and explicit
|
|
@@ -116,14 +116,14 @@ trusted application code, not a sandbox for untrusted extensions.
|
|
|
116
116
|
|
|
117
117
|
## Managed SQLite
|
|
118
118
|
|
|
119
|
-
Declare `requires={"
|
|
119
|
+
Declare `requires={"sql": Requirement(service="toolframe.sql")}`
|
|
120
120
|
and `store=StoreSchema(revision="v1", migrations=(Migration(...),))` when needed.
|
|
121
121
|
The provider allocates a database for the stable plugin ID. It retains data when
|
|
122
122
|
a plugin is disabled, removed or reloaded. Core's own SQLite holds management
|
|
123
123
|
state and is not business storage.
|
|
124
124
|
|
|
125
125
|
```python
|
|
126
|
-
storage = self.context.
|
|
126
|
+
storage = self.context.sql() # requires alias "sql"
|
|
127
127
|
async with storage.transaction() as tx:
|
|
128
128
|
result = await tx.execute("INSERT INTO notes(body) VALUES (?)", (body,))
|
|
129
129
|
rows = await tx.query(
|