aegis-stack 0.2.0rc2__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.
- aegis/__init__.py +5 -0
- aegis/__main__.py +51 -0
- aegis/cli/__init__.py +6 -0
- aegis/cli/callbacks.py +114 -0
- aegis/cli/interactive.py +611 -0
- aegis/cli/utils.py +70 -0
- aegis/cli/validators.py +34 -0
- aegis/commands/__init__.py +6 -0
- aegis/commands/add.py +353 -0
- aegis/commands/add_service.py +332 -0
- aegis/commands/components.py +35 -0
- aegis/commands/init.py +370 -0
- aegis/commands/remove.py +227 -0
- aegis/commands/services.py +52 -0
- aegis/commands/update.py +252 -0
- aegis/commands/version.py +12 -0
- aegis/config/__init__.py +1 -0
- aegis/config/shared_files.py +136 -0
- aegis/core/CLAUDE.md +377 -0
- aegis/core/__init__.py +6 -0
- aegis/core/component_files.py +228 -0
- aegis/core/component_utils.py +220 -0
- aegis/core/components.py +127 -0
- aegis/core/copier_manager.py +315 -0
- aegis/core/copier_updater.py +475 -0
- aegis/core/dependency_resolver.py +119 -0
- aegis/core/manual_updater.py +554 -0
- aegis/core/post_gen_tasks.py +547 -0
- aegis/core/service_resolver.py +261 -0
- aegis/core/services.py +157 -0
- aegis/core/template_generator.py +266 -0
- aegis/core/version_compatibility.py +259 -0
- aegis/templates/CLAUDE.md +591 -0
- aegis/templates/cookiecutter-aegis-project/cookiecutter.json +39 -0
- aegis/templates/cookiecutter-aegis-project/hooks/post_gen_project.py +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.env.example.j2 +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Makefile +236 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/README.md.j2 +196 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/alembic.ini.j2 +111 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/env.py.j2 +91 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/script.py.mako +25 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/versions/001_initial_auth.py.j2 +51 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai.py.j2 +700 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai_rendering.py +361 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/auth.py.j2 +253 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/health.py.j2 +419 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/load_test.py.j2 +656 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/main.py.j2 +65 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/tasks.py.j2 +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/{% if cookiecutter.include_scheduler == /"yes/" %}tasks.py{% endif %}" +340 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/deps.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/health.py +163 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/models.py.j2 +280 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/routing.py.j2 +32 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/scheduler.py.j2 +121 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/worker.py.j2 +478 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/hooks.py +144 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/main.py +31 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/component_health.py.j2 +418 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/database_init.py.j2 +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/__init__.py.j2 +47 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/main.py.j2 +653 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/theme.py +48 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/main.py.j2 +156 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/CLAUDE.md.j2 +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/constants.py.j2 +30 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/pools.py +97 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/media.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/system.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/registry.py +139 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/config.py.j2 +178 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/constants.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/db.py.j2 +176 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/log.py +92 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/security.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/webserver.py +40 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/{% if cookiecutter.include_scheduler == /"yes/" %}scheduler.py{% endif %}" +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/main.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/user.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/py.typed +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/config.py +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/conversation.py +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/health.py +96 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/models.py +229 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/providers.py +370 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/service.py +388 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/auth_service.py +41 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/health.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/user_service.py +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/middleware_inspector.py.j2 +223 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/models.py.j2 +70 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/route_inspector.py.j2 +155 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test.py +679 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test_models.py +266 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/__init__.py.j2 +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/models.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/scheduled_task_manager.py.j2 +273 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/task_monitor.py.j2 +189 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/__init__.py +15 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/models.py +26 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/__init__.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/alerts.py +94 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/backup.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/health.py.j2 +1333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/models.py +243 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/ui.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.env.example.j2 +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Makefile +211 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/README.md.j2 +172 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/docker-compose.yml.j2 +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/pyproject.toml.j2 +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/uv.lock +1673 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docker-compose.yml.j2 +200 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/api.md +191 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md.j2 +621 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/development.md +215 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/health.md +240 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/pyproject.toml.j2 +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh +87 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh.j2 +93 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/gen_docs.py +16 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_auth_endpoints.py.j2 +307 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_health_endpoints.py.j2 +262 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_scheduler_endpoints.py.j2 +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_worker_endpoints.py.j2 +165 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/components/test_scheduler.py +43 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/conftest.py.j2 +195 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/conftest.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_health.py +157 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_models.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_service.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_auth_integration.py.j2 +528 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_component_integration.py.j2 +387 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_health_logic.py.j2 +663 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_middleware_inspector.py.j2 +248 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_scheduled_task_manager.py.j2 +292 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_system_service.py +98 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_worker_health_registration.py.j2 +257 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/test_core.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/uv.lock +1673 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.copier-answers.yml.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.dockerignore +71 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.env.example.jinja +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.gitignore +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Dockerfile +53 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Makefile.jinja +236 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/README.md.jinja +196 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/alembic.ini.jinja +111 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/env.py.jinja +91 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/script.py.mako +25 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/versions/001_initial_auth.py.jinja +51 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/__init__.py.jinja +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/__init__.py.jinja +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai.py.jinja +700 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai_rendering.py +360 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/auth.py.jinja +253 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/health.py.jinja +419 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/load_test.py.jinja +656 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/main.py.jinja +65 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/tasks.py.jinja +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/deps.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja +163 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja +280 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja +32 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/scheduler.py.jinja +121 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/worker.py.jinja +478 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/hooks.py +144 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/main.py +31 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/component_health.py.jinja +418 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/database_init.py.jinja +83 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/__init__.py +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/__init__.py.jinja +47 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/main.py.jinja +653 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/theme.py +48 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/main.py.jinja +156 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/CLAUDE.md.jinja +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/__init__.py +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/constants.py.jinja +30 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/pools.py +97 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/media.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/system.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/registry.py +139 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/config.py.jinja +178 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/constants.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/db.py.jinja +176 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/log.py +92 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/security.py +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/scheduler.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/webserver.py +39 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/main.py +61 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/user.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/py.typed +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/config.py +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/conversation.py +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/health.py +96 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/models.py +229 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/providers.py.jinja +370 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/service.py +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/auth_service.py +40 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/health.py +162 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/user_service.py +82 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/middleware_inspector.py.jinja +223 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/models.py.jinja +70 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/route_inspector.py.jinja +155 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test.py +678 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test_models.py +265 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/__init__.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/models.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/scheduled_task_manager.py.jinja +273 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/task_monitor.py.jinja +189 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/__init__.py +15 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/models.py +26 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/__init__.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/alerts.py +94 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/backup.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/health.py.jinja +1333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/models.py +243 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/ui.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57223!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57225!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57533!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57538!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57897!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57904!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58315!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58324!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58837!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58849!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/.env.example.jinja +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/README.md.jinja +172 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/pyproject.toml.jinja +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docker-compose.yml.jinja +200 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/api.md.jinja +191 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md.jinja +621 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/development.md.jinja +215 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/health.md.jinja +240 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/pyproject.toml.jinja +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh +87 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh.jinja +93 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/gen_docs.py +16 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_auth_endpoints.py.jinja +307 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_health_endpoints.py.jinja +262 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_scheduler_endpoints.py.jinja +214 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_worker_endpoints.py.jinja +165 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/components/test_scheduler.py +43 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/conftest.py.jinja +195 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/conftest.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_health.py +157 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_models.py +164 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_service.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_auth_integration.py.jinja +528 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_component_integration.py.jinja +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_health_logic.py.jinja +663 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_middleware_inspector.py.jinja +248 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_scheduled_task_manager.py.jinja +292 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_system_service.py +98 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_worker_health_registration.py.jinja +257 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_core.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/uv.lock +1673 -0
- aegis_stack-0.2.0rc2.dist-info/METADATA +165 -0
- aegis_stack-0.2.0rc2.dist-info/RECORD +392 -0
- aegis_stack-0.2.0rc2.dist-info/WHEEL +4 -0
- aegis_stack-0.2.0rc2.dist-info/entry_points.txt +3 -0
- aegis_stack-0.2.0rc2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""
|
|
2
|
+
System domain Pydantic models.
|
|
3
|
+
|
|
4
|
+
Type-safe data models for system health monitoring, alerts, and status reporting.
|
|
5
|
+
All models provide runtime validation and automatic FastAPI integration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field, computed_field
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ComponentStatusType(str, Enum):
|
|
16
|
+
"""Component status levels."""
|
|
17
|
+
|
|
18
|
+
HEALTHY = "healthy"
|
|
19
|
+
INFO = "info"
|
|
20
|
+
WARNING = "warning"
|
|
21
|
+
UNHEALTHY = "unhealthy"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ComponentStatus(BaseModel):
|
|
25
|
+
"""Status of a single system component."""
|
|
26
|
+
|
|
27
|
+
name: str = Field(..., description="Component name")
|
|
28
|
+
status: ComponentStatusType = Field(
|
|
29
|
+
default=ComponentStatusType.HEALTHY,
|
|
30
|
+
description="Detailed status level (healthy/info/warning/unhealthy)",
|
|
31
|
+
)
|
|
32
|
+
message: str = Field(..., description="Status message or error description")
|
|
33
|
+
response_time_ms: float | None = Field(
|
|
34
|
+
None, description="Response time in milliseconds"
|
|
35
|
+
)
|
|
36
|
+
metadata: dict[str, Any] = Field(
|
|
37
|
+
default_factory=dict, description="Additional component metadata"
|
|
38
|
+
)
|
|
39
|
+
sub_components: dict[str, "ComponentStatus"] = Field(
|
|
40
|
+
default_factory=dict,
|
|
41
|
+
description="Sub-components (e.g., system metrics under backend)",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@computed_field # type: ignore[prop-decorator]
|
|
45
|
+
@property
|
|
46
|
+
def healthy(self) -> bool:
|
|
47
|
+
"""
|
|
48
|
+
Component is healthy if status is not UNHEALTHY.
|
|
49
|
+
|
|
50
|
+
WARNING and INFO statuses are considered healthy (functional but with concerns),
|
|
51
|
+
only UNHEALTHY is considered not healthy (non-functional).
|
|
52
|
+
"""
|
|
53
|
+
return self.status != ComponentStatusType.UNHEALTHY
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SystemStatus(BaseModel):
|
|
57
|
+
"""Overall system status with component details."""
|
|
58
|
+
|
|
59
|
+
components: dict[str, ComponentStatus] = Field(
|
|
60
|
+
..., description="Component status by name"
|
|
61
|
+
)
|
|
62
|
+
overall_healthy: bool = Field(..., description="Whether all components are healthy")
|
|
63
|
+
timestamp: datetime = Field(..., description="When status was generated")
|
|
64
|
+
system_info: dict[str, Any] = Field(
|
|
65
|
+
default_factory=dict, description="System information"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def _get_all_components_flat(self) -> list[tuple[str, ComponentStatus]]:
|
|
69
|
+
"""Get all components including sub-components as a flat list."""
|
|
70
|
+
all_components = []
|
|
71
|
+
|
|
72
|
+
for name, component in self.components.items():
|
|
73
|
+
all_components.extend(self._flatten_component(name, component))
|
|
74
|
+
|
|
75
|
+
return all_components
|
|
76
|
+
|
|
77
|
+
def _flatten_component(
|
|
78
|
+
self, name: str, component: ComponentStatus
|
|
79
|
+
) -> list[tuple[str, ComponentStatus]]:
|
|
80
|
+
"""Recursively flatten a component and its sub-components into a list."""
|
|
81
|
+
result = [(name, component)]
|
|
82
|
+
# Recursively add sub-components with parent.child naming
|
|
83
|
+
for sub_name, sub_component in component.sub_components.items():
|
|
84
|
+
result.extend(self._flatten_component(f"{name}.{sub_name}", sub_component))
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def healthy_components(self) -> list[str]:
|
|
89
|
+
"""List of healthy component names (including sub-components)."""
|
|
90
|
+
return [
|
|
91
|
+
name
|
|
92
|
+
for name, component in self._get_all_components_flat()
|
|
93
|
+
if component.healthy
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def unhealthy_components(self) -> list[str]:
|
|
98
|
+
"""List of unhealthy component names (including sub-components)."""
|
|
99
|
+
return [
|
|
100
|
+
name
|
|
101
|
+
for name, component in self._get_all_components_flat()
|
|
102
|
+
if not component.healthy
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def health_percentage(self) -> float:
|
|
107
|
+
"""Percentage of healthy components (including sub-components)."""
|
|
108
|
+
all_components = self._get_all_components_flat()
|
|
109
|
+
if not all_components:
|
|
110
|
+
return 100.0
|
|
111
|
+
healthy_count = len([c for _, c in all_components if c.healthy])
|
|
112
|
+
return (healthy_count / len(all_components)) * 100
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def total_components(self) -> int:
|
|
116
|
+
"""Total number of top-level components."""
|
|
117
|
+
return len(self.components)
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def healthy_top_level_components(self) -> list[str]:
|
|
121
|
+
"""List of healthy top-level component names."""
|
|
122
|
+
return [name for name, comp in self.components.items() if comp.healthy]
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def services_status(self) -> ComponentStatus | None:
|
|
126
|
+
"""Get the services component status if it exists."""
|
|
127
|
+
if "aegis" in self.components:
|
|
128
|
+
aegis_component = self.components["aegis"]
|
|
129
|
+
if (
|
|
130
|
+
hasattr(aegis_component, "sub_components")
|
|
131
|
+
and aegis_component.sub_components
|
|
132
|
+
):
|
|
133
|
+
return aegis_component.sub_components.get("services")
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def has_services(self) -> bool:
|
|
138
|
+
"""Check if any services are registered in the system."""
|
|
139
|
+
return self.services_status is not None
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def service_names(self) -> list[str]:
|
|
143
|
+
"""Get list of registered service names."""
|
|
144
|
+
services_component = self.services_status
|
|
145
|
+
if services_component and hasattr(services_component, "sub_components"):
|
|
146
|
+
return list(services_component.sub_components.keys())
|
|
147
|
+
return []
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def healthy_services(self) -> list[str]:
|
|
151
|
+
"""List of healthy service names."""
|
|
152
|
+
services_component = self.services_status
|
|
153
|
+
if services_component and hasattr(services_component, "sub_components"):
|
|
154
|
+
return [
|
|
155
|
+
name
|
|
156
|
+
for name, service in services_component.sub_components.items()
|
|
157
|
+
if service.healthy
|
|
158
|
+
]
|
|
159
|
+
return []
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def unhealthy_services(self) -> list[str]:
|
|
163
|
+
"""List of unhealthy service names."""
|
|
164
|
+
services_component = self.services_status
|
|
165
|
+
if services_component and hasattr(services_component, "sub_components"):
|
|
166
|
+
return [
|
|
167
|
+
name
|
|
168
|
+
for name, service in services_component.sub_components.items()
|
|
169
|
+
if not service.healthy
|
|
170
|
+
]
|
|
171
|
+
return []
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class HealthResponse(BaseModel):
|
|
175
|
+
"""Basic health check API response."""
|
|
176
|
+
|
|
177
|
+
healthy: bool = Field(..., description="Whether system is healthy")
|
|
178
|
+
status: str = Field(..., description="Overall status text")
|
|
179
|
+
components: dict[str, ComponentStatus] = Field(
|
|
180
|
+
default_factory=dict, description="Component statuses"
|
|
181
|
+
)
|
|
182
|
+
timestamp: str = Field(..., description="ISO timestamp when checked")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class DetailedHealthResponse(BaseModel):
|
|
186
|
+
"""Detailed health check API response with system information."""
|
|
187
|
+
|
|
188
|
+
healthy: bool = Field(..., description="Whether system is healthy")
|
|
189
|
+
status: str = Field(..., description="Overall status text")
|
|
190
|
+
service: str = Field(..., description="Service name")
|
|
191
|
+
version: str = Field(..., description="Service version")
|
|
192
|
+
components: dict[str, ComponentStatus] = Field(
|
|
193
|
+
..., description="Component statuses"
|
|
194
|
+
)
|
|
195
|
+
system_info: dict[str, Any] = Field(..., description="System information")
|
|
196
|
+
timestamp: str = Field(..., description="ISO timestamp when checked")
|
|
197
|
+
healthy_components: list[str] = Field(
|
|
198
|
+
..., description="List of healthy component names"
|
|
199
|
+
)
|
|
200
|
+
unhealthy_components: list[str] = Field(
|
|
201
|
+
..., description="List of unhealthy component names"
|
|
202
|
+
)
|
|
203
|
+
health_percentage: float = Field(
|
|
204
|
+
..., description="Percentage of healthy components"
|
|
205
|
+
)
|
|
206
|
+
# Service-specific fields (optional)
|
|
207
|
+
has_services: bool = Field(
|
|
208
|
+
default=False, description="Whether any services are registered"
|
|
209
|
+
)
|
|
210
|
+
service_names: list[str] = Field(
|
|
211
|
+
default_factory=list, description="List of registered service names"
|
|
212
|
+
)
|
|
213
|
+
healthy_services: list[str] = Field(
|
|
214
|
+
default_factory=list, description="List of healthy service names"
|
|
215
|
+
)
|
|
216
|
+
unhealthy_services: list[str] = Field(
|
|
217
|
+
default_factory=list, description="List of unhealthy service names"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class AlertSeverity(BaseModel):
|
|
222
|
+
"""Alert severity levels as constants."""
|
|
223
|
+
|
|
224
|
+
INFO: str = Field(default="info", description="Informational alert")
|
|
225
|
+
WARNING: str = Field(default="warning", description="Warning alert")
|
|
226
|
+
ERROR: str = Field(default="error", description="Error alert")
|
|
227
|
+
CRITICAL: str = Field(default="critical", description="Critical alert")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class Alert(BaseModel):
|
|
231
|
+
"""System alert model."""
|
|
232
|
+
|
|
233
|
+
severity: str = Field(..., description="Alert severity level")
|
|
234
|
+
title: str = Field(..., min_length=1, description="Alert title")
|
|
235
|
+
message: str = Field(..., min_length=1, description="Alert message")
|
|
236
|
+
timestamp: datetime = Field(..., description="When alert was created")
|
|
237
|
+
metadata: dict[str, Any] = Field(
|
|
238
|
+
default_factory=dict, description="Additional alert data"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Singleton for alert severity constants
|
|
243
|
+
alert_severity = AlertSeverity()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared UI helpers for status presentation across CLI and frontend.
|
|
3
|
+
|
|
4
|
+
Provides a single source of truth for mapping ComponentStatusType to
|
|
5
|
+
icons and semantic colors, so CLI and dashboard remain consistent.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .models import ComponentStatusType
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_status_icon(status: ComponentStatusType) -> str:
|
|
12
|
+
"""Return the display icon for a given status.
|
|
13
|
+
|
|
14
|
+
Note: INFO icon intentionally includes a trailing space for terminal alignment.
|
|
15
|
+
"""
|
|
16
|
+
if status == ComponentStatusType.HEALTHY:
|
|
17
|
+
return "✅"
|
|
18
|
+
if status == ComponentStatusType.INFO:
|
|
19
|
+
return "ℹ️ "
|
|
20
|
+
if status == ComponentStatusType.WARNING:
|
|
21
|
+
return "⚠️"
|
|
22
|
+
if status == ComponentStatusType.UNHEALTHY:
|
|
23
|
+
return "❌"
|
|
24
|
+
return "❓"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_status_color_name(status: ComponentStatusType) -> str:
|
|
28
|
+
"""Return a semantic color name for a given status (CLI friendly).
|
|
29
|
+
|
|
30
|
+
Frontend can adapt these semantic names to theme-specific colors.
|
|
31
|
+
"""
|
|
32
|
+
if status == ComponentStatusType.HEALTHY:
|
|
33
|
+
return "green"
|
|
34
|
+
if status == ComponentStatusType.INFO:
|
|
35
|
+
return "blue"
|
|
36
|
+
if status == ComponentStatusType.WARNING:
|
|
37
|
+
return "yellow"
|
|
38
|
+
if status == ComponentStatusType.UNHEALTHY:
|
|
39
|
+
return "red"
|
|
40
|
+
return "white"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_component_label(component_name: str) -> str:
|
|
44
|
+
"""Map component keys to user-facing labels (brand or friendly name)."""
|
|
45
|
+
mapping = {
|
|
46
|
+
"backend": "FastAPI",
|
|
47
|
+
"frontend": "Flet",
|
|
48
|
+
"cache": "Redis",
|
|
49
|
+
"worker": "arq",
|
|
50
|
+
"scheduler": "APScheduler",
|
|
51
|
+
}
|
|
52
|
+
return mapping.get(component_name, component_name.title())
|
|
File without changes
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png
ADDED
|
File without changes
|
|
File without changes
|
|
Binary file
|
aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Aegis Stack Environment Variables Example
|
|
2
|
+
# Copy this file to .env and customize for your environment
|
|
3
|
+
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# APPLICATION SETTINGS
|
|
6
|
+
# =============================================================================
|
|
7
|
+
|
|
8
|
+
# Environment: dev, qa, stg, prod
|
|
9
|
+
APP_ENV=dev
|
|
10
|
+
|
|
11
|
+
# Port to run the webserver on
|
|
12
|
+
PORT=8000
|
|
13
|
+
|
|
14
|
+
# Logging level: DEBUG, INFO, WARNING, ERROR
|
|
15
|
+
LOG_LEVEL=INFO
|
|
16
|
+
|
|
17
|
+
# Auto-reload server on code changes (development only)
|
|
18
|
+
AUTO_RELOAD=true
|
|
19
|
+
|
|
20
|
+
# =============================================================================
|
|
21
|
+
# DOCKER SETTINGS
|
|
22
|
+
# =============================================================================
|
|
23
|
+
|
|
24
|
+
# Docker image tag (used by docker-compose)
|
|
25
|
+
AEGIS_STACK_TAG=aegis-stack:latest
|
|
26
|
+
|
|
27
|
+
# Version tag for builds
|
|
28
|
+
AEGIS_STACK_VERSION=dev
|
|
29
|
+
|
|
30
|
+
# Environment file to use (defaults to .env)
|
|
31
|
+
# AEGIS_STACK_ENV_FILE=.env
|
|
32
|
+
|
|
33
|
+
# =============================================================================
|
|
34
|
+
# COMPONENT SETTINGS
|
|
35
|
+
# =============================================================================
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Database settings
|
|
39
|
+
# DATABASE_URL=sqlite:///./data/app.db # SQLite database (default)
|
|
40
|
+
# DATABASE_ENGINE_ECHO=false # Set to true to log all SQL queries (debugging)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Scheduler settings
|
|
47
|
+
# SCHEDULER_TIMEZONE=UTC
|
|
48
|
+
# SCHEDULER_MAX_WORKERS=10
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# API Keys and Secrets (add as needed)
|
|
52
|
+
# SECRET_KEY=your-super-secret-key-here
|
|
53
|
+
# API_KEY=your-api-key-here
|
|
54
|
+
|
|
55
|
+
# =============================================================================
|
|
56
|
+
# DEVELOPMENT OVERRIDES
|
|
57
|
+
# =============================================================================
|
|
58
|
+
|
|
59
|
+
# Worker auto-reload settings
|
|
60
|
+
# WORKER_WATCH=false # Disable worker auto-reload (useful for debugging)
|
|
61
|
+
|
|
62
|
+
# Override for local development
|
|
63
|
+
# Use this to point to local services instead of Docker services
|
|
64
|
+
# DATABASE_HOST=host.docker.internal # For connecting to host DB from container
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# clean-validation 🛡️
|
|
2
|
+
|
|
3
|
+
A production-ready async Python application built with Aegis Stack
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
This Aegis Stack project includes the following components:
|
|
8
|
+
|
|
9
|
+
- **✅ Backend**: FastAPI-based async web server
|
|
10
|
+
- **✅ Frontend**: Flet-based Python UI framework
|
|
11
|
+
- **✅ Scheduler**: APScheduler-based async task scheduling
|
|
12
|
+
- **✅ Database**: SQLite database with SQLModel ORM
|
|
13
|
+
|
|
14
|
+
## Getting Started
|
|
15
|
+
|
|
16
|
+
### Prerequisites
|
|
17
|
+
|
|
18
|
+
- Python 3.11+
|
|
19
|
+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
20
|
+
|
|
21
|
+
### Installation
|
|
22
|
+
|
|
23
|
+
1. **Install dependencies:**
|
|
24
|
+
```bash
|
|
25
|
+
uv sync # Core dependencies only
|
|
26
|
+
# Or for development: uv sync --all-extras (includes testing, linting, docs)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. **Activate virtual environment:**
|
|
30
|
+
```bash
|
|
31
|
+
source .venv/bin/activate
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. **Set up environment:**
|
|
35
|
+
```bash
|
|
36
|
+
cp .env.example .env
|
|
37
|
+
# Edit .env with your configuration
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
4. **Set up database:**
|
|
41
|
+
```bash
|
|
42
|
+
# Create data directory for SQLite database
|
|
43
|
+
mkdir -p data
|
|
44
|
+
|
|
45
|
+
# Database will be created automatically on first run
|
|
46
|
+
# Default location: data/app.db
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
5. **Run the application:**
|
|
50
|
+
```bash
|
|
51
|
+
make server
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The application will be available at `http://127.0.0.1:8000`.
|
|
55
|
+
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
### Running Tests
|
|
59
|
+
```bash
|
|
60
|
+
make test
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Code Quality
|
|
64
|
+
```bash
|
|
65
|
+
make check # Run linting, type checking, and tests
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### CLI Commands
|
|
69
|
+
|
|
70
|
+
Your project gets its own CLI command **automatically installed** when first used - no setup required! 🎉
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Health monitoring (auto-installs CLI if needed)
|
|
74
|
+
make health # Basic health check
|
|
75
|
+
make health-detailed # Detailed component status
|
|
76
|
+
make health-json # JSON output for scripts
|
|
77
|
+
make health-quick # Quick healthy/unhealthy check
|
|
78
|
+
|
|
79
|
+
# Direct CLI usage (after first make command)
|
|
80
|
+
clean-validation health check # Basic health check
|
|
81
|
+
clean-validation health check --detailed # Detailed component status
|
|
82
|
+
clean-validation health check --json # JSON output for scripts
|
|
83
|
+
clean-validation health quick # Quick healthy/unhealthy check
|
|
84
|
+
|
|
85
|
+
# Explore all commands
|
|
86
|
+
clean-validation --help # See all available commands
|
|
87
|
+
clean-validation health --help # See health subcommand options
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Environment Issues?** If CLI commands don't work:
|
|
91
|
+
```bash
|
|
92
|
+
# Ensure you're in the project's virtual environment
|
|
93
|
+
unset VIRTUAL_ENV # Clear Docker contamination
|
|
94
|
+
source .venv/bin/activate # Activate local venv
|
|
95
|
+
make health # This will auto-install CLI
|
|
96
|
+
# Or manually: make install-cli
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Documentation
|
|
100
|
+
```bash
|
|
101
|
+
make docs-serve # Serve docs at http://localhost:8001/clean-validation/
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Docker
|
|
105
|
+
|
|
106
|
+
### Development
|
|
107
|
+
```bash
|
|
108
|
+
docker compose --profile dev up
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Production
|
|
112
|
+
```bash
|
|
113
|
+
docker compose --profile prod up
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Configuration
|
|
117
|
+
|
|
118
|
+
### Database Settings
|
|
119
|
+
|
|
120
|
+
The database component uses SQLite with the following default configuration:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Environment variables (add to .env file)
|
|
124
|
+
DATABASE_URL=sqlite:///data/app.db # Database file location
|
|
125
|
+
DATABASE_ENGINE_ECHO=false # Enable SQL query logging
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Database Usage
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from app.core.db import db_session
|
|
132
|
+
from sqlmodel import SQLModel, Field, select
|
|
133
|
+
|
|
134
|
+
# Define a model
|
|
135
|
+
class User(SQLModel, table=True):
|
|
136
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
137
|
+
name: str
|
|
138
|
+
email: str
|
|
139
|
+
|
|
140
|
+
# Use the database
|
|
141
|
+
with db_session() as session:
|
|
142
|
+
user = User(name="John Doe", email="john@example.com")
|
|
143
|
+
session.add(user)
|
|
144
|
+
# Auto-committed by context manager
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Project Structure
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
clean-validation/
|
|
151
|
+
├── app/ # Application code
|
|
152
|
+
│ ├── components/ # Component implementations
|
|
153
|
+
│ │ ├── backend/ # FastAPI backend
|
|
154
|
+
│ │ └── frontend/ # Flet frontend
|
|
155
|
+
│ │ └── scheduler/ # APScheduler background tasks
|
|
156
|
+
│ ├── cli/ # CLI commands and health monitoring
|
|
157
|
+
│ ├── core/ # Core utilities
|
|
158
|
+
│ │ ├── config.py # Environment-dependent configuration
|
|
159
|
+
│ │ ├── constants.py # Immutable constants (12-Factor App)
|
|
160
|
+
│ │ ├── db.py # Database connection and session management
|
|
161
|
+
│ │ └── log.py # Structured logging
|
|
162
|
+
│ ├── entrypoints/ # Execution entry points
|
|
163
|
+
│ ├── integrations/ # App composition layer
|
|
164
|
+
├── tests/ # Test suite
|
|
165
|
+
├── docs/ # Documentation
|
|
166
|
+
├── docker-compose.yml # Docker services
|
|
167
|
+
└── pyproject.toml # Project configuration
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
Generated with [Aegis Stack](https://github.com/lbedner/aegis-stack) 🛡️
|
aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
|
|
2
|
+
x-app: &app
|
|
3
|
+
image: ${AEGIS_STACK_TAG:-aegis-stack:latest}
|
|
4
|
+
build:
|
|
5
|
+
context: .
|
|
6
|
+
args:
|
|
7
|
+
- AEGIS_STACK_VERSION=${AEGIS_STACK_VERSION:-dev}
|
|
8
|
+
- PORT=${PORT:-8000}
|
|
9
|
+
env_file:
|
|
10
|
+
- ${AEGIS_STACK_ENV_FILE:-.env}
|
|
11
|
+
volumes:
|
|
12
|
+
- .:/code
|
|
13
|
+
# Exclude .venv to prevent host/container virtual environment conflicts
|
|
14
|
+
- /code/.venv
|
|
15
|
+
environment:
|
|
16
|
+
# Docker container marker for entrypoint script
|
|
17
|
+
- DOCKER_CONTAINER=1
|
|
18
|
+
- PORT=${PORT:-8000}
|
|
19
|
+
labels:
|
|
20
|
+
logging: "aegis-stack"
|
|
21
|
+
|
|
22
|
+
services:
|
|
23
|
+
# DEVELOPMENT PROFILE
|
|
24
|
+
|
|
25
|
+
webserver:
|
|
26
|
+
<<: *app
|
|
27
|
+
command:
|
|
28
|
+
- webserver
|
|
29
|
+
ports:
|
|
30
|
+
- "${PORT:-8000}:${PORT:-8000}"
|
|
31
|
+
healthcheck:
|
|
32
|
+
test: ["CMD", "curl", "-f", "http://localhost:${PORT:-8000}/health/"]
|
|
33
|
+
interval: 30s
|
|
34
|
+
timeout: 10s
|
|
35
|
+
retries: 3
|
|
36
|
+
start_period: 40s
|
|
37
|
+
restart: unless-stopped
|
|
38
|
+
deploy:
|
|
39
|
+
resources:
|
|
40
|
+
limits:
|
|
41
|
+
memory: 512M
|
|
42
|
+
cpus: '0.5'
|
|
43
|
+
reservations:
|
|
44
|
+
memory: 256M
|
|
45
|
+
cpus: '0.25'
|
|
46
|
+
profiles:
|
|
47
|
+
- dev
|
|
48
|
+
# Scheduler service (runs scheduler tasks independently)
|
|
49
|
+
scheduler:
|
|
50
|
+
<<: *app
|
|
51
|
+
command:
|
|
52
|
+
- scheduler
|
|
53
|
+
restart: unless-stopped
|
|
54
|
+
deploy:
|
|
55
|
+
resources:
|
|
56
|
+
limits:
|
|
57
|
+
memory: 256M
|
|
58
|
+
cpus: '0.25'
|
|
59
|
+
reservations:
|
|
60
|
+
memory: 128M
|
|
61
|
+
cpus: '0.1'
|
|
62
|
+
profiles:
|
|
63
|
+
- dev
|
|
64
|
+
- prod
|
|
65
|
+
|
|
66
|
+
# TEST PROFILE
|
|
67
|
+
|
|
68
|
+
test_runner:
|
|
69
|
+
<<: *app
|
|
70
|
+
command:
|
|
71
|
+
- test
|
|
72
|
+
env_file:
|
|
73
|
+
- ${AEGIS_STACK_ENV_FILE:-.env}
|
|
74
|
+
profiles:
|
|
75
|
+
- test
|
|
76
|
+
|
|
77
|
+
volumes:
|
|
78
|
+
aegis-data:
|