ciris-agent 1.7.7__py3-none-any.whl
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.
- ciris_adapters/README.md +113 -0
- ciris_adapters/__init__.py +30 -0
- ciris_adapters/ciris_covenant_metrics/README.md +144 -0
- ciris_adapters/ciris_covenant_metrics/__init__.py +36 -0
- ciris_adapters/ciris_covenant_metrics/adapter.py +249 -0
- ciris_adapters/ciris_covenant_metrics/manifest.json +152 -0
- ciris_adapters/ciris_covenant_metrics/services.py +403 -0
- ciris_adapters/ciris_hosted_tools/__init__.py +24 -0
- ciris_adapters/ciris_hosted_tools/adapter.py +169 -0
- ciris_adapters/ciris_hosted_tools/manifest.json +94 -0
- ciris_adapters/ciris_hosted_tools/services.py +744 -0
- ciris_adapters/external_data_sql/README.md +559 -0
- ciris_adapters/external_data_sql/__init__.py +43 -0
- ciris_adapters/external_data_sql/adapter.py +144 -0
- ciris_adapters/external_data_sql/configurable.py +315 -0
- ciris_adapters/external_data_sql/dialects/__init__.py +37 -0
- ciris_adapters/external_data_sql/dialects/base.py +133 -0
- ciris_adapters/external_data_sql/dialects/mysql.py +63 -0
- ciris_adapters/external_data_sql/dialects/postgresql.py +59 -0
- ciris_adapters/external_data_sql/dialects/sqlite.py +62 -0
- ciris_adapters/external_data_sql/example_config.json +88 -0
- ciris_adapters/external_data_sql/example_privacy_schema.yaml +127 -0
- ciris_adapters/external_data_sql/manifest.json +195 -0
- ciris_adapters/external_data_sql/privacy_schema_loader.py +189 -0
- ciris_adapters/external_data_sql/protocol.py +101 -0
- ciris_adapters/external_data_sql/schemas.py +146 -0
- ciris_adapters/external_data_sql/service.py +1547 -0
- ciris_adapters/external_data_sql/service_old.py +492 -0
- ciris_adapters/home_assistant/__init__.py +63 -0
- ciris_adapters/home_assistant/adapter.py +201 -0
- ciris_adapters/home_assistant/communication_service.py +347 -0
- ciris_adapters/home_assistant/configurable.py +667 -0
- ciris_adapters/home_assistant/manifest.json +203 -0
- ciris_adapters/home_assistant/schemas.py +129 -0
- ciris_adapters/home_assistant/service.py +751 -0
- ciris_adapters/home_assistant/tool_service.py +441 -0
- ciris_adapters/mcp_client/__init__.py +82 -0
- ciris_adapters/mcp_client/adapter.py +847 -0
- ciris_adapters/mcp_client/config.py +280 -0
- ciris_adapters/mcp_client/configurable.py +422 -0
- ciris_adapters/mcp_client/manifest.json +185 -0
- ciris_adapters/mcp_client/mcp_communication_service.py +393 -0
- ciris_adapters/mcp_client/mcp_tool_service.py +463 -0
- ciris_adapters/mcp_client/mcp_wise_service.py +394 -0
- ciris_adapters/mcp_client/schemas.py +149 -0
- ciris_adapters/mcp_client/security.py +592 -0
- ciris_adapters/mcp_common/__init__.py +44 -0
- ciris_adapters/mcp_common/manifest.json +25 -0
- ciris_adapters/mcp_common/protocol.py +315 -0
- ciris_adapters/mcp_common/schemas.py +225 -0
- ciris_adapters/mcp_server/__init__.py +47 -0
- ciris_adapters/mcp_server/adapter.py +581 -0
- ciris_adapters/mcp_server/config.py +260 -0
- ciris_adapters/mcp_server/configurable.py +393 -0
- ciris_adapters/mcp_server/handlers.py +663 -0
- ciris_adapters/mcp_server/manifest.json +211 -0
- ciris_adapters/mcp_server/security.py +500 -0
- ciris_adapters/mock_llm/README.md +117 -0
- ciris_adapters/mock_llm/__init__.py +21 -0
- ciris_adapters/mock_llm/adapter.py +131 -0
- ciris_adapters/mock_llm/configurable.py +237 -0
- ciris_adapters/mock_llm/manifest.json +106 -0
- ciris_adapters/mock_llm/protocol.py +37 -0
- ciris_adapters/mock_llm/responses.py +520 -0
- ciris_adapters/mock_llm/responses_action_selection.py +1041 -0
- ciris_adapters/mock_llm/responses_epistemic.py +17 -0
- ciris_adapters/mock_llm/responses_feedback.py +27 -0
- ciris_adapters/mock_llm/schemas.py +35 -0
- ciris_adapters/mock_llm/service.py +294 -0
- ciris_adapters/navigation/__init__.py +21 -0
- ciris_adapters/navigation/adapter.py +129 -0
- ciris_adapters/navigation/configurable.py +239 -0
- ciris_adapters/navigation/manifest.json +104 -0
- ciris_adapters/navigation/service.py +487 -0
- ciris_adapters/reddit/README.md +132 -0
- ciris_adapters/reddit/REDDIT_ADAPTER_ANALYSIS.md +715 -0
- ciris_adapters/reddit/REDDIT_ADAPTER_SUMMARY.txt +278 -0
- ciris_adapters/reddit/REDDIT_ANALYSIS_INDEX.md +307 -0
- ciris_adapters/reddit/REDDIT_PRODUCTION_READINESS_PLAN.md +518 -0
- ciris_adapters/reddit/__init__.py +15 -0
- ciris_adapters/reddit/adapter.py +189 -0
- ciris_adapters/reddit/configurable.py +274 -0
- ciris_adapters/reddit/error_handler.py +307 -0
- ciris_adapters/reddit/manifest.json +218 -0
- ciris_adapters/reddit/observer.py +532 -0
- ciris_adapters/reddit/protocol.py +34 -0
- ciris_adapters/reddit/schemas.py +433 -0
- ciris_adapters/reddit/service.py +1471 -0
- ciris_adapters/sample_adapter/README.md +474 -0
- ciris_adapters/sample_adapter/__init__.py +45 -0
- ciris_adapters/sample_adapter/adapter.py +208 -0
- ciris_adapters/sample_adapter/configurable.py +469 -0
- ciris_adapters/sample_adapter/manifest.json +247 -0
- ciris_adapters/sample_adapter/services.py +486 -0
- ciris_adapters/weather/__init__.py +16 -0
- ciris_adapters/weather/adapter.py +130 -0
- ciris_adapters/weather/configurable.py +240 -0
- ciris_adapters/weather/manifest.json +156 -0
- ciris_adapters/weather/service.py +600 -0
- ciris_agent-1.7.7.dist-info/METADATA +284 -0
- ciris_agent-1.7.7.dist-info/RECORD +986 -0
- ciris_agent-1.7.7.dist-info/WHEEL +5 -0
- ciris_agent-1.7.7.dist-info/entry_points.txt +15 -0
- ciris_agent-1.7.7.dist-info/licenses/LICENSE +205 -0
- ciris_agent-1.7.7.dist-info/licenses/NOTICE +82 -0
- ciris_agent-1.7.7.dist-info/top_level.txt +4 -0
- ciris_engine/__init__.py +15 -0
- ciris_engine/ciris_templates/ally.yaml +632 -0
- ciris_engine/ciris_templates/default.yaml +411 -0
- ciris_engine/ciris_templates/echo-core.yaml +629 -0
- ciris_engine/ciris_templates/echo-speculative.yaml +764 -0
- ciris_engine/ciris_templates/echo.yaml +647 -0
- ciris_engine/ciris_templates/sage.yaml +332 -0
- ciris_engine/ciris_templates/scout.yaml +338 -0
- ciris_engine/ciris_templates/test.yaml +168 -0
- ciris_engine/cli.py +42 -0
- ciris_engine/config/CIRIS_SERVICES.json +19 -0
- ciris_engine/config/MODEL_CAPABILITIES.json +419 -0
- ciris_engine/config/PRICING_DATA.json +179 -0
- ciris_engine/config/__init__.py +50 -0
- ciris_engine/config/ciris_services.py +113 -0
- ciris_engine/config/model_capabilities.py +388 -0
- ciris_engine/config/pricing_models.py +276 -0
- ciris_engine/constants.py +35 -0
- ciris_engine/data/__init__.py +1 -0
- ciris_engine/data/covenant_1.0b.txt +978 -0
- ciris_engine/gui_static/11steps.svg +107 -0
- ciris_engine/gui_static/2x-schematics.png +0 -0
- ciris_engine/gui_static/404/index.html +1 -0
- ciris_engine/gui_static/404.html +1 -0
- ciris_engine/gui_static/_next/static/0edhkwDxd5UccTsCmtaBi/_buildManifest.js +1 -0
- ciris_engine/gui_static/_next/static/0edhkwDxd5UccTsCmtaBi/_ssgManifest.js +1 -0
- ciris_engine/gui_static/_next/static/U-3xTQao7hc2wnAi-Uekm/_buildManifest.js +1 -0
- ciris_engine/gui_static/_next/static/U-3xTQao7hc2wnAi-Uekm/_ssgManifest.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/3297-60e86ba0f8a7b040.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/3835-2aad4b7f5f8e4643.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4499-99a0bc47de0b8975.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4534-af88cd4ba6e99bff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4541-84b455f9e0dc4cfe.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/4789-61412711484754bb.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/6539-c6398bc9d7018430.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/704-8e827b26cc8c2d32.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/704-fb45d630f3192c6f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8072-de4952a2e6d2b33f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8315-b91d03a3949db0af.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8386-f93a83ccbd789bd9.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/87c73c54-781a7f35148d5433.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/8903-fefea3339a02d41b.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/9090-e66485adf8d9d990.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/_not-found/page-a67d9808462c23b1.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/api-keys/page-2d7ee1583bbbd02e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/api-keys/page-6a3c2bae6fe92b7b.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/consent/page-2ed3a035136bc4e8.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/consent/page-b2f5c91844a32422.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/page-25b90f89af3ea58c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/page-b65d16c94ecaf69c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/privacy/page-675b6d05c8f9184f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/privacy/page-cbee2e1c8ab52145.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/settings/page-0f44da06697cf9f0.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/account/settings/page-563420253577edbf.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/adapters/page-1854631018bc32be.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/agents/page-8353752c176a7c70.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/agents/page-f61a529f110a6040.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/api-demo/page-7f19b9d20d39be28.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/api-demo/page-d1063938f249b8bd.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/audit/page-321b6728b8fff0bb.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/audit/page-ebac35ca961a1277.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/billing/page-6f3dc3bd02924f8e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/billing/page-fa4a469f814c821a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/comms/page-0d4f734269addd8f.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/comms/page-79227d426050089c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/config/page-018d21d683b6e5bc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/config/page-2aa5a5363ca2a371.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/consent/page-198373205fd316e2.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/consent/page-f2ca39e7713b13f8.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/dashboard/page-1dd5a196f643c60d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/dashboard/page-530a04d3abbb8cda.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/docs/page-3193b06d094ab654.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/docs/page-330e996dedb87aba.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/layout-0a70f5fc460298b1.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/layout-21f2f99dd5b336e9.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/login/page-33240e6c6034a49d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/login/page-68ffab6d54a7fdcd.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/logs/page-8a6167aecc4a475c.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/memory/page-9ca8c5d0056de3ff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/memory/page-e961226941c18f81.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/page-6fdb065a787a4974.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/page-89f87d431be6064a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/runtime/page-2e728b9c43aa164d.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/runtime/page-c7dd033dc40a72f0.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/services/page-ae9f0bdf11d01a95.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/services/page-b10feb79ca5d75e5.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/sessions/page-13ebe7ef1c16ae11.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/sessions/page-e6c82b16d617f785.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/setup/page-0beb5f5b5a5c20fc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/setup/page-2595e729eae30c0e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/status-dashboard/page-1037c987aecc3653.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/status-dashboard/page-2ffd147f6d3162ff.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/system/page-2c5798d58cafcd91.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/system/page-505b1ba4eceb01c3.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-auth/page-b0cad31d5cb1b2fa.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-auth/page-f3ecd7a8012df230.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-login/page-f35117fdc4105801.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-login/page-fb583a7924114906.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-sdk/page-50f116fd76935563.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/test-sdk/page-c37d8aa5ba623a44.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/tools/page-429aec7a707777ef.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/tools/page-5f705aad60e0c04e.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/users/page-13476b8b0f3808cc.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/users/page-7e500d154ed5bba4.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/wa/page-cc4a9d8a5cb44d08.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/app/wa/page-ec3e429efbc79230.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/framework-9d29490f5ba089ba.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-1f554952e47a82c4.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-app-26fa8aed029082e5.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/main-app-97b0486ef6bcef25.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/pages/_app-6ce685456e616eb2.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/pages/_error-d4bce98d93fe21e7.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- ciris_engine/gui_static/_next/static/chunks/webpack-fcebd240b7f8477d.js +1 -0
- ciris_engine/gui_static/_next/static/css/16b94b1fe0cc6e37.css +3 -0
- ciris_engine/gui_static/_next/static/css/77a24ceaae86deff.css +3 -0
- ciris_engine/gui_static/_next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/747892c23ea88013-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/8d697b304b401681-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/9610d9e46709d722-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- ciris_engine/gui_static/_next/static/media/d8298875641ec7d4-s.p.woff2 +0 -0
- ciris_engine/gui_static/account/api-keys/index.html +1 -0
- ciris_engine/gui_static/account/api-keys/index.txt +27 -0
- ciris_engine/gui_static/account/consent/index.html +1 -0
- ciris_engine/gui_static/account/consent/index.txt +27 -0
- ciris_engine/gui_static/account/index.html +1 -0
- ciris_engine/gui_static/account/index.txt +27 -0
- ciris_engine/gui_static/account/privacy/index.html +1 -0
- ciris_engine/gui_static/account/privacy/index.txt +27 -0
- ciris_engine/gui_static/account/settings/index.html +1 -0
- ciris_engine/gui_static/account/settings/index.txt +27 -0
- ciris_engine/gui_static/adapters/index.html +1 -0
- ciris_engine/gui_static/adapters/index.txt +27 -0
- ciris_engine/gui_static/agents/index.html +1 -0
- ciris_engine/gui_static/agents/index.txt +27 -0
- ciris_engine/gui_static/andrew-roberts-euBRXcx57T4-unsplash.jpg +0 -0
- ciris_engine/gui_static/api-demo/index.html +1 -0
- ciris_engine/gui_static/api-demo/index.txt +27 -0
- ciris_engine/gui_static/audit/index.html +1 -0
- ciris_engine/gui_static/audit/index.txt +27 -0
- ciris_engine/gui_static/billing/index.html +1 -0
- ciris_engine/gui_static/billing/index.txt +27 -0
- ciris_engine/gui_static/blurryinfo.png +0 -0
- ciris_engine/gui_static/chip-vincent-PkQDwfl9Flc-unsplash.jpg +0 -0
- ciris_engine/gui_static/ciris-architecture.svg +338 -0
- ciris_engine/gui_static/comms/index.html +1 -0
- ciris_engine/gui_static/comms/index.txt +27 -0
- ciris_engine/gui_static/config/index.html +1 -0
- ciris_engine/gui_static/config/index.txt +27 -0
- ciris_engine/gui_static/consent/index.html +1 -0
- ciris_engine/gui_static/consent/index.txt +27 -0
- ciris_engine/gui_static/dashboard/index.html +1 -0
- ciris_engine/gui_static/dashboard/index.txt +27 -0
- ciris_engine/gui_static/docs/index.html +1 -0
- ciris_engine/gui_static/docs/index.txt +27 -0
- ciris_engine/gui_static/eric.png +0 -0
- ciris_engine/gui_static/file.svg +1 -0
- ciris_engine/gui_static/globe.svg +1 -0
- ciris_engine/gui_static/index.html +1 -0
- ciris_engine/gui_static/index.txt +27 -0
- ciris_engine/gui_static/infogfx-1@2x.png +0 -0
- ciris_engine/gui_static/infogfx-2.png +0 -0
- ciris_engine/gui_static/infogfx-dark-1.png +0 -0
- ciris_engine/gui_static/kelly-vohs-soSTXmIxTDU-unsplash.jpg +0 -0
- ciris_engine/gui_static/login/index.html +1 -0
- ciris_engine/gui_static/login/index.txt +27 -0
- ciris_engine/gui_static/logs/index.html +1 -0
- ciris_engine/gui_static/logs/index.txt +27 -0
- ciris_engine/gui_static/memory/index.html +1 -0
- ciris_engine/gui_static/memory/index.txt +27 -0
- ciris_engine/gui_static/nathan-farrish-ArcTfEoBgzs-unsplash.jpg +0 -0
- ciris_engine/gui_static/next.svg +1 -0
- ciris_engine/gui_static/overview.svg +512 -0
- ciris_engine/gui_static/overview1.svg +407 -0
- ciris_engine/gui_static/overview2.svg +370 -0
- ciris_engine/gui_static/pipeline-visualization.svg +278 -0
- ciris_engine/gui_static/privacy-policy.html +160 -0
- ciris_engine/gui_static/runtime/index.html +8 -0
- ciris_engine/gui_static/runtime/index.txt +27 -0
- ciris_engine/gui_static/services/index.html +1 -0
- ciris_engine/gui_static/services/index.txt +27 -0
- ciris_engine/gui_static/sessions/index.html +1 -0
- ciris_engine/gui_static/sessions/index.txt +27 -0
- ciris_engine/gui_static/setup/index.html +1 -0
- ciris_engine/gui_static/setup/index.txt +27 -0
- ciris_engine/gui_static/status-dashboard/index.html +1 -0
- ciris_engine/gui_static/status-dashboard/index.txt +27 -0
- ciris_engine/gui_static/system/index.html +1 -0
- ciris_engine/gui_static/system/index.txt +27 -0
- ciris_engine/gui_static/terms-of-service.html +174 -0
- ciris_engine/gui_static/test-auth/index.html +1 -0
- ciris_engine/gui_static/test-auth/index.txt +27 -0
- ciris_engine/gui_static/test-login/index.html +1 -0
- ciris_engine/gui_static/test-login/index.txt +27 -0
- ciris_engine/gui_static/test-sdk/index.html +1 -0
- ciris_engine/gui_static/test-sdk/index.txt +27 -0
- ciris_engine/gui_static/tools/index.html +1 -0
- ciris_engine/gui_static/tools/index.txt +27 -0
- ciris_engine/gui_static/users/index.html +1 -0
- ciris_engine/gui_static/users/index.txt +27 -0
- ciris_engine/gui_static/vercel.svg +1 -0
- ciris_engine/gui_static/videos/video1.mp4 +0 -0
- ciris_engine/gui_static/videos/video3.mp4 +0 -0
- ciris_engine/gui_static/wa/index.html +1 -0
- ciris_engine/gui_static/wa/index.txt +27 -0
- ciris_engine/gui_static/window.svg +1 -0
- ciris_engine/logic/__init__.py +8 -0
- ciris_engine/logic/adapters/__init__.py +74 -0
- ciris_engine/logic/adapters/api/__init__.py +5 -0
- ciris_engine/logic/adapters/api/adapter.py +1037 -0
- ciris_engine/logic/adapters/api/api_communication.py +370 -0
- ciris_engine/logic/adapters/api/api_document.py +330 -0
- ciris_engine/logic/adapters/api/api_observer.py +24 -0
- ciris_engine/logic/adapters/api/api_runtime_control.py +388 -0
- ciris_engine/logic/adapters/api/api_tools.py +299 -0
- ciris_engine/logic/adapters/api/api_vision.py +215 -0
- ciris_engine/logic/adapters/api/app.py +272 -0
- ciris_engine/logic/adapters/api/auth.py +159 -0
- ciris_engine/logic/adapters/api/config.py +101 -0
- ciris_engine/logic/adapters/api/constants.py +55 -0
- ciris_engine/logic/adapters/api/dependencies/__init__.py +1 -0
- ciris_engine/logic/adapters/api/dependencies/auth.py +260 -0
- ciris_engine/logic/adapters/api/endpoints/__init__.py +1 -0
- ciris_engine/logic/adapters/api/endpoints/emergency.py +86 -0
- ciris_engine/logic/adapters/api/middleware/__init__.py +1 -0
- ciris_engine/logic/adapters/api/middleware/rate_limiter.py +302 -0
- ciris_engine/logic/adapters/api/models.py +29 -0
- ciris_engine/logic/adapters/api/routes/__init__.py +52 -0
- ciris_engine/logic/adapters/api/routes/agent.py +1762 -0
- ciris_engine/logic/adapters/api/routes/audit.py +707 -0
- ciris_engine/logic/adapters/api/routes/auth.py +1745 -0
- ciris_engine/logic/adapters/api/routes/billing.py +895 -0
- ciris_engine/logic/adapters/api/routes/config.py +329 -0
- ciris_engine/logic/adapters/api/routes/connectors.py +534 -0
- ciris_engine/logic/adapters/api/routes/consent.py +637 -0
- ciris_engine/logic/adapters/api/routes/dsar.py +637 -0
- ciris_engine/logic/adapters/api/routes/dsar_multi_source.py +484 -0
- ciris_engine/logic/adapters/api/routes/emergency.py +302 -0
- ciris_engine/logic/adapters/api/routes/memory.py +733 -0
- ciris_engine/logic/adapters/api/routes/memory_filters.py +230 -0
- ciris_engine/logic/adapters/api/routes/memory_models.py +112 -0
- ciris_engine/logic/adapters/api/routes/memory_queries.py +236 -0
- ciris_engine/logic/adapters/api/routes/memory_query_helpers.py +394 -0
- ciris_engine/logic/adapters/api/routes/memory_visualization.py +359 -0
- ciris_engine/logic/adapters/api/routes/memory_visualization_helpers.py +110 -0
- ciris_engine/logic/adapters/api/routes/partnership.py +541 -0
- ciris_engine/logic/adapters/api/routes/setup.py +1374 -0
- ciris_engine/logic/adapters/api/routes/system.py +3049 -0
- ciris_engine/logic/adapters/api/routes/system_extensions.py +952 -0
- ciris_engine/logic/adapters/api/routes/telemetry.py +1987 -0
- ciris_engine/logic/adapters/api/routes/telemetry_converters.py +141 -0
- ciris_engine/logic/adapters/api/routes/telemetry_helpers.py +111 -0
- ciris_engine/logic/adapters/api/routes/telemetry_logs_reader.py +280 -0
- ciris_engine/logic/adapters/api/routes/telemetry_metrics.py +131 -0
- ciris_engine/logic/adapters/api/routes/telemetry_models.py +190 -0
- ciris_engine/logic/adapters/api/routes/telemetry_otlp.py +878 -0
- ciris_engine/logic/adapters/api/routes/telemetry_resource_helpers.py +191 -0
- ciris_engine/logic/adapters/api/routes/tickets.py +541 -0
- ciris_engine/logic/adapters/api/routes/tools.py +556 -0
- ciris_engine/logic/adapters/api/routes/transparency.py +281 -0
- ciris_engine/logic/adapters/api/routes/users.py +981 -0
- ciris_engine/logic/adapters/api/routes/verification.py +373 -0
- ciris_engine/logic/adapters/api/routes/wa.py +369 -0
- ciris_engine/logic/adapters/api/service_configuration.py +177 -0
- ciris_engine/logic/adapters/api/services/__init__.py +1 -0
- ciris_engine/logic/adapters/api/services/auth_service.py +1417 -0
- ciris_engine/logic/adapters/api/services/oauth_security.py +68 -0
- ciris_engine/logic/adapters/base.py +141 -0
- ciris_engine/logic/adapters/base_adapter.py +73 -0
- ciris_engine/logic/adapters/base_observer.py +1141 -0
- ciris_engine/logic/adapters/base_vision.py +312 -0
- ciris_engine/logic/adapters/cirisnode_client.py +307 -0
- ciris_engine/logic/adapters/cli/__init__.py +3 -0
- ciris_engine/logic/adapters/cli/adapter.py +207 -0
- ciris_engine/logic/adapters/cli/cli_adapter.py +902 -0
- ciris_engine/logic/adapters/cli/cli_observer.py +268 -0
- ciris_engine/logic/adapters/cli/cli_tools.py +427 -0
- ciris_engine/logic/adapters/cli/cli_wa_service.py +134 -0
- ciris_engine/logic/adapters/cli/config.py +73 -0
- ciris_engine/logic/adapters/discord/__init__.py +3 -0
- ciris_engine/logic/adapters/discord/adapter.py +783 -0
- ciris_engine/logic/adapters/discord/ciris_discord_client.py +159 -0
- ciris_engine/logic/adapters/discord/config.py +177 -0
- ciris_engine/logic/adapters/discord/constants.py +185 -0
- ciris_engine/logic/adapters/discord/discord-stubs.pyi +50 -0
- ciris_engine/logic/adapters/discord/discord_adapter.py +1584 -0
- ciris_engine/logic/adapters/discord/discord_audit.py +150 -0
- ciris_engine/logic/adapters/discord/discord_channel_manager.py +351 -0
- ciris_engine/logic/adapters/discord/discord_connection_manager.py +313 -0
- ciris_engine/logic/adapters/discord/discord_embed_formatter.py +369 -0
- ciris_engine/logic/adapters/discord/discord_error_classifier.py +302 -0
- ciris_engine/logic/adapters/discord/discord_error_handler.py +316 -0
- ciris_engine/logic/adapters/discord/discord_guidance_handler.py +460 -0
- ciris_engine/logic/adapters/discord/discord_message_handler.py +207 -0
- ciris_engine/logic/adapters/discord/discord_observer.py +670 -0
- ciris_engine/logic/adapters/discord/discord_rate_limiter.py +249 -0
- ciris_engine/logic/adapters/discord/discord_reaction_handler.py +278 -0
- ciris_engine/logic/adapters/discord/discord_tool_handler.py +465 -0
- ciris_engine/logic/adapters/discord/discord_tool_service.py +790 -0
- ciris_engine/logic/adapters/discord/discord_tools.py +90 -0
- ciris_engine/logic/adapters/discord/discord_vision_helper.py +148 -0
- ciris_engine/logic/adapters/discord/py.typed +0 -0
- ciris_engine/logic/adapters/document_parser.py +320 -0
- ciris_engine/logic/audit/__init__.py +10 -0
- ciris_engine/logic/audit/hash_chain.py +313 -0
- ciris_engine/logic/audit/signature_manager.py +352 -0
- ciris_engine/logic/audit/verifier.py +408 -0
- ciris_engine/logic/buses/__init__.py +21 -0
- ciris_engine/logic/buses/base_bus.py +178 -0
- ciris_engine/logic/buses/bus_manager.py +121 -0
- ciris_engine/logic/buses/communication_bus.py +387 -0
- ciris_engine/logic/buses/llm_bus.py +722 -0
- ciris_engine/logic/buses/memory_bus.py +577 -0
- ciris_engine/logic/buses/prohibitions.py +502 -0
- ciris_engine/logic/buses/runtime_control_bus.py +539 -0
- ciris_engine/logic/buses/tool_bus.py +482 -0
- ciris_engine/logic/buses/wise_bus.py +684 -0
- ciris_engine/logic/config/__init__.py +25 -0
- ciris_engine/logic/config/bootstrap.py +255 -0
- ciris_engine/logic/config/config_accessor.py +202 -0
- ciris_engine/logic/config/db_paths.py +194 -0
- ciris_engine/logic/config/env_utils.py +39 -0
- ciris_engine/logic/conscience/__init__.py +16 -0
- ciris_engine/logic/conscience/build_deferral_package.py +0 -0
- ciris_engine/logic/conscience/core.py +688 -0
- ciris_engine/logic/conscience/interface.py +33 -0
- ciris_engine/logic/conscience/registry.py +76 -0
- ciris_engine/logic/conscience/thought_depth_guardrail.py +231 -0
- ciris_engine/logic/conscience/updated_status_conscience.py +156 -0
- ciris_engine/logic/context/__init__.py +10 -0
- ciris_engine/logic/context/batch_context.py +550 -0
- ciris_engine/logic/context/builder.py +149 -0
- ciris_engine/logic/context/channel_resolution.py +136 -0
- ciris_engine/logic/context/secrets_snapshot.py +52 -0
- ciris_engine/logic/context/system_snapshot.py +116 -0
- ciris_engine/logic/context/system_snapshot_helpers.py +1651 -0
- ciris_engine/logic/covenant/__init__.py +33 -0
- ciris_engine/logic/covenant/executor.py +303 -0
- ciris_engine/logic/covenant/extractor.py +382 -0
- ciris_engine/logic/covenant/handler.py +241 -0
- ciris_engine/logic/covenant/verifier.py +383 -0
- ciris_engine/logic/dma/__init__.py +15 -0
- ciris_engine/logic/dma/action_selection/__init__.py +11 -0
- ciris_engine/logic/dma/action_selection/action_instruction_generator.py +444 -0
- ciris_engine/logic/dma/action_selection/context_builder.py +508 -0
- ciris_engine/logic/dma/action_selection/faculty_integration.py +193 -0
- ciris_engine/logic/dma/action_selection/special_cases.py +132 -0
- ciris_engine/logic/dma/action_selection_pdma.py +365 -0
- ciris_engine/logic/dma/base_dma.py +335 -0
- ciris_engine/logic/dma/csdma.py +239 -0
- ciris_engine/logic/dma/dma_executor.py +575 -0
- ciris_engine/logic/dma/dsdma_base.py +410 -0
- ciris_engine/logic/dma/exceptions.py +4 -0
- ciris_engine/logic/dma/factory.py +150 -0
- ciris_engine/logic/dma/pdma.py +120 -0
- ciris_engine/logic/dma/prompt_loader.py +189 -0
- ciris_engine/logic/dma/prompts/action_selection_pdma.yml +58 -0
- ciris_engine/logic/dma/prompts/csdma_common_sense.yml +28 -0
- ciris_engine/logic/dma/prompts/dsdma_base.yml +17 -0
- ciris_engine/logic/dma/prompts/pdma_ethical.yml +42 -0
- ciris_engine/logic/formatters/__init__.py +26 -0
- ciris_engine/logic/formatters/crisis_resources.py +80 -0
- ciris_engine/logic/formatters/escalation.py +21 -0
- ciris_engine/logic/formatters/identity.py +224 -0
- ciris_engine/logic/formatters/prompt_blocks.py +64 -0
- ciris_engine/logic/formatters/system_snapshot.py +193 -0
- ciris_engine/logic/formatters/user_profiles.py +108 -0
- ciris_engine/logic/handlers/__init__.py +1 -0
- ciris_engine/logic/handlers/control/__init__.py +1 -0
- ciris_engine/logic/handlers/control/defer_handler.py +195 -0
- ciris_engine/logic/handlers/control/ponder_handler.py +154 -0
- ciris_engine/logic/handlers/control/reject_handler.py +81 -0
- ciris_engine/logic/handlers/external/__init__.py +1 -0
- ciris_engine/logic/handlers/external/observe_handler.py +154 -0
- ciris_engine/logic/handlers/external/speak_handler.py +250 -0
- ciris_engine/logic/handlers/external/tool_handler.py +148 -0
- ciris_engine/logic/handlers/memory/__init__.py +1 -0
- ciris_engine/logic/handlers/memory/forget_handler.py +107 -0
- ciris_engine/logic/handlers/memory/memorize_handler.py +391 -0
- ciris_engine/logic/handlers/memory/recall_handler.py +213 -0
- ciris_engine/logic/handlers/terminal/__init__.py +1 -0
- ciris_engine/logic/handlers/terminal/task_complete_handler.py +299 -0
- ciris_engine/logic/infrastructure/__init__.py +1 -0
- ciris_engine/logic/infrastructure/handlers/__init__.py +8 -0
- ciris_engine/logic/infrastructure/handlers/action_dispatcher.py +382 -0
- ciris_engine/logic/infrastructure/handlers/base_handler.py +450 -0
- ciris_engine/logic/infrastructure/handlers/exceptions.py +2 -0
- ciris_engine/logic/infrastructure/handlers/handler_registry.py +59 -0
- ciris_engine/logic/infrastructure/handlers/helpers.py +55 -0
- ciris_engine/logic/infrastructure/step_streaming.py +149 -0
- ciris_engine/logic/infrastructure/sub_services/__init__.py +1 -0
- ciris_engine/logic/infrastructure/sub_services/identity_variance_monitor.py +1035 -0
- ciris_engine/logic/infrastructure/sub_services/pattern_analysis_loop.py +758 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_bootstrap.py +229 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_display.py +176 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_oauth.py +404 -0
- ciris_engine/logic/infrastructure/sub_services/wa_cli_wizard.py +181 -0
- ciris_engine/logic/persistence/__init__.py +130 -0
- ciris_engine/logic/persistence/analytics.py +97 -0
- ciris_engine/logic/persistence/db/__init__.py +28 -0
- ciris_engine/logic/persistence/db/core.py +520 -0
- ciris_engine/logic/persistence/db/dialect.py +380 -0
- ciris_engine/logic/persistence/db/execution_helpers.py +216 -0
- ciris_engine/logic/persistence/db/migration_runner.py +191 -0
- ciris_engine/logic/persistence/db/operations.py +313 -0
- ciris_engine/logic/persistence/db/query_builder.py +232 -0
- ciris_engine/logic/persistence/db/retry.py +154 -0
- ciris_engine/logic/persistence/db/setup.py +18 -0
- ciris_engine/logic/persistence/migrations/postgres/001_initial_schema.sql +4 -0
- ciris_engine/logic/persistence/migrations/postgres/002_add_retry_status.sql +3 -0
- ciris_engine/logic/persistence/migrations/postgres/003_add_task_update_tracking.sql +8 -0
- ciris_engine/logic/persistence/migrations/postgres/004_add_occurrence_id.sql +54 -0
- ciris_engine/logic/persistence/migrations/postgres/005_add_consolidation_locks.sql +22 -0
- ciris_engine/logic/persistence/migrations/postgres/006_add_correlation_id_unique_index.sql +16 -0
- ciris_engine/logic/persistence/migrations/postgres/007_add_dsar_tickets.sql +39 -0
- ciris_engine/logic/persistence/migrations/postgres/008_rename_to_tickets_add_sop.sql +123 -0
- ciris_engine/logic/persistence/migrations/postgres/009_add_ticket_status_columns.sql +39 -0
- ciris_engine/logic/persistence/migrations/postgres/010_add_images_to_tasks.sql +5 -0
- ciris_engine/logic/persistence/migrations/sqlite/001_initial_schema.sql +357 -0
- ciris_engine/logic/persistence/migrations/sqlite/002_add_retry_status.sql +3 -0
- ciris_engine/logic/persistence/migrations/sqlite/003_add_task_update_tracking.sql +8 -0
- ciris_engine/logic/persistence/migrations/sqlite/004_add_occurrence_id.sql +45 -0
- ciris_engine/logic/persistence/migrations/sqlite/005_add_consolidation_locks.sql +22 -0
- ciris_engine/logic/persistence/migrations/sqlite/006_add_correlation_id_unique_index.sql +16 -0
- ciris_engine/logic/persistence/migrations/sqlite/007_add_dsar_tickets.sql +39 -0
- ciris_engine/logic/persistence/migrations/sqlite/008_rename_to_tickets_add_sop.sql +120 -0
- ciris_engine/logic/persistence/migrations/sqlite/009_add_ticket_status_columns.sql +129 -0
- ciris_engine/logic/persistence/migrations/sqlite/010_add_images_to_tasks.sql +17 -0
- ciris_engine/logic/persistence/models/__init__.py +141 -0
- ciris_engine/logic/persistence/models/correlations.py +881 -0
- ciris_engine/logic/persistence/models/deferral.py +68 -0
- ciris_engine/logic/persistence/models/dsar.py +286 -0
- ciris_engine/logic/persistence/models/graph.py +362 -0
- ciris_engine/logic/persistence/models/identity.py +264 -0
- ciris_engine/logic/persistence/models/queue_status.py +139 -0
- ciris_engine/logic/persistence/models/tasks.py +1043 -0
- ciris_engine/logic/persistence/models/thoughts.py +400 -0
- ciris_engine/logic/persistence/models/tickets.py +518 -0
- ciris_engine/logic/persistence/stores/__init__.py +13 -0
- ciris_engine/logic/persistence/stores/auth_helpers.py +117 -0
- ciris_engine/logic/persistence/stores/authentication_store.py +414 -0
- ciris_engine/logic/persistence/utils.py +212 -0
- ciris_engine/logic/processors/__init__.py +30 -0
- ciris_engine/logic/processors/core/__init__.py +1 -0
- ciris_engine/logic/processors/core/base_processor.py +280 -0
- ciris_engine/logic/processors/core/main_processor.py +1777 -0
- ciris_engine/logic/processors/core/step_decorators.py +1583 -0
- ciris_engine/logic/processors/core/thought_processor/__init__.py +20 -0
- ciris_engine/logic/processors/core/thought_processor/action_execution.py +49 -0
- ciris_engine/logic/processors/core/thought_processor/conscience_execution.py +382 -0
- ciris_engine/logic/processors/core/thought_processor/finalize_action.py +66 -0
- ciris_engine/logic/processors/core/thought_processor/gather_context.py +120 -0
- ciris_engine/logic/processors/core/thought_processor/main.py +920 -0
- ciris_engine/logic/processors/core/thought_processor/perform_aspdma.py +86 -0
- ciris_engine/logic/processors/core/thought_processor/perform_dmas.py +106 -0
- ciris_engine/logic/processors/core/thought_processor/recursive_processing.py +237 -0
- ciris_engine/logic/processors/core/thought_processor/round_complete.py +52 -0
- ciris_engine/logic/processors/core/thought_processor/start_round.py +64 -0
- ciris_engine/logic/processors/exceptions.py +59 -0
- ciris_engine/logic/processors/states/__init__.py +1 -0
- ciris_engine/logic/processors/states/dream_processor.py +1381 -0
- ciris_engine/logic/processors/states/play_processor.py +141 -0
- ciris_engine/logic/processors/states/shutdown_processor.py +623 -0
- ciris_engine/logic/processors/states/solitude_processor.py +305 -0
- ciris_engine/logic/processors/states/wakeup_processor.py +802 -0
- ciris_engine/logic/processors/states/work_processor.py +742 -0
- ciris_engine/logic/processors/support/__init__.py +1 -0
- ciris_engine/logic/processors/support/dma_orchestrator.py +336 -0
- ciris_engine/logic/processors/support/processing_queue.py +133 -0
- ciris_engine/logic/processors/support/shutdown_condition_evaluator.py +294 -0
- ciris_engine/logic/processors/support/state_manager.py +358 -0
- ciris_engine/logic/processors/support/task_manager.py +303 -0
- ciris_engine/logic/processors/support/thought_escalation.py +116 -0
- ciris_engine/logic/processors/support/thought_manager.py +328 -0
- ciris_engine/logic/processors/support/thought_manager_enhanced.py +105 -0
- ciris_engine/logic/registries/__init__.py +34 -0
- ciris_engine/logic/registries/base.py +653 -0
- ciris_engine/logic/registries/circuit_breaker.py +275 -0
- ciris_engine/logic/registries/typed_registries.py +184 -0
- ciris_engine/logic/runtime/__init__.py +7 -0
- ciris_engine/logic/runtime/adapter_loader.py +261 -0
- ciris_engine/logic/runtime/adapter_manager.py +1053 -0
- ciris_engine/logic/runtime/ciris_runtime.py +2342 -0
- ciris_engine/logic/runtime/ciris_runtime_helpers.py +923 -0
- ciris_engine/logic/runtime/component_builder.py +361 -0
- ciris_engine/logic/runtime/identity_manager.py +219 -0
- ciris_engine/logic/runtime/module_loader.py +207 -0
- ciris_engine/logic/runtime/prevent_sideeffects.py +30 -0
- ciris_engine/logic/runtime/runtime_interface.py +23 -0
- ciris_engine/logic/runtime/service_initializer.py +1623 -0
- ciris_engine/logic/secrets/__init__.py +30 -0
- ciris_engine/logic/secrets/encryption.py +175 -0
- ciris_engine/logic/secrets/filter.py +295 -0
- ciris_engine/logic/secrets/service.py +652 -0
- ciris_engine/logic/secrets/store.py +669 -0
- ciris_engine/logic/services/__init__.py +1 -0
- ciris_engine/logic/services/adaptation/__init__.py +3 -0
- ciris_engine/logic/services/base_graph_service.py +142 -0
- ciris_engine/logic/services/base_infrastructure_service.py +69 -0
- ciris_engine/logic/services/base_scheduled_service.py +136 -0
- ciris_engine/logic/services/base_service.py +247 -0
- ciris_engine/logic/services/governance/__init__.py +3 -0
- ciris_engine/logic/services/governance/adaptive_filter/__init__.py +14 -0
- ciris_engine/logic/services/governance/adaptive_filter/service.py +818 -0
- ciris_engine/logic/services/governance/consent/__init__.py +53 -0
- ciris_engine/logic/services/governance/consent/air.py +403 -0
- ciris_engine/logic/services/governance/consent/decay.py +324 -0
- ciris_engine/logic/services/governance/consent/dsar_automation.py +589 -0
- ciris_engine/logic/services/governance/consent/exceptions.py +106 -0
- ciris_engine/logic/services/governance/consent/metrics.py +270 -0
- ciris_engine/logic/services/governance/consent/partnership.py +533 -0
- ciris_engine/logic/services/governance/consent/service.py +1256 -0
- ciris_engine/logic/services/governance/dsar/__init__.py +29 -0
- ciris_engine/logic/services/governance/dsar/orchestrator.py +977 -0
- ciris_engine/logic/services/governance/dsar/schemas.py +141 -0
- ciris_engine/logic/services/governance/dsar/signature_service.py +283 -0
- ciris_engine/logic/services/governance/self_observation/__init__.py +20 -0
- ciris_engine/logic/services/governance/self_observation/service.py +1153 -0
- ciris_engine/logic/services/governance/visibility/__init__.py +17 -0
- ciris_engine/logic/services/governance/visibility/service.py +512 -0
- ciris_engine/logic/services/governance/wise_authority/__init__.py +15 -0
- ciris_engine/logic/services/governance/wise_authority/service.py +827 -0
- ciris_engine/logic/services/graph/__init__.py +5 -0
- ciris_engine/logic/services/graph/audit_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/audit_service/service.py +1675 -0
- ciris_engine/logic/services/graph/base.py +208 -0
- ciris_engine/logic/services/graph/config_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/config_service/service.py +372 -0
- ciris_engine/logic/services/graph/incident_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/incident_service/service.py +803 -0
- ciris_engine/logic/services/graph/memory_service.py +1120 -0
- ciris_engine/logic/services/graph/telemetry_service/__init__.py +5 -0
- ciris_engine/logic/services/graph/telemetry_service/exceptions.py +104 -0
- ciris_engine/logic/services/graph/telemetry_service/helpers.py +1337 -0
- ciris_engine/logic/services/graph/telemetry_service/service.py +2429 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/__init__.py +17 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/aggregation_helpers.py +355 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/cleanup_helpers.py +438 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/compressor.py +260 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/__init__.py +27 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/audit.py +326 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/conversation.py +291 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/memory.py +197 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/metrics.py +251 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/task.py +257 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/consolidators/trace.py +363 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/data_converter.py +545 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/date_calculation_helpers.py +193 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/db_query_helpers.py +296 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/edge_helpers.py +92 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/edge_manager.py +896 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/extensive_helpers.py +322 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/period_manager.py +152 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/profound_helpers.py +277 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/query_manager.py +812 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/service.py +1692 -0
- ciris_engine/logic/services/graph/tsdb_consolidation/sql_builders.py +363 -0
- ciris_engine/logic/services/infrastructure/__init__.py +1 -0
- ciris_engine/logic/services/infrastructure/authentication/__init__.py +5 -0
- ciris_engine/logic/services/infrastructure/authentication/service.py +1634 -0
- ciris_engine/logic/services/infrastructure/database_maintenance/__init__.py +15 -0
- ciris_engine/logic/services/infrastructure/database_maintenance/service.py +764 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/__init__.py +7 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/ciris_billing_provider.py +755 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/service.py +409 -0
- ciris_engine/logic/services/infrastructure/resource_monitor/simple_credit_provider.py +129 -0
- ciris_engine/logic/services/lifecycle/__init__.py +3 -0
- ciris_engine/logic/services/lifecycle/initialization/__init__.py +10 -0
- ciris_engine/logic/services/lifecycle/initialization/service.py +312 -0
- ciris_engine/logic/services/lifecycle/scheduler/__init__.py +5 -0
- ciris_engine/logic/services/lifecycle/scheduler/service.py +607 -0
- ciris_engine/logic/services/lifecycle/shutdown/__init__.py +9 -0
- ciris_engine/logic/services/lifecycle/shutdown/service.py +378 -0
- ciris_engine/logic/services/lifecycle/time/__init__.py +15 -0
- ciris_engine/logic/services/lifecycle/time/service.py +259 -0
- ciris_engine/logic/services/memory_service/__init__.py +8 -0
- ciris_engine/logic/services/mixins/__init__.py +13 -0
- ciris_engine/logic/services/mixins/example_usage.py +200 -0
- ciris_engine/logic/services/mixins/request_metrics.py +179 -0
- ciris_engine/logic/services/runtime/__init__.py +3 -0
- ciris_engine/logic/services/runtime/adapter_configuration/__init__.py +16 -0
- ciris_engine/logic/services/runtime/adapter_configuration/service.py +674 -0
- ciris_engine/logic/services/runtime/adapter_configuration/session.py +67 -0
- ciris_engine/logic/services/runtime/control_service/__init__.py +5 -0
- ciris_engine/logic/services/runtime/control_service/service.py +2269 -0
- ciris_engine/logic/services/runtime/llm_service/__init__.py +14 -0
- ciris_engine/logic/services/runtime/llm_service/pricing_calculator.py +279 -0
- ciris_engine/logic/services/runtime/llm_service/service.py +930 -0
- ciris_engine/logic/services/tools/__init__.py +5 -0
- ciris_engine/logic/services/tools/core_tool_service/__init__.py +8 -0
- ciris_engine/logic/services/tools/core_tool_service/service.py +852 -0
- ciris_engine/logic/setup/__init__.py +1 -0
- ciris_engine/logic/setup/first_run.py +250 -0
- ciris_engine/logic/setup/wizard.py +327 -0
- ciris_engine/logic/telemetry/__init__.py +46 -0
- ciris_engine/logic/telemetry/core.py +239 -0
- ciris_engine/logic/telemetry/hot_cold_config.py +133 -0
- ciris_engine/logic/telemetry/log_collector.py +190 -0
- ciris_engine/logic/telemetry/resource_monitor.py +7 -0
- ciris_engine/logic/telemetry/security.py +79 -0
- ciris_engine/logic/utils/__init__.py +18 -0
- ciris_engine/logic/utils/channel_utils.py +75 -0
- ciris_engine/logic/utils/consent/__init__.py +1 -0
- ciris_engine/logic/utils/consent/partnership_utils.py +172 -0
- ciris_engine/logic/utils/constants.py +92 -0
- ciris_engine/logic/utils/context_utils.py +145 -0
- ciris_engine/logic/utils/directory_setup.py +533 -0
- ciris_engine/logic/utils/graphql_context_provider.py +152 -0
- ciris_engine/logic/utils/identity_resolution.py +843 -0
- ciris_engine/logic/utils/incident_capture_handler.py +303 -0
- ciris_engine/logic/utils/initialization_manager.py +74 -0
- ciris_engine/logic/utils/jsondict_helpers.py +290 -0
- ciris_engine/logic/utils/log_sanitizer.py +97 -0
- ciris_engine/logic/utils/logging_config.py +151 -0
- ciris_engine/logic/utils/observability_decorators.py +544 -0
- ciris_engine/logic/utils/occurrence_utils.py +155 -0
- ciris_engine/logic/utils/path_resolution.py +281 -0
- ciris_engine/logic/utils/platform_detection.py +286 -0
- ciris_engine/logic/utils/privacy.py +266 -0
- ciris_engine/logic/utils/profile_loader.py +124 -0
- ciris_engine/logic/utils/profile_manager.py +16 -0
- ciris_engine/logic/utils/runtime_utils.py +69 -0
- ciris_engine/logic/utils/shutdown_manager.py +107 -0
- ciris_engine/logic/utils/task_formatters.py +60 -0
- ciris_engine/logic/utils/task_thought_factory.py +404 -0
- ciris_engine/logic/utils/thought_utils.py +54 -0
- ciris_engine/logic/utils/user_utils.py +70 -0
- ciris_engine/protocols/__init__.py +0 -0
- ciris_engine/protocols/adapters/__init__.py +35 -0
- ciris_engine/protocols/adapters/base.py +149 -0
- ciris_engine/protocols/adapters/configurable.py +265 -0
- ciris_engine/protocols/adapters/message.py +90 -0
- ciris_engine/protocols/audit/__init__.py +1 -0
- ciris_engine/protocols/buses/__init__.py +1 -0
- ciris_engine/protocols/config/__init__.py +1 -0
- ciris_engine/protocols/conscience/__init__.py +1 -0
- ciris_engine/protocols/consent.py +88 -0
- ciris_engine/protocols/context/__init__.py +1 -0
- ciris_engine/protocols/data/__init__.py +1 -0
- ciris_engine/protocols/dma/__init__.py +1 -0
- ciris_engine/protocols/dma/base.py +107 -0
- ciris_engine/protocols/faculties.py +34 -0
- ciris_engine/protocols/formatters/__init__.py +1 -0
- ciris_engine/protocols/handlers/__init__.py +1 -0
- ciris_engine/protocols/infrastructure/__init__.py +25 -0
- ciris_engine/protocols/infrastructure/base.py +377 -0
- ciris_engine/protocols/persistence/__init__.py +1 -0
- ciris_engine/protocols/pipeline_control.py +609 -0
- ciris_engine/protocols/processors/__init__.py +19 -0
- ciris_engine/protocols/processors/agent.py +299 -0
- ciris_engine/protocols/processors/base.py +130 -0
- ciris_engine/protocols/processors/orchestration.py +62 -0
- ciris_engine/protocols/registries/__init__.py +1 -0
- ciris_engine/protocols/runtime/__init__.py +1 -0
- ciris_engine/protocols/runtime/base.py +163 -0
- ciris_engine/protocols/secrets/__init__.py +1 -0
- ciris_engine/protocols/services/__init__.py +80 -0
- ciris_engine/protocols/services/adaptation/__init__.py +7 -0
- ciris_engine/protocols/services/adaptation/self_observation.py +265 -0
- ciris_engine/protocols/services/governance/__init__.py +20 -0
- ciris_engine/protocols/services/governance/communication.py +58 -0
- ciris_engine/protocols/services/governance/filter.py +56 -0
- ciris_engine/protocols/services/governance/visibility.py +32 -0
- ciris_engine/protocols/services/governance/wa_auth.py +192 -0
- ciris_engine/protocols/services/governance/wise_authority.py +75 -0
- ciris_engine/protocols/services/graph/__init__.py +19 -0
- ciris_engine/protocols/services/graph/audit.py +92 -0
- ciris_engine/protocols/services/graph/config.py +54 -0
- ciris_engine/protocols/services/graph/incident_management.py +103 -0
- ciris_engine/protocols/services/graph/memory.py +110 -0
- ciris_engine/protocols/services/graph/telemetry.py +51 -0
- ciris_engine/protocols/services/graph/tsdb_consolidation.py +87 -0
- ciris_engine/protocols/services/infrastructure/__init__.py +11 -0
- ciris_engine/protocols/services/infrastructure/authentication.py +159 -0
- ciris_engine/protocols/services/infrastructure/credit_gate.py +46 -0
- ciris_engine/protocols/services/infrastructure/database_maintenance.py +25 -0
- ciris_engine/protocols/services/infrastructure/resource_monitor.py +83 -0
- ciris_engine/protocols/services/lifecycle/__init__.py +13 -0
- ciris_engine/protocols/services/lifecycle/initialization.py +41 -0
- ciris_engine/protocols/services/lifecycle/scheduler.py +42 -0
- ciris_engine/protocols/services/lifecycle/shutdown.py +50 -0
- ciris_engine/protocols/services/lifecycle/time.py +31 -0
- ciris_engine/protocols/services/runtime/__init__.py +13 -0
- ciris_engine/protocols/services/runtime/llm.py +50 -0
- ciris_engine/protocols/services/runtime/runtime_control.py +193 -0
- ciris_engine/protocols/services/runtime/secrets.py +100 -0
- ciris_engine/protocols/services/runtime/tool.py +123 -0
- ciris_engine/protocols/telemetry/__init__.py +1 -0
- ciris_engine/protocols/utils/__init__.py +1 -0
- ciris_engine/schemas/__init__.py +112 -0
- ciris_engine/schemas/actions/__init__.py +37 -0
- ciris_engine/schemas/actions/parameters.py +137 -0
- ciris_engine/schemas/adapters/__init__.py +13 -0
- ciris_engine/schemas/adapters/cirisnode.py +135 -0
- ciris_engine/schemas/adapters/cli.py +97 -0
- ciris_engine/schemas/adapters/cli_tools.py +98 -0
- ciris_engine/schemas/adapters/discord.py +125 -0
- ciris_engine/schemas/adapters/graphql_core.py +144 -0
- ciris_engine/schemas/adapters/registration.py +47 -0
- ciris_engine/schemas/adapters/runtime_context.py +48 -0
- ciris_engine/schemas/adapters/tool_execution.py +45 -0
- ciris_engine/schemas/adapters/tools.py +96 -0
- ciris_engine/schemas/api/__init__.py +1 -0
- ciris_engine/schemas/api/agent.py +50 -0
- ciris_engine/schemas/api/audit.py +38 -0
- ciris_engine/schemas/api/auth.py +351 -0
- ciris_engine/schemas/api/config_security.py +242 -0
- ciris_engine/schemas/api/emergency.py +111 -0
- ciris_engine/schemas/api/responses.py +72 -0
- ciris_engine/schemas/api/runtime.py +26 -0
- ciris_engine/schemas/api/telemetry.py +109 -0
- ciris_engine/schemas/api/wa.py +90 -0
- ciris_engine/schemas/audit/__init__.py +13 -0
- ciris_engine/schemas/audit/core.py +139 -0
- ciris_engine/schemas/audit/hash_chain.py +58 -0
- ciris_engine/schemas/audit/verification.py +131 -0
- ciris_engine/schemas/buses/__init__.py +1 -0
- ciris_engine/schemas/config/__init__.py +41 -0
- ciris_engine/schemas/config/agent.py +279 -0
- ciris_engine/schemas/config/cognitive_state_behaviors.py +194 -0
- ciris_engine/schemas/config/default_dsar_sops.py +178 -0
- ciris_engine/schemas/config/essential.py +195 -0
- ciris_engine/schemas/config/tickets.py +86 -0
- ciris_engine/schemas/conscience/__init__.py +25 -0
- ciris_engine/schemas/conscience/context.py +34 -0
- ciris_engine/schemas/conscience/core.py +145 -0
- ciris_engine/schemas/conscience/results.py +24 -0
- ciris_engine/schemas/consent/__init__.py +5 -0
- ciris_engine/schemas/consent/core.py +404 -0
- ciris_engine/schemas/context/__init__.py +1 -0
- ciris_engine/schemas/covenant.py +382 -0
- ciris_engine/schemas/data/__init__.py +1 -0
- ciris_engine/schemas/dma/__init__.py +16 -0
- ciris_engine/schemas/dma/core.py +199 -0
- ciris_engine/schemas/dma/faculty.py +192 -0
- ciris_engine/schemas/dma/prompts.py +172 -0
- ciris_engine/schemas/dma/results.py +103 -0
- ciris_engine/schemas/formatters/__init__.py +1 -0
- ciris_engine/schemas/handlers/__init__.py +10 -0
- ciris_engine/schemas/handlers/context.py +119 -0
- ciris_engine/schemas/handlers/contexts.py +100 -0
- ciris_engine/schemas/handlers/core.py +167 -0
- ciris_engine/schemas/handlers/memory_schemas.py +67 -0
- ciris_engine/schemas/handlers/schemas.py +95 -0
- ciris_engine/schemas/identity.py +149 -0
- ciris_engine/schemas/infrastructure/__init__.py +1 -0
- ciris_engine/schemas/infrastructure/base.py +256 -0
- ciris_engine/schemas/infrastructure/behavioral_patterns.py +129 -0
- ciris_engine/schemas/infrastructure/feedback_loop.py +57 -0
- ciris_engine/schemas/infrastructure/identity_variance.py +141 -0
- ciris_engine/schemas/infrastructure/oauth.py +175 -0
- ciris_engine/schemas/infrastructure/wa_cli_wizard.py +54 -0
- ciris_engine/schemas/persistence/__init__.py +34 -0
- ciris_engine/schemas/persistence/core.py +140 -0
- ciris_engine/schemas/persistence/correlations.py +73 -0
- ciris_engine/schemas/persistence/postgres/__init__.py +1 -0
- ciris_engine/schemas/persistence/postgres/tables.py +280 -0
- ciris_engine/schemas/persistence/sqlite/__init__.py +1 -0
- ciris_engine/schemas/persistence/sqlite/tables.py +281 -0
- ciris_engine/schemas/platform.py +149 -0
- ciris_engine/schemas/processors/__init__.py +26 -0
- ciris_engine/schemas/processors/base.py +130 -0
- ciris_engine/schemas/processors/cognitive.py +77 -0
- ciris_engine/schemas/processors/context.py +35 -0
- ciris_engine/schemas/processors/core.py +152 -0
- ciris_engine/schemas/processors/dma.py +105 -0
- ciris_engine/schemas/processors/error.py +122 -0
- ciris_engine/schemas/processors/main.py +109 -0
- ciris_engine/schemas/processors/phase_results.py +21 -0
- ciris_engine/schemas/processors/results.py +99 -0
- ciris_engine/schemas/processors/solitude.py +79 -0
- ciris_engine/schemas/processors/state.py +202 -0
- ciris_engine/schemas/processors/state_example.py +177 -0
- ciris_engine/schemas/processors/states.py +21 -0
- ciris_engine/schemas/processors/status.py +34 -0
- ciris_engine/schemas/registries/__init__.py +1 -0
- ciris_engine/schemas/registries/base.py +66 -0
- ciris_engine/schemas/resources/__init__.py +15 -0
- ciris_engine/schemas/resources/crisis.py +315 -0
- ciris_engine/schemas/runtime/__init__.py +42 -0
- ciris_engine/schemas/runtime/adapter_management.py +186 -0
- ciris_engine/schemas/runtime/api.py +58 -0
- ciris_engine/schemas/runtime/audit.py +50 -0
- ciris_engine/schemas/runtime/bootstrap.py +33 -0
- ciris_engine/schemas/runtime/contexts.py +61 -0
- ciris_engine/schemas/runtime/core.py +161 -0
- ciris_engine/schemas/runtime/enums.py +167 -0
- ciris_engine/schemas/runtime/extended.py +232 -0
- ciris_engine/schemas/runtime/manifest.py +311 -0
- ciris_engine/schemas/runtime/memory.py +60 -0
- ciris_engine/schemas/runtime/messages.py +108 -0
- ciris_engine/schemas/runtime/models.py +156 -0
- ciris_engine/schemas/runtime/processing_context.py +43 -0
- ciris_engine/schemas/runtime/protocols_core.py +96 -0
- ciris_engine/schemas/runtime/resources.py +33 -0
- ciris_engine/schemas/runtime/system_context.py +417 -0
- ciris_engine/schemas/secrets/__init__.py +1 -0
- ciris_engine/schemas/secrets/core.py +267 -0
- ciris_engine/schemas/secrets/service.py +95 -0
- ciris_engine/schemas/services/__init__.py +33 -0
- ciris_engine/schemas/services/audit_summary_node.py +172 -0
- ciris_engine/schemas/services/authority/__init__.py +39 -0
- ciris_engine/schemas/services/authority/jwt.py +158 -0
- ciris_engine/schemas/services/authority/wa_updates.py +138 -0
- ciris_engine/schemas/services/authority/wise_authority.py +163 -0
- ciris_engine/schemas/services/authority_core.py +370 -0
- ciris_engine/schemas/services/capabilities.py +72 -0
- ciris_engine/schemas/services/community_core.py +95 -0
- ciris_engine/schemas/services/context.py +111 -0
- ciris_engine/schemas/services/conversation_summary_node.py +189 -0
- ciris_engine/schemas/services/core/__init__.py +153 -0
- ciris_engine/schemas/services/core/runtime.py +262 -0
- ciris_engine/schemas/services/core/runtime_config.py +117 -0
- ciris_engine/schemas/services/core/secrets.py +65 -0
- ciris_engine/schemas/services/correlation_node.py +179 -0
- ciris_engine/schemas/services/credit_gate.py +92 -0
- ciris_engine/schemas/services/discord_nodes.py +299 -0
- ciris_engine/schemas/services/feedback_core.py +131 -0
- ciris_engine/schemas/services/filters_core.py +270 -0
- ciris_engine/schemas/services/governance.py +26 -0
- ciris_engine/schemas/services/graph/__init__.py +26 -0
- ciris_engine/schemas/services/graph/attributes.py +254 -0
- ciris_engine/schemas/services/graph/audit.py +98 -0
- ciris_engine/schemas/services/graph/consolidation.py +338 -0
- ciris_engine/schemas/services/graph/edge_types.py +43 -0
- ciris_engine/schemas/services/graph/edges.py +88 -0
- ciris_engine/schemas/services/graph/incident.py +312 -0
- ciris_engine/schemas/services/graph/memory.py +84 -0
- ciris_engine/schemas/services/graph/node_data.py +174 -0
- ciris_engine/schemas/services/graph/query_results.py +82 -0
- ciris_engine/schemas/services/graph/telemetry.py +250 -0
- ciris_engine/schemas/services/graph/tsdb_consolidation.py +27 -0
- ciris_engine/schemas/services/graph/tsdb_models.py +107 -0
- ciris_engine/schemas/services/graph_core.py +196 -0
- ciris_engine/schemas/services/graph_typed_nodes.py +194 -0
- ciris_engine/schemas/services/infrastructure/__init__.py +1 -0
- ciris_engine/schemas/services/infrastructure/resource_monitor.py +20 -0
- ciris_engine/schemas/services/lifecycle/__init__.py +9 -0
- ciris_engine/schemas/services/lifecycle/initialization.py +33 -0
- ciris_engine/schemas/services/lifecycle/time.py +50 -0
- ciris_engine/schemas/services/llm.py +187 -0
- ciris_engine/schemas/services/metadata.py +43 -0
- ciris_engine/schemas/services/nodes.py +704 -0
- ciris_engine/schemas/services/operations.py +126 -0
- ciris_engine/schemas/services/requests.py +128 -0
- ciris_engine/schemas/services/resources_core.py +182 -0
- ciris_engine/schemas/services/runtime_control.py +1010 -0
- ciris_engine/schemas/services/shutdown.py +88 -0
- ciris_engine/schemas/services/special/__init__.py +0 -0
- ciris_engine/schemas/services/special/self_observation.py +396 -0
- ciris_engine/schemas/services/trace_summary_node.py +199 -0
- ciris_engine/schemas/services/visibility.py +98 -0
- ciris_engine/schemas/streaming/__init__.py +10 -0
- ciris_engine/schemas/streaming/reasoning_stream.py +95 -0
- ciris_engine/schemas/telemetry/__init__.py +0 -0
- ciris_engine/schemas/telemetry/collector.py +67 -0
- ciris_engine/schemas/telemetry/core.py +252 -0
- ciris_engine/schemas/telemetry/unified.py +59 -0
- ciris_engine/schemas/tools.py +72 -0
- ciris_engine/schemas/types.py +47 -0
- ciris_engine/schemas/utils/__init__.py +1 -0
- ciris_engine/schemas/utils/config_validator.py +54 -0
- ciris_engine/utils/__init__.py +1 -0
- ciris_engine/utils/serialization.py +35 -0
- ciris_sdk/__init__.py +124 -0
- ciris_sdk/auth_store.py +261 -0
- ciris_sdk/client.py +261 -0
- ciris_sdk/exceptions.py +73 -0
- ciris_sdk/model_types.py +258 -0
- ciris_sdk/models.py +354 -0
- ciris_sdk/pagination.py +214 -0
- ciris_sdk/rate_limiter.py +188 -0
- ciris_sdk/setup.py +17 -0
- ciris_sdk/telemetry_models.py +257 -0
- ciris_sdk/telemetry_responses.py +199 -0
- ciris_sdk/transport.py +177 -0
- ciris_sdk/websocket.py +400 -0
- main.py +766 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication dependencies for FastAPI routes.
|
|
3
|
+
|
|
4
|
+
Provides role-based access control through dependency injection.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Any, Callable, Optional, Set
|
|
9
|
+
|
|
10
|
+
from fastapi import Depends, Header, HTTPException, Request, status
|
|
11
|
+
|
|
12
|
+
from ciris_engine.schemas.api.auth import ROLE_PERMISSIONS, APIKeyInfo, AuthContext, UserInfo, UserRole
|
|
13
|
+
|
|
14
|
+
from ..services.auth_service import APIAuthService
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AuthContext",
|
|
18
|
+
"get_auth_service",
|
|
19
|
+
"require_admin",
|
|
20
|
+
"require_observer",
|
|
21
|
+
"require_authenticated",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_auth_service(request: Request) -> APIAuthService:
|
|
26
|
+
"""Get auth service from app state."""
|
|
27
|
+
if not hasattr(request.app.state, "auth_service"):
|
|
28
|
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Auth service not initialized")
|
|
29
|
+
auth_service = request.app.state.auth_service
|
|
30
|
+
if not isinstance(auth_service, APIAuthService):
|
|
31
|
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Invalid auth service type")
|
|
32
|
+
return auth_service
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _extract_bearer_token(authorization: Optional[str]) -> str:
|
|
36
|
+
"""Extract and validate bearer token from authorization header."""
|
|
37
|
+
if not authorization:
|
|
38
|
+
raise HTTPException(
|
|
39
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
40
|
+
detail="Missing authorization header",
|
|
41
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if not authorization.startswith("Bearer "):
|
|
45
|
+
raise HTTPException(
|
|
46
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
47
|
+
detail="Invalid authorization format",
|
|
48
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return authorization[7:] # Remove "Bearer " prefix
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _handle_service_token_auth(request: Request, auth_service: APIAuthService, service_token: str) -> AuthContext:
|
|
55
|
+
"""Handle service token authentication."""
|
|
56
|
+
service_user = auth_service.validate_service_token(service_token)
|
|
57
|
+
if not service_user:
|
|
58
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid service token")
|
|
59
|
+
|
|
60
|
+
# Service token authentication successful
|
|
61
|
+
# NOTE: We do not audit successful service token auth to avoid log spam
|
|
62
|
+
# Service tokens are used frequently by the manager and other services
|
|
63
|
+
# Only failed attempts are audited for security monitoring
|
|
64
|
+
|
|
65
|
+
from ciris_engine.schemas.api.auth import UserRole as AuthUserRole
|
|
66
|
+
|
|
67
|
+
context = AuthContext(
|
|
68
|
+
user_id=service_user.wa_id,
|
|
69
|
+
role=AuthUserRole.SERVICE_ACCOUNT,
|
|
70
|
+
permissions=ROLE_PERMISSIONS.get(AuthUserRole.SERVICE_ACCOUNT, set()),
|
|
71
|
+
api_key_id=None,
|
|
72
|
+
authenticated_at=datetime.now(timezone.utc),
|
|
73
|
+
)
|
|
74
|
+
context.request = request
|
|
75
|
+
return context
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def _handle_password_auth(request: Request, auth_service: APIAuthService, api_key: str) -> AuthContext:
|
|
79
|
+
"""Handle username:password authentication."""
|
|
80
|
+
username, password = api_key.split(":", 1)
|
|
81
|
+
user = await auth_service.verify_user_password(username, password)
|
|
82
|
+
if not user:
|
|
83
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid username or password")
|
|
84
|
+
|
|
85
|
+
from ciris_engine.schemas.api.auth import UserRole as AuthUserRole
|
|
86
|
+
|
|
87
|
+
# Map APIRole to UserRole
|
|
88
|
+
user_role = AuthUserRole[user.api_role.value]
|
|
89
|
+
context = AuthContext(
|
|
90
|
+
user_id=user.wa_id,
|
|
91
|
+
role=user_role,
|
|
92
|
+
permissions=ROLE_PERMISSIONS.get(user_role, set()),
|
|
93
|
+
api_key_id=None,
|
|
94
|
+
authenticated_at=datetime.now(timezone.utc),
|
|
95
|
+
)
|
|
96
|
+
context.request = request
|
|
97
|
+
return context
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _build_permissions_set(key_info: Any, user: Any) -> Set[Any]:
|
|
101
|
+
"""Build permissions set from role and custom permissions."""
|
|
102
|
+
permissions = set(ROLE_PERMISSIONS.get(key_info.role, set()))
|
|
103
|
+
|
|
104
|
+
# Add any custom permissions if user exists and has them
|
|
105
|
+
if user and hasattr(user, "custom_permissions") and user.custom_permissions:
|
|
106
|
+
from ciris_engine.schemas.api.auth import Permission
|
|
107
|
+
|
|
108
|
+
for perm in user.custom_permissions:
|
|
109
|
+
# Convert string to Permission enum if it's a valid permission
|
|
110
|
+
try:
|
|
111
|
+
permissions.add(Permission(perm))
|
|
112
|
+
except ValueError:
|
|
113
|
+
# Skip invalid permission strings
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
return permissions
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _handle_api_key_auth(request: Request, auth_service: APIAuthService, api_key: str) -> AuthContext:
|
|
120
|
+
"""Handle regular API key authentication."""
|
|
121
|
+
key_info = auth_service.validate_api_key(api_key)
|
|
122
|
+
if not key_info:
|
|
123
|
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API key")
|
|
124
|
+
|
|
125
|
+
# Get user to check for custom permissions
|
|
126
|
+
user = auth_service.get_user(key_info.user_id)
|
|
127
|
+
|
|
128
|
+
# Build permissions set
|
|
129
|
+
permissions = _build_permissions_set(key_info, user)
|
|
130
|
+
|
|
131
|
+
# Create auth context with request reference
|
|
132
|
+
context = AuthContext(
|
|
133
|
+
user_id=key_info.user_id,
|
|
134
|
+
role=key_info.role,
|
|
135
|
+
permissions=permissions,
|
|
136
|
+
api_key_id=auth_service._get_key_id(api_key),
|
|
137
|
+
authenticated_at=datetime.now(timezone.utc),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Attach request to context for service access in routes
|
|
141
|
+
context.request = request
|
|
142
|
+
return context
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
async def get_auth_context( # NOSONAR: FastAPI requires async for dependency injection
|
|
146
|
+
request: Request,
|
|
147
|
+
authorization: Optional[str] = Header(None),
|
|
148
|
+
auth_service: APIAuthService = Depends(get_auth_service),
|
|
149
|
+
) -> AuthContext:
|
|
150
|
+
"""Extract and validate authentication from request."""
|
|
151
|
+
api_key = _extract_bearer_token(authorization)
|
|
152
|
+
|
|
153
|
+
# Check if this is a service token
|
|
154
|
+
if api_key.startswith("service:"):
|
|
155
|
+
service_token = api_key[8:] # Remove "service:" prefix
|
|
156
|
+
return _handle_service_token_auth(request, auth_service, service_token)
|
|
157
|
+
|
|
158
|
+
# Check if this is username:password format (for legacy support)
|
|
159
|
+
if ":" in api_key:
|
|
160
|
+
return await _handle_password_auth(request, auth_service, api_key)
|
|
161
|
+
|
|
162
|
+
# Otherwise, validate as regular API key
|
|
163
|
+
return _handle_api_key_auth(request, auth_service, api_key)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
async def optional_auth(
|
|
167
|
+
request: Request,
|
|
168
|
+
authorization: Optional[str] = Header(None),
|
|
169
|
+
auth_service: APIAuthService = Depends(get_auth_service),
|
|
170
|
+
) -> Optional[AuthContext]:
|
|
171
|
+
"""Optional authentication - returns None if no auth provided."""
|
|
172
|
+
if not authorization:
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
return await get_auth_context(request, authorization, auth_service)
|
|
177
|
+
except HTTPException:
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def require_role(minimum_role: UserRole) -> Callable[..., AuthContext]:
|
|
182
|
+
"""
|
|
183
|
+
Factory for role-based access control dependencies.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
minimum_role: Minimum role required for access
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Dependency function that validates role
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
def check_role(auth: AuthContext = Depends(get_auth_context)) -> AuthContext:
|
|
193
|
+
"""Validate user has required role."""
|
|
194
|
+
if not auth.role.has_permission(minimum_role):
|
|
195
|
+
raise HTTPException(
|
|
196
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
197
|
+
detail=f"Insufficient permissions. Requires {minimum_role.value} role or higher.",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
return auth
|
|
201
|
+
|
|
202
|
+
# Set function name for better error messages
|
|
203
|
+
check_role.__name__ = f"require_{minimum_role.value.lower()}"
|
|
204
|
+
return check_role
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# Convenience dependencies for common roles
|
|
208
|
+
require_authenticated = get_auth_context # Alias for basic authentication
|
|
209
|
+
require_observer = require_role(UserRole.OBSERVER)
|
|
210
|
+
require_admin = require_role(UserRole.ADMIN)
|
|
211
|
+
require_authority = require_role(UserRole.AUTHORITY)
|
|
212
|
+
require_system_admin = require_role(UserRole.SYSTEM_ADMIN)
|
|
213
|
+
require_service_account = require_role(UserRole.SERVICE_ACCOUNT)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def check_permissions(permissions: list[str]) -> Callable[..., Any]:
|
|
217
|
+
"""
|
|
218
|
+
Factory for permission-based access control dependencies.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
permissions: List of required permissions
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Dependency function that validates permissions
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
async def check( # NOSONAR: FastAPI requires async for dependency injection
|
|
228
|
+
auth: AuthContext = Depends(get_auth_context), auth_service: APIAuthService = Depends(get_auth_service)
|
|
229
|
+
) -> None:
|
|
230
|
+
"""Validate user has required permissions."""
|
|
231
|
+
from ciris_engine.schemas.runtime.api import APIRole
|
|
232
|
+
from ciris_engine.schemas.services.authority_core import WARole
|
|
233
|
+
|
|
234
|
+
# Get the user from auth service to get their API role
|
|
235
|
+
user = auth_service.get_user(auth.user_id)
|
|
236
|
+
if not user:
|
|
237
|
+
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="User not found")
|
|
238
|
+
|
|
239
|
+
# Get permissions for user's API role
|
|
240
|
+
user_permissions = set(auth_service.get_permissions_for_role(user.api_role))
|
|
241
|
+
|
|
242
|
+
# ROOT WA role inherits AUTHORITY permissions (for deferral resolution, etc.)
|
|
243
|
+
# This is separate from API role - ROOT WAs get both SYSTEM_ADMIN + AUTHORITY perms
|
|
244
|
+
if hasattr(user, "wa_role") and user.wa_role == WARole.ROOT:
|
|
245
|
+
authority_perms = auth_service.get_permissions_for_role(APIRole.AUTHORITY)
|
|
246
|
+
user_permissions.update(authority_perms)
|
|
247
|
+
|
|
248
|
+
# Add any custom permissions
|
|
249
|
+
if hasattr(user, "custom_permissions") and user.custom_permissions:
|
|
250
|
+
for perm in user.custom_permissions:
|
|
251
|
+
user_permissions.add(perm)
|
|
252
|
+
|
|
253
|
+
# Check if user has all required permissions
|
|
254
|
+
missing = set(permissions) - user_permissions
|
|
255
|
+
if missing:
|
|
256
|
+
raise HTTPException(
|
|
257
|
+
status_code=status.HTTP_403_FORBIDDEN, detail=f"Missing required permissions: {', '.join(missing)}"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
return check
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""API endpoints module."""
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Emergency API endpoints.
|
|
3
|
+
|
|
4
|
+
Provides WA-authorized emergency control endpoints including kill switch.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any, Dict
|
|
9
|
+
|
|
10
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
11
|
+
|
|
12
|
+
from ciris_engine.protocols.services import RuntimeControlService as RuntimeControlServiceProtocol
|
|
13
|
+
from ciris_engine.schemas.services.shutdown import EmergencyShutdownStatus, WASignedCommand
|
|
14
|
+
from ciris_engine.schemas.types import JSONDict
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
router = APIRouter(prefix="/emergency", tags=["emergency"])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_runtime_service() -> RuntimeControlServiceProtocol:
|
|
22
|
+
"""Get runtime control service dependency."""
|
|
23
|
+
# This will be injected by the API adapter
|
|
24
|
+
# For now, return None - the actual service should be injected
|
|
25
|
+
return None # type: ignore
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.post("/shutdown", response_model=EmergencyShutdownStatus)
|
|
29
|
+
async def emergency_shutdown(
|
|
30
|
+
command: WASignedCommand, runtime_service: RuntimeControlServiceProtocol = Depends(get_runtime_service)
|
|
31
|
+
) -> EmergencyShutdownStatus:
|
|
32
|
+
"""
|
|
33
|
+
Execute WA-authorized emergency shutdown.
|
|
34
|
+
|
|
35
|
+
This endpoint accepts a signed SHUTDOWN_NOW command from a Wise Authority
|
|
36
|
+
and initiates immediate graceful shutdown, bypassing normal procedures.
|
|
37
|
+
|
|
38
|
+
The command must be signed by a ROOT WA authority or a WA in the trust tree.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
command: Signed emergency shutdown command
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Status of the emergency shutdown process
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
HTTPException: If command verification fails
|
|
48
|
+
"""
|
|
49
|
+
logger.critical(f"Emergency shutdown endpoint called by WA {command.wa_id}")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
# Handle the emergency command
|
|
53
|
+
status = await runtime_service.handle_emergency_shutdown(command)
|
|
54
|
+
|
|
55
|
+
if not status.command_verified:
|
|
56
|
+
raise HTTPException(status_code=403, detail=f"Command verification failed: {status.verification_error}")
|
|
57
|
+
|
|
58
|
+
return status
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
logger.error(f"Emergency shutdown failed: {e}")
|
|
62
|
+
raise HTTPException(status_code=500, detail=f"Emergency shutdown failed: {str(e)}")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@router.get("/kill-switch/status")
|
|
66
|
+
async def get_kill_switch_status(
|
|
67
|
+
runtime_service: RuntimeControlServiceProtocol = Depends(get_runtime_service),
|
|
68
|
+
) -> JSONDict:
|
|
69
|
+
"""
|
|
70
|
+
Get current kill switch configuration status.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Current kill switch configuration (without sensitive keys)
|
|
74
|
+
"""
|
|
75
|
+
if hasattr(runtime_service, "_kill_switch_config"):
|
|
76
|
+
config = runtime_service._kill_switch_config
|
|
77
|
+
return {
|
|
78
|
+
"enabled": config.enabled,
|
|
79
|
+
"root_wa_count": len(config.root_wa_public_keys), # ROOT WA authorities
|
|
80
|
+
"trust_tree_depth": config.trust_tree_depth,
|
|
81
|
+
"allow_relay": config.allow_relay,
|
|
82
|
+
"max_shutdown_time_ms": config.max_shutdown_time_ms,
|
|
83
|
+
"command_expiry_seconds": config.command_expiry_seconds,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {"enabled": False, "error": "Kill switch not configured"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""API middleware components."""
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple rate limiting middleware for CIRIS API.
|
|
3
|
+
|
|
4
|
+
Implements a basic in-memory rate limiter using token bucket algorithm.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from datetime import datetime, timedelta
|
|
10
|
+
from typing import Any, Callable, Dict, Optional, Tuple, cast
|
|
11
|
+
|
|
12
|
+
import jwt
|
|
13
|
+
from fastapi import Request, Response
|
|
14
|
+
from fastapi.responses import JSONResponse
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RateLimiter:
|
|
20
|
+
"""Simple in-memory rate limiter using token bucket algorithm.
|
|
21
|
+
|
|
22
|
+
IMPORTANT: This implementation is in-memory only and not suitable for
|
|
23
|
+
multi-instance deployments. For production with multiple API pods,
|
|
24
|
+
consider using Redis or another distributed backend.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, requests_per_minute: int = 60, max_clients: int = 10000):
|
|
28
|
+
"""
|
|
29
|
+
Initialize rate limiter.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
requests_per_minute: Number of requests allowed per minute
|
|
33
|
+
max_clients: Maximum number of client buckets to track (prevents memory exhaustion)
|
|
34
|
+
"""
|
|
35
|
+
self.rate = requests_per_minute
|
|
36
|
+
self.max_clients = max_clients
|
|
37
|
+
self.buckets: Dict[str, Tuple[float, datetime]] = {}
|
|
38
|
+
self._lock = asyncio.Lock()
|
|
39
|
+
self._cleanup_interval = 300 # Cleanup old entries every 5 minutes
|
|
40
|
+
self._last_cleanup = datetime.now()
|
|
41
|
+
|
|
42
|
+
async def check_rate_limit(self, client_id: str) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
Check if request is within rate limit.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
client_id: Unique identifier for client (IP or user)
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
True if allowed, False if rate limited
|
|
51
|
+
"""
|
|
52
|
+
async with self._lock:
|
|
53
|
+
now = datetime.now()
|
|
54
|
+
|
|
55
|
+
# Cleanup old entries periodically
|
|
56
|
+
if (now - self._last_cleanup).total_seconds() > self._cleanup_interval:
|
|
57
|
+
self._cleanup_old_entries()
|
|
58
|
+
self._last_cleanup = now
|
|
59
|
+
|
|
60
|
+
# Get or create bucket
|
|
61
|
+
if client_id not in self.buckets:
|
|
62
|
+
# Enforce max bucket count to prevent memory exhaustion
|
|
63
|
+
if len(self.buckets) >= self.max_clients:
|
|
64
|
+
# Remove oldest bucket to make room (LRU-like behavior)
|
|
65
|
+
oldest_client = min(self.buckets.items(), key=lambda x: x[1][1])[0]
|
|
66
|
+
del self.buckets[oldest_client]
|
|
67
|
+
|
|
68
|
+
# New client starts with full tokens minus the one consumed by this request
|
|
69
|
+
self.buckets[client_id] = (float(self.rate - 1), now)
|
|
70
|
+
return True
|
|
71
|
+
|
|
72
|
+
tokens, last_update = self.buckets[client_id]
|
|
73
|
+
|
|
74
|
+
# Calculate time elapsed and refill tokens
|
|
75
|
+
elapsed = (now - last_update).total_seconds()
|
|
76
|
+
tokens = min(self.rate, tokens + elapsed * (self.rate / 60.0))
|
|
77
|
+
|
|
78
|
+
# Check if we have tokens available
|
|
79
|
+
if tokens >= 1:
|
|
80
|
+
tokens -= 1
|
|
81
|
+
self.buckets[client_id] = (tokens, now)
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
# No tokens available - update timestamp but don't consume
|
|
85
|
+
self.buckets[client_id] = (tokens, now)
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
def _cleanup_old_entries(self) -> None:
|
|
89
|
+
"""Remove entries that haven't been used in over an hour."""
|
|
90
|
+
now = datetime.now()
|
|
91
|
+
cutoff = now - timedelta(hours=1)
|
|
92
|
+
|
|
93
|
+
to_remove = []
|
|
94
|
+
for client_id, (_, last_update) in self.buckets.items():
|
|
95
|
+
if last_update < cutoff:
|
|
96
|
+
to_remove.append(client_id)
|
|
97
|
+
|
|
98
|
+
for client_id in to_remove:
|
|
99
|
+
del self.buckets[client_id]
|
|
100
|
+
|
|
101
|
+
def get_retry_after(self, client_id: str) -> int:
|
|
102
|
+
"""
|
|
103
|
+
Get seconds until next request is allowed.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
client_id: Unique identifier for client
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Seconds to wait before retry
|
|
110
|
+
"""
|
|
111
|
+
if client_id not in self.buckets:
|
|
112
|
+
return 0
|
|
113
|
+
|
|
114
|
+
tokens, _ = self.buckets[client_id]
|
|
115
|
+
if tokens >= 1:
|
|
116
|
+
return 0
|
|
117
|
+
|
|
118
|
+
# Calculate time needed to get 1 token
|
|
119
|
+
tokens_needed = 1 - tokens
|
|
120
|
+
seconds_per_token = 60.0 / self.rate
|
|
121
|
+
return int(tokens_needed * seconds_per_token) + 1
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class RateLimitMiddleware:
|
|
125
|
+
"""FastAPI middleware for rate limiting."""
|
|
126
|
+
|
|
127
|
+
def __init__(self, requests_per_minute: int = 60, gateway_secret: Optional[bytes] = None):
|
|
128
|
+
"""
|
|
129
|
+
Initialize middleware.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
requests_per_minute: Rate limit per minute
|
|
133
|
+
gateway_secret: Secret for verifying JWT tokens (required for user-based rate limiting)
|
|
134
|
+
"""
|
|
135
|
+
self.limiter = RateLimiter(requests_per_minute)
|
|
136
|
+
self.gateway_secret = gateway_secret
|
|
137
|
+
# Exempt paths that should not be rate limited
|
|
138
|
+
self.exempt_paths = {
|
|
139
|
+
"/openapi.json",
|
|
140
|
+
"/docs",
|
|
141
|
+
"/redoc",
|
|
142
|
+
"/emergency/shutdown", # Emergency endpoints bypass rate limiting
|
|
143
|
+
"/v1/system/health", # Health checks should not be rate limited
|
|
144
|
+
}
|
|
145
|
+
# Static file extensions that should be exempt from rate limiting
|
|
146
|
+
self.exempt_extensions = {
|
|
147
|
+
".js",
|
|
148
|
+
".css",
|
|
149
|
+
".map",
|
|
150
|
+
".woff",
|
|
151
|
+
".woff2",
|
|
152
|
+
".ttf",
|
|
153
|
+
".otf",
|
|
154
|
+
".eot",
|
|
155
|
+
".png",
|
|
156
|
+
".jpg",
|
|
157
|
+
".jpeg",
|
|
158
|
+
".gif",
|
|
159
|
+
".svg",
|
|
160
|
+
".ico",
|
|
161
|
+
".webp",
|
|
162
|
+
".mp4",
|
|
163
|
+
".webm",
|
|
164
|
+
".txt",
|
|
165
|
+
".html", # Static HTML pages from Next.js export
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
def _get_gateway_secret(self, request: Request) -> Optional[bytes]:
|
|
169
|
+
"""
|
|
170
|
+
Get gateway secret from the authentication service.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
request: FastAPI request object with app state
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Gateway secret bytes, or None if not available
|
|
177
|
+
"""
|
|
178
|
+
# Try to get from explicitly set gateway_secret first
|
|
179
|
+
if self.gateway_secret:
|
|
180
|
+
return self.gateway_secret
|
|
181
|
+
|
|
182
|
+
# Lazy-load from authentication service if available
|
|
183
|
+
if hasattr(request.app.state, "authentication_service"):
|
|
184
|
+
auth_service = request.app.state.authentication_service
|
|
185
|
+
if auth_service and hasattr(auth_service, "gateway_secret"):
|
|
186
|
+
secret = auth_service.gateway_secret
|
|
187
|
+
# Type guard: ensure it's bytes
|
|
188
|
+
if isinstance(secret, bytes):
|
|
189
|
+
return secret
|
|
190
|
+
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
def _extract_user_id_from_jwt(self, token: str, request: Request) -> Optional[str]:
|
|
194
|
+
"""
|
|
195
|
+
Extract user ID from JWT token WITH proper signature verification.
|
|
196
|
+
|
|
197
|
+
SECURITY: This method verifies the JWT signature before trusting the contents.
|
|
198
|
+
Prevents attackers from forging tokens with arbitrary user IDs to bypass rate limiting.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
token: JWT token string
|
|
202
|
+
request: FastAPI request object (for accessing authentication service)
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
User ID (wa_id) from verified token's 'sub' claim, or None if verification fails
|
|
206
|
+
"""
|
|
207
|
+
gateway_secret = self._get_gateway_secret(request)
|
|
208
|
+
if not gateway_secret:
|
|
209
|
+
# No gateway secret available - cannot verify tokens, fallback to IP-based rate limiting
|
|
210
|
+
logger.debug("No gateway_secret available - cannot verify JWT tokens")
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
# SECURITY FIX: Verify signature with gateway secret before trusting token contents
|
|
215
|
+
decoded = jwt.decode(token, gateway_secret, algorithms=["HS256"])
|
|
216
|
+
|
|
217
|
+
# Extract and validate the 'sub' field
|
|
218
|
+
sub = decoded.get("sub")
|
|
219
|
+
if isinstance(sub, str):
|
|
220
|
+
return sub
|
|
221
|
+
return None
|
|
222
|
+
except jwt.InvalidTokenError as e:
|
|
223
|
+
# Token verification failed - fallback to IP-based rate limiting
|
|
224
|
+
logger.debug(f"JWT verification failed in rate limiter: {type(e).__name__}: {e}")
|
|
225
|
+
return None
|
|
226
|
+
except Exception as e:
|
|
227
|
+
# Unexpected error during verification
|
|
228
|
+
logger.debug(f"Failed to verify JWT in rate limiter: {type(e).__name__}: {e}")
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
async def __call__(self, request: Request, call_next: Callable[..., Any]) -> Response:
|
|
232
|
+
"""Process request through rate limiter."""
|
|
233
|
+
# Check if path is exempt
|
|
234
|
+
if request.url.path in self.exempt_paths:
|
|
235
|
+
response = await call_next(request)
|
|
236
|
+
return cast(Response, response)
|
|
237
|
+
|
|
238
|
+
# Check if request is for a static file (by extension or path prefix)
|
|
239
|
+
path = request.url.path
|
|
240
|
+
if path.startswith("/_next/") or any(path.endswith(ext) for ext in self.exempt_extensions):
|
|
241
|
+
response = await call_next(request)
|
|
242
|
+
return cast(Response, response)
|
|
243
|
+
|
|
244
|
+
# Extract client identifier (prefer authenticated user, fallback to IP)
|
|
245
|
+
client_host = request.client.host if request.client else "unknown"
|
|
246
|
+
client_id = None
|
|
247
|
+
|
|
248
|
+
# Try to extract user ID from authentication
|
|
249
|
+
auth_header = request.headers.get("Authorization", "")
|
|
250
|
+
if auth_header.startswith("Bearer "):
|
|
251
|
+
token = auth_header[7:] # Remove "Bearer " prefix
|
|
252
|
+
|
|
253
|
+
# Check for service token format: "service:TOKEN"
|
|
254
|
+
if token.startswith("service:"):
|
|
255
|
+
# Service tokens use IP-based rate limiting
|
|
256
|
+
client_id = f"service_{client_host}"
|
|
257
|
+
else:
|
|
258
|
+
# JWT tokens: verify and extract user_id for per-user rate limiting
|
|
259
|
+
user_id = self._extract_user_id_from_jwt(token, request)
|
|
260
|
+
if user_id:
|
|
261
|
+
# Use user ID from verified JWT for per-user rate limiting
|
|
262
|
+
client_id = f"user_{user_id}"
|
|
263
|
+
else:
|
|
264
|
+
# Failed to verify JWT, fall back to IP-based
|
|
265
|
+
client_id = f"auth_{client_host}"
|
|
266
|
+
else:
|
|
267
|
+
# No authentication - use IP-based rate limiting
|
|
268
|
+
client_id = f"ip_{client_host}"
|
|
269
|
+
|
|
270
|
+
# Check rate limit
|
|
271
|
+
allowed = await self.limiter.check_rate_limit(client_id)
|
|
272
|
+
|
|
273
|
+
if not allowed:
|
|
274
|
+
retry_after = self.limiter.get_retry_after(client_id)
|
|
275
|
+
return JSONResponse(
|
|
276
|
+
status_code=429,
|
|
277
|
+
content={
|
|
278
|
+
"detail": f"Too many requests. Please wait {retry_after} seconds before trying again.",
|
|
279
|
+
"error": "rate_limit_exceeded",
|
|
280
|
+
"retry_after": retry_after,
|
|
281
|
+
"message": "You're sending requests too quickly. The system will be ready again shortly.",
|
|
282
|
+
},
|
|
283
|
+
headers={
|
|
284
|
+
"Retry-After": str(retry_after),
|
|
285
|
+
"X-RateLimit-Limit": str(self.limiter.rate),
|
|
286
|
+
"X-RateLimit-Remaining": "0",
|
|
287
|
+
"X-RateLimit-Window": "60",
|
|
288
|
+
},
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# Process request
|
|
292
|
+
processed_response = await call_next(request)
|
|
293
|
+
typed_response: Response = cast(Response, processed_response)
|
|
294
|
+
|
|
295
|
+
# Add rate limit headers to response
|
|
296
|
+
if client_id in self.limiter.buckets:
|
|
297
|
+
tokens, _ = self.limiter.buckets[client_id]
|
|
298
|
+
typed_response.headers["X-RateLimit-Limit"] = str(self.limiter.rate)
|
|
299
|
+
typed_response.headers["X-RateLimit-Remaining"] = str(int(tokens))
|
|
300
|
+
typed_response.headers["X-RateLimit-Window"] = "60"
|
|
301
|
+
|
|
302
|
+
return typed_response
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared models for API responses.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from ciris_engine.schemas.types import JSONDict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StandardResponse(BaseModel):
|
|
14
|
+
"""Standard API response format."""
|
|
15
|
+
|
|
16
|
+
success: bool = Field(..., description="Whether the request was successful")
|
|
17
|
+
data: Optional[Any] = Field(None, description="Response data")
|
|
18
|
+
message: Optional[str] = Field(None, description="Human-readable message")
|
|
19
|
+
error: Optional[str] = Field(None, description="Error message if success is False")
|
|
20
|
+
metadata: Optional[JSONDict] = Field(default_factory=lambda: {}, description="Additional metadata")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TokenData(BaseModel):
|
|
24
|
+
"""Token data for authenticated users."""
|
|
25
|
+
|
|
26
|
+
username: str = Field(..., description="Username")
|
|
27
|
+
email: Optional[str] = Field(None, description="User email")
|
|
28
|
+
role: str = Field("OBSERVER", description="User role (OBSERVER, ADMIN, AUTHORITY, SYSTEM_ADMIN)")
|
|
29
|
+
exp: Optional[datetime] = Field(None, description="Token expiration")
|