core-framework 3.0.0__tar.gz → 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/constitution.mdc +6 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/code-review/SKILL.md +1 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/workflows/_deploy.yml +5 -3
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/workflows/dev-ci-cd.yaml +2 -3
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/workflows/manual-deployment.yaml +0 -1
- core_framework-3.1.0/.github/workflows/manual-observability-deployment.yaml +225 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/workflows/test.yaml +23 -6
- {core_framework-3.0.0 → core_framework-3.1.0}/.gitignore +3 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.pre-commit-config.yaml +3 -12
- {core_framework-3.0.0 → core_framework-3.1.0}/CHANGELOG.md +58 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/PKG-INFO +27 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/README.md +18 -2
- core_framework-3.1.0/alembic/notification/alembic/versions/2fdd68777706_notification_read_at_retention_index.py +28 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/config.toml +3 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/config.toml.template +3 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/cache/schemas.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/authenticated/router.py +8 -5
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/authenticated/schemas.py +5 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/authenticated/router.py +11 -5
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/authenticated/schemas.py +5 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/refresh_service.py +6 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/README.md +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/notification_service.py +34 -44
- core_framework-3.1.0/core_framework/application/notifications/prune_service.py +8 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/events.py +4 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/polling_service.py +8 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/processing_service.py +24 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/aggregation_service.py +1 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/authenticated_service.py +2 -1
- core_framework-3.1.0/core_framework/application/shared/worker_jobs.py +62 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/admin_service.py +2 -2
- core_framework-3.1.0/core_framework/core/context.py +40 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/database.py +6 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/exception_handlers/common.py +19 -16
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/http_client.py +1 -1
- core_framework-3.1.0/core_framework/core/http_probes.py +4 -0
- core_framework-3.1.0/core_framework/core/logging.py +120 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/middleware.py +60 -11
- core_framework-3.1.0/core_framework/core/observability.py +648 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/pagination.py +4 -7
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/redis.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/settings.py +37 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/service.py +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/repository.py +1 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/service.py +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/README.md +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/repository.py +26 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/service.py +20 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/models.py +1 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/repository.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/service.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/utils.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/pillow_staging_image.py +3 -6
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/ssh_attachment_finals_publisher_adapter.py +32 -28
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +28 -24
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +39 -35
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/outbox/outbox_consumer_adapter.py +3 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/main.py +15 -3
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/arq.py +3 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/auth.py +9 -6
- core_framework-3.1.0/core_framework/testing/firebase.py +132 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/httpx_test_client.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/plugin.py +11 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/main.py +24 -13
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/__init__.py +8 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +4 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +4 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +4 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_expired_account_deletions.py +4 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +4 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_prune_analytics_daily_facts.py +1 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_prune_post_views.py +1 -2
- core_framework-3.1.0/core_framework/worker/schedules/schedule_prune_read_notifications.py +16 -0
- core_framework-3.1.0/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +17 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/__init__.py +2 -0
- core_framework-3.1.0/deploy/README.md +27 -0
- core_framework-3.1.0/deploy/observability/.env.example +7 -0
- core_framework-3.1.0/deploy/observability/README.md +11 -0
- core_framework-3.1.0/deploy/observability/docker-compose.yml +153 -0
- core_framework-3.1.0/deploy/observability/grafana/dashboards/application/api-http.json +297 -0
- core_framework-3.1.0/deploy/observability/grafana/dashboards/application/worker-jobs.json +250 -0
- core_framework-3.1.0/deploy/observability/grafana/dashboards/infrastructure/node-exporter.json +23900 -0
- core_framework-3.1.0/deploy/observability/grafana/dashboards/infrastructure/postgres-exporter.json +1453 -0
- core_framework-3.1.0/deploy/observability/grafana/dashboards/infrastructure/redis-exporter.json +1620 -0
- core_framework-3.1.0/deploy/observability/grafana/provisioning/dashboards/dashboards.yml +26 -0
- core_framework-3.1.0/deploy/observability/grafana/provisioning/datasources/datasources.yml +49 -0
- core_framework-3.1.0/deploy/observability/loki.yaml +61 -0
- core_framework-3.1.0/deploy/observability/otel-collector-config.yaml +54 -0
- core_framework-3.1.0/deploy/observability/prometheus.yml +39 -0
- core_framework-3.1.0/deploy/observability/targets.example/README.md +19 -0
- core_framework-3.1.0/deploy/observability/targets.example/node.yml.example +9 -0
- core_framework-3.1.0/deploy/observability/targets.example/postgres.yml.example +5 -0
- core_framework-3.1.0/deploy/observability/targets.example/redis.yml.example +6 -0
- core_framework-3.1.0/deploy/observability/tempo.yaml +30 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/README.md +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/README.md +15 -11
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/deploy-playbook.md +39 -10
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/examples/Caddyfile.example +3 -0
- core_framework-3.1.0/docs/deployments/examples/Caddyfile.observability.example +13 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/playbook/postgres-backup-playbook.md +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/caddy-setup.md +1 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/cloudflare-setup.md +37 -11
- core_framework-3.1.0/docs/deployments/guides/setup/observability-lgtm-setup.md +204 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/postgres-setup.md +9 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/redis-setup.md +9 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/ubuntu-server-setup.md +10 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/release-playbook.md +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/README.md +11 -10
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/create-idempotency-design.md +18 -20
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/event-outbox-design.md +1 -1
- core_framework-3.1.0/docs/design/observability-lgtm-design.md +591 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/create_comment.md +20 -6
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/post-comment-attachments-design.md +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/notifications/notification_inbox.md +6 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/create_post.md +14 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/core-framework-migration.md +3 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/overview.md +3 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/package-api.md +104 -23
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/testing-plugin-design.md +9 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/workers.md +22 -16
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/architecture-decisions.md +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/conventions.md +4 -3
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/reviews/review-playbook.md +1 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/reviews/slices.md +21 -10
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/testing.md +2 -2
- core_framework-3.1.0/docs/todo.md +4 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/makefile +1 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/pyproject.toml +41 -26
- core_framework-3.1.0/tach.toml +176 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/analytics/_helpers.py +15 -14
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_destructive_delete_helpers.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_http_helpers.py +18 -29
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_user_deletion_helpers.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_user_helpers.py +3 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/analytics/router_test.py +0 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/cache/router_test.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/comments/router_test.py +0 -14
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/moderation/router_test.py +0 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/outbox/router_test.py +12 -13
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/posts/router_test.py +8 -17
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/attachments/_helpers.py +43 -33
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +18 -22
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/comments/comment_attachments_integration_test.py +0 -12
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/comments/public/router_test.py +0 -14
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/create_idempotency_integration_test.py +12 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/events/router_test.py +0 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/mentions/mentions_integration_test.py +0 -13
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/notifications/router_test.py +0 -7
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +10 -19
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/followers_visibility_test.py +2 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/post_attachments_integration_test.py +11 -28
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/post_deletion_integration_test.py +0 -18
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/post_stats_dirty_marking_test.py +0 -7
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/posts/public/router_test.py +0 -41
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/authenticated/router_test.py +10 -5
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/deletion_audit_integration_test.py +5 -3
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/user_deletion_integration_test.py +0 -8
- core_framework-3.1.0/tests/integration/worker/_media_upload_helpers.py +84 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/account_deletion_test.py +7 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/aggregate_comment_stats_test.py +4 -10
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/aggregate_post_stats_test.py +2 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/aggregate_user_stats_test.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/analytics_refresh_test.py +0 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/avatar_upload_test.py +8 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/banner_upload_test.py +8 -8
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/create_idempotency_retention_test.py +0 -5
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/moderation_outbox_test.py +5 -6
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/mute_lift_test.py +7 -7
- core_framework-3.1.0/tests/integration/worker/read_notifications_retention_test.py +169 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/user_outbox_test.py +0 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/utils_test.py +37 -40
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/core/bundled_alembic_test.py +3 -5
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/core/pagination_test.py +14 -13
- core_framework-3.1.0/tests/unit/domains/__init__.py +0 -0
- core_framework-3.1.0/tests/unit/domains/comment/__init__.py +0 -0
- core_framework-3.1.0/tests/unit/infrastructure/__init__.py +0 -0
- core_framework-3.1.0/tests/unit/infrastructure/media/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +18 -14
- {core_framework-3.0.0 → core_framework-3.1.0}/uv.lock +213 -102
- core_framework-3.0.0/core_framework/application/shared/worker_jobs.py +0 -19
- core_framework-3.0.0/core_framework/core/context.py +0 -14
- core_framework-3.0.0/core_framework/core/logging.py +0 -79
- core_framework-3.0.0/core_framework/core/observability.py +0 -31
- core_framework-3.0.0/core_framework/testing/firebase.py +0 -95
- core_framework-3.0.0/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +0 -23
- core_framework-3.0.0/docs/todo.md +0 -71
- core_framework-3.0.0/tests/integration/worker/_media_upload_helpers.py +0 -77
- {core_framework-3.0.0 → core_framework-3.1.0}/.agents/skills/fastapi +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.agents/skills/library-skills/.library-skills.json +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.agents/skills/library-skills/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/alembic-migrations.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/api-layer.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/api-reference-docs.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/api-validation.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/application-layer.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/constants-final.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/database-triggers.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/docstrings.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/domain-caller-context.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/domain-imports.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/domain-input-guards.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/domain-services-and-adapters.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/error-boundary.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/flow-documentation.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/inline-raise-messages.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/integration-test-strategy.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/layer-boundaries.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/no-code-in-docs.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/postgres-config-conventions.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/repository-schema-isolation.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/strong-reads.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/rules/structured-logging.mdc +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/add-config/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/add-domain/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/fastapi +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/implement-feature/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/recommend-features/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/sync-host-rules/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.cursor/skills/write-flow-doc/SKILL.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.dockerignore +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/ci/package-lock.json +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/ci/package.json +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.github/workflows/publish-pypi.yml +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/.python-version +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/LICENSE +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/versions/2d61a5e88d76_analytics_utm_events_add_kind.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/versions/585105e1149e_analytics_add_utm_events.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/versions/5b9ac98bb150_analytics_daily_fact.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic/versions/7f2a9c1d4e8b_analytics_daily_fact_day_index.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/analytics/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/comment_add_comment_attachments.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency_created_at_index.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/comment_add_comment_mentions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/comment_tombstone_status_model.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/comment/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/extension/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/extension/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/extension/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/extension/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/versions/media_add_attachment_staging_registry.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/versions/media_attachment_staging_registry_published_at.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/media/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/versions/moderation_add_event_outbox.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/versions/moderation_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/versions/moderation_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/moderation/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/notification/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/notification/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/notification/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/notification/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_add_post_attachments.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_add_post_create_idempotency.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_add_post_create_idempotency_created_at_index.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_add_post_mentions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_post_views_retention_high_water_mark.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/post_tombstone_status_model.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/post/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/README +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/env.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/script.py.mako +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/44df70a45ba6_user_add_signup_events.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_event_outbox.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/user_reserve_sentinel_user_ids.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/alembic/user/alembic.ini +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/analytics/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/analytics/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/analytics/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/cache/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/cache/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/comments/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/comments/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/comments/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/moderation/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/moderation/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/moderation/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/outbox/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/outbox/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/outbox/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/posts/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/posts/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/posts/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/users/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/users/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/admin/users/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/attachments/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/attachments/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/attachments/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/auth/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/auth/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/auth/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/authenticated/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/authenticated/mappers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/public/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/public/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/public/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/comments/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/dependencies.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/events/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/events/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/events/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/idempotency/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/idempotency/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/notifications/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/notifications/authenticated/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/notifications/authenticated/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/notifications/authenticated/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/notifications/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/authenticated/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/authenticated/mappers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/public/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/public/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/public/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/posts/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/system/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/system/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/upload.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/authenticated/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/authenticated/mappers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/authenticated/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/authenticated/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/mappers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/public/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/public/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/public/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/router.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/shared/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/api/users/shared/schemas.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/bucket_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/prune_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/read_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/registry.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/sources/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/sources/comment_created.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/sources/post_created.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/sources/post_viewed.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/analytics/sources/user_registered.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/auth/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/auth/access_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/auth/auth_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/auth/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/auth/token_verification.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/bootstrap.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/cache/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/cache/invalidate_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/cache/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/admin_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/aggregation_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/authenticated_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/cleanup_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/comments/public_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/event_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/event_token.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/events/utm_capture_kinds.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/attachment_read.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/attachment_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/avatar_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/banner_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/ingest_guards.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/media/read_url_config.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/appeal_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/moderator_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/report_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/scheduled_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/moderation/user_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/inbox_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/notifications/mute_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/block_mirrors.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/follow_mirrors.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/handlers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/ops_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/outbox/restriction_mirrors.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/admin_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/cleanup_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/posts/public_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/shared/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/shared/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/shared/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/shared/request_context.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/aggregation_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/authenticated_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/deletion_audit.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/public_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/scheduled_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/application/users/user_deletion_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/asgi.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/bundled_alembic.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/__init__.py +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/cache.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/exception_handlers/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/exception_handlers/application.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/exception_handlers/setup.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/firebase.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/core/runtime.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/__init__.py +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/dependencies.py +2 -2
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/ports/activity_source.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/analytics/repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/ports/auth.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/auth/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/__init__.py +12 -12
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/dependencies.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/outcomes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/comment/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/__init__.py +4 -4
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/components/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/components/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/components/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/components/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/ports/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/ports/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/ports/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/attachment/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/components/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/components/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/components/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/components/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/ports/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/ports/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/ports/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/avatar/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/components/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/components/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/components/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/components/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/ports/finals_publisher.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/ports/staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/ports/variant_encoder.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/banner/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/outcomes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/media/shared/utils.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/__init__.py +12 -12
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/outbox_repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/outbox_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/outcomes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/moderation/repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/__init__.py +1 -1
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/notification/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/ports/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/ports/admin.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/ports/consumer.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/ports/producer.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/outbox/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/__init__.py +9 -9
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/outcomes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/post/service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/repository_sql.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/__init__.py +11 -11
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/constants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/dependencies.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/enums.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/exceptions.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/models.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/outbox_repository.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/outbox_service.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/outcomes.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/domains/user/utils.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/firebase/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/firebase/firebase_auth_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/attachment_staging_display_geometry.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/local_attachment_staging_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/local_avatar_staging_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/local_banner_staging_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/pillow_attachment_variant_encoder_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/media/staging_paths.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/outbox/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/infrastructure/outbox/outbox_producer_adapter.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/migrate_cli.py +0 -0
- /core_framework-3.0.0/core_framework/worker/__init__.py → /core_framework-3.1.0/core_framework/py.typed +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/config.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/containers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/firebase_identity_toolkit.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/hookspecs.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/media.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/testing/migrations.py +0 -0
- {core_framework-3.0.0/tests → core_framework-3.1.0/core_framework/worker}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/analytics_refresh_cron.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_poll_outbox.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_refresh_analytics.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_sweep_stale_attachment_staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/delete_attachment_finals.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/delete_superseded_banner_finals.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_account_deletion.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_admin_user_deletion.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_aggregate_comment_stats.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_aggregate_post_stats.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_aggregate_user_stats.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_attachment_asset_variants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_banner_asset_variants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_cache_pattern_invalidation.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_destructive_comment_delete.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_destructive_post_delete.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_media_asset_variants.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_mute_lift.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_outbox_row.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_refresh_analytics_bucket.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/tasks/process_user_content_deletion.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/core_framework/worker/worker_context.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0/deploy/app}/docker-compose.dev.yaml +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0/deploy/app}/docker-compose.yml +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0/deploy/app}/dockerfile +0 -0
- /core_framework-3.0.0/tests/integration/__init__.py → /core_framework-3.1.0/deploy/observability/targets/node/.gitkeep +0 -0
- /core_framework-3.0.0/tests/integration/api/__init__.py → /core_framework-3.1.0/deploy/observability/targets/postgres/.gitkeep +0 -0
- /core_framework-3.0.0/tests/integration/api/admin/__init__.py → /core_framework-3.1.0/deploy/observability/targets/redis/.gitkeep +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/e2e-smoke-tests-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/edge-rate-limits.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/edge-upload-limits.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/examples/image-server-known-hosts.example +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/playbook/py-spy-playbook.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/app-server-deploy-ssh.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/image-server-ssh.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/postgres-backup-setup.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/guides/setup/py-spy-setup.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/deployments/postgres-backup-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/analytics-rollup-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/cache-invalidation-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/events-ingest-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/media-storage-topology.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/outbox-admin-ops-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/design/utm-events-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/analytics/admin_analytics_reads.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/auth/access_control.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/auth/registration.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/cache/admin_cache_invalidation.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/admin_comments.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/comment_like.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/comment_report.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/comment_stats_aggregation.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/delete_comment.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/edit_comment.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/comments/retrieve_comments.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/deletion/comments.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/deletion/overview.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/deletion/posts.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/deletion/users.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/events/events.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/attachment_upload.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/avatar-upload-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/banner-upload-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/upload-pipeline-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/media/upload_pipeline.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/mentions/mentions_in_content.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/appeals.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/internal_notes.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/moderator_actions.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/reports.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/moderation/restrictions.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/outbox/admin_outbox_ops.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/admin_posts.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/author_context.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/delete_post.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/edit_post.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/hashtag_discovery.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/post_like.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/post_report.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/post_stats_aggregation.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/post_visibility.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/posts/retrieve_posts.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/account.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/account_deletion.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/admin_users.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/avatar.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/banner.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/blocks.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/change_history.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/check_username_exists.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/follow-system-design.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/follow.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/my_posts_and_comments.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/preferences.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/profile.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/public_profile.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/user_removal.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/domains/users/user_stats_aggregation.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/api.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/library/capability-wiring.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/client-error-visibility.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/database-triggers.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/domain-services-and-adapters.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/layers-and-boundaries.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/platform/patch-update-typed-payload.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/reviews/README.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/docs/reviews/log.md +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/firebase_config.example.json +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/analytics → core_framework-3.1.0/tests}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/conftest.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/_auth.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/_canaries.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/_media.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/_settings.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/_upload_payloads.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/conftest.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/media/pipeline_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/smoke/canary_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/smoke/media_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/smoke/system_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/e2e/smoke/tls_host_test.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/cache → core_framework-3.1.0/tests/integration}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/_http_error_details.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/comments → core_framework-3.1.0/tests/integration/api}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_auth_helpers.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/_outbox_helpers.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/moderation → core_framework-3.1.0/tests/integration/api/admin}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/_auth_cases.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/outbox → core_framework-3.1.0/tests/integration/api/admin/analytics}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/posts → core_framework-3.1.0/tests/integration/api/admin/cache}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/admin/users → core_framework-3.1.0/tests/integration/api/admin/comments}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/auth → core_framework-3.1.0/tests/integration/api/admin/moderation}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/moderation/_auth_cases.py +0 -0
- {core_framework-3.0.0/tests/integration/api/comments → core_framework-3.1.0/tests/integration/api/admin/outbox}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/comments/authenticated → core_framework-3.1.0/tests/integration/api/admin/posts}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/comments/public → core_framework-3.1.0/tests/integration/api/admin/users}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/admin/users/router_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/attachments/attachment_upload_test.py +0 -0
- {core_framework-3.0.0/tests/integration/api/notifications → core_framework-3.1.0/tests/integration/api/auth}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/auth/router_test.py +0 -0
- {core_framework-3.0.0/tests/integration/api/posts → core_framework-3.1.0/tests/integration/api/comments}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/posts/public → core_framework-3.1.0/tests/integration/api/comments/authenticated}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/system → core_framework-3.1.0/tests/integration/api/comments/public}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/media/ingest_contract_test.py +0 -0
- {core_framework-3.0.0/tests/integration/api/users → core_framework-3.1.0/tests/integration/api/notifications}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/users/authenticated → core_framework-3.1.0/tests/integration/api/posts}/__init__.py +0 -0
- {core_framework-3.0.0/tests/integration/api/users → core_framework-3.1.0/tests/integration/api/posts}/public/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/public_read_by_id_unavailable_detail_test.py +0 -0
- {core_framework-3.0.0/tests/integration/worker → core_framework-3.1.0/tests/integration/api/system}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/system/router_test.py +0 -0
- {core_framework-3.0.0/tests/unit → core_framework-3.1.0/tests/integration/api/users}/__init__.py +0 -0
- {core_framework-3.0.0/tests/unit/application/comments → core_framework-3.1.0/tests/integration/api/users/authenticated}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/authenticated/avatar_upload_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/authenticated/banner_upload_test.py +0 -0
- {core_framework-3.0.0/tests/unit/domains → core_framework-3.1.0/tests/integration/api/users/public}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/api/users/public/router_test.py +0 -0
- {core_framework-3.0.0/tests/unit/domains/comment → core_framework-3.1.0/tests/integration/worker}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/analytics_prune_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/attachment_upload_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/conftest.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/integration/worker/stale_staging_sweep_test.py +0 -0
- {core_framework-3.0.0/tests/unit/infrastructure → core_framework-3.1.0/tests/unit}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/api/comments/authenticated/comment_request_schemas_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/api/dedupe_preserving_order_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/api/posts/authenticated/post_update_mapper_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/api/users/profile_update_mapper_test.py +0 -0
- {core_framework-3.0.0/tests/unit/infrastructure/media → core_framework-3.1.0/tests/unit/application/comments}/__init__.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/application/events/event_service_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/application/notifications/inbox_service_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/application/shared/request_context_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/application/users/deletion_audit_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/core/migrate_cli_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/docs/_api_reference.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/docs/api_routes_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/domains/post/models_test.py +0 -0
- {core_framework-3.0.0 → core_framework-3.1.0}/tests/unit/domains/user/service_test.py +0 -0
|
@@ -16,7 +16,12 @@ alwaysApply: true
|
|
|
16
16
|
|
|
17
17
|
- Python 3.14, Pydantic v2, PostgreSQL 18, orjson (not stdlib json).
|
|
18
18
|
- Absolute imports only (`from core_framework....`). Comma-style `except A, B:` is intentional.
|
|
19
|
-
- Prefer newer APIs
|
|
19
|
+
- Prefer newer APIs and **current Python syntax** over older equivalents still legal on 3.14, for example:
|
|
20
|
+
- `asyncio.TaskGroup` over `asyncio.gather`
|
|
21
|
+
- PEP 695 type parameters (`def f[T](...)`, `def f[**P, R](...)`) over module-level `TypeVar` / `ParamSpec`
|
|
22
|
+
- Built-in generics (`list[str]`, `dict[str, int]`) over `typing.List` / `typing.Dict`
|
|
23
|
+
- `X | Y` over `Optional[X]` / `Union[X, Y]` unless a library API requires the old form
|
|
24
|
+
- Do **not** add `from __future__ import annotations` — 3.14 deferred annotations are the default (PEP 649)
|
|
20
25
|
|
|
21
26
|
## Layers
|
|
22
27
|
|
|
@@ -28,6 +28,7 @@ Do **not** flag documented accepted trade-offs in **`docs/platform/architecture-
|
|
|
28
28
|
- API: thin routers, validation in schemas, orchestration in application — **fastapi** skill (`.agents/skills/fastapi/`) + **`api-layer`** / **`api-validation`** / **`error-boundary`** rules.
|
|
29
29
|
- Domain: imports only via **`__init__.py`** / **`dependencies`** from outer layers; no caller-context names (**`domain-caller-context`**).
|
|
30
30
|
- Read-after-write refetches use **`*_strong`** where applicable.
|
|
31
|
+
- **Python modernity (constitution):** prefer current 3.14 syntax in reviewed code — PEP 695 type params over module-level `TypeVar`/`ParamSpec`; no unnecessary `from __future__ import annotations`; builtins / `X | Y` over legacy `typing` aliases; `asyncio.TaskGroup` over `gather`.
|
|
31
32
|
|
|
32
33
|
## Parallel drift
|
|
33
34
|
|
|
@@ -20,8 +20,6 @@ on:
|
|
|
20
20
|
required: true
|
|
21
21
|
READ_POSTGRES_PASSWORD:
|
|
22
22
|
required: true
|
|
23
|
-
LOGFIRE_TOKEN:
|
|
24
|
-
required: true
|
|
25
23
|
FIREBASE_CONFIG:
|
|
26
24
|
required: true
|
|
27
25
|
IMAGE_SERVER_SSH_PRIVATE_KEY:
|
|
@@ -79,13 +77,14 @@ jobs:
|
|
|
79
77
|
IMAGE_SERVER_HOST: ${{ vars.IMAGE_SERVER_HOST }}
|
|
80
78
|
IMAGE_SERVER_PORT: ${{ vars.IMAGE_SERVER_PORT }}
|
|
81
79
|
IMAGE_SERVER_USER: ${{ vars.IMAGE_SERVER_USER }}
|
|
82
|
-
LOGFIRE_TOKEN: ${{ secrets.LOGFIRE_TOKEN }}
|
|
83
80
|
OBSERVABILITY_ENABLED: ${{ vars.OBSERVABILITY_ENABLED }}
|
|
81
|
+
OBSERVABILITY_OTLP_ENDPOINT: ${{ vars.OBSERVABILITY_OTLP_ENDPOINT }}
|
|
84
82
|
PROFILING_KEY: ${{ vars.PROFILING_KEY }}
|
|
85
83
|
PROFILING_ENABLED: ${{ vars.PROFILING_ENABLED }}
|
|
86
84
|
LOG_LEVEL: ${{ vars.LOG_LEVEL }}
|
|
87
85
|
CORS_ALLOWED_ORIGINS: ${{ vars.CORS_ALLOWED_ORIGINS }}
|
|
88
86
|
RETENTION_POST_VIEWS_DAYS: ${{ vars.RETENTION_POST_VIEWS_DAYS }}
|
|
87
|
+
RETENTION_READ_NOTIFICATIONS_DAYS: ${{ vars.RETENTION_READ_NOTIFICATIONS_DAYS }}
|
|
89
88
|
ANALYTICS_REFRESH_INTERVAL_SECONDS: ${{ vars.ANALYTICS_REFRESH_INTERVAL_SECONDS }}
|
|
90
89
|
run: |
|
|
91
90
|
set -euo pipefail
|
|
@@ -150,6 +149,9 @@ jobs:
|
|
|
150
149
|
test -s image_server_known_hosts
|
|
151
150
|
chmod 644 image_server_known_hosts
|
|
152
151
|
|
|
152
|
+
- name: Stage docker-compose.yml for upload
|
|
153
|
+
run: cp deploy/app/docker-compose.yml ./docker-compose.yml
|
|
154
|
+
|
|
153
155
|
- name: Upload rendered config.toml, firebase_config.json and docker-compose.yml
|
|
154
156
|
uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0
|
|
155
157
|
with:
|
|
@@ -133,7 +133,7 @@ jobs:
|
|
|
133
133
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
134
134
|
with:
|
|
135
135
|
context: .
|
|
136
|
-
file: ./dockerfile
|
|
136
|
+
file: ./deploy/app/dockerfile
|
|
137
137
|
target: api
|
|
138
138
|
push: true
|
|
139
139
|
tags: ${{ steps.meta.outputs.tags }}
|
|
@@ -170,7 +170,7 @@ jobs:
|
|
|
170
170
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
171
171
|
with:
|
|
172
172
|
context: .
|
|
173
|
-
file: ./dockerfile
|
|
173
|
+
file: ./deploy/app/dockerfile
|
|
174
174
|
target: worker
|
|
175
175
|
push: true
|
|
176
176
|
tags: ${{ steps.meta.outputs.tags }}
|
|
@@ -187,7 +187,6 @@ jobs:
|
|
|
187
187
|
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
|
188
188
|
WRITE_POSTGRES_PASSWORD: ${{ secrets.WRITE_POSTGRES_PASSWORD }}
|
|
189
189
|
READ_POSTGRES_PASSWORD: ${{ secrets.READ_POSTGRES_PASSWORD }}
|
|
190
|
-
LOGFIRE_TOKEN: ${{ secrets.LOGFIRE_TOKEN }}
|
|
191
190
|
FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }}
|
|
192
191
|
IMAGE_SERVER_SSH_PRIVATE_KEY: ${{ secrets.IMAGE_SERVER_SSH_PRIVATE_KEY }}
|
|
193
192
|
IMAGE_SERVER_KNOWN_HOSTS: ${{ secrets.IMAGE_SERVER_KNOWN_HOSTS }}
|
|
@@ -45,7 +45,6 @@ jobs:
|
|
|
45
45
|
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
|
46
46
|
WRITE_POSTGRES_PASSWORD: ${{ secrets.WRITE_POSTGRES_PASSWORD }}
|
|
47
47
|
READ_POSTGRES_PASSWORD: ${{ secrets.READ_POSTGRES_PASSWORD }}
|
|
48
|
-
LOGFIRE_TOKEN: ${{ secrets.LOGFIRE_TOKEN }}
|
|
49
48
|
FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }}
|
|
50
49
|
IMAGE_SERVER_SSH_PRIVATE_KEY: ${{ secrets.IMAGE_SERVER_SSH_PRIVATE_KEY }}
|
|
51
50
|
IMAGE_SERVER_KNOWN_HOSTS: ${{ secrets.IMAGE_SERVER_KNOWN_HOSTS }}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
name: Manual Observability Deployment
|
|
2
|
+
|
|
3
|
+
# Syncs deploy/observability/ to the LGTM host and runs docker compose up -d
|
|
4
|
+
# --force-recreate --remove-orphans (so bind-mounted config changes reload).
|
|
5
|
+
# Uses OBSERVABILITY_DEPLOY_* (not DEPLOY_SERVER_*) so the stack can move hosts later.
|
|
6
|
+
# Optional PROMETHEUS_TARGETS_{NODE,POSTGRES,REDIS} (GitHub Environment vars) are
|
|
7
|
+
# written to targets/*/hosts.yml at stage time — host inventory stays out of the repo.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
environment:
|
|
13
|
+
description: "Target environment (development or production)"
|
|
14
|
+
required: true
|
|
15
|
+
type: choice
|
|
16
|
+
options:
|
|
17
|
+
- development
|
|
18
|
+
- production
|
|
19
|
+
confirm:
|
|
20
|
+
description: "Type the environment name to confirm (development or production)"
|
|
21
|
+
required: true
|
|
22
|
+
|
|
23
|
+
permissions: {}
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
validate:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
permissions: {}
|
|
29
|
+
steps:
|
|
30
|
+
- name: Validate confirmation
|
|
31
|
+
env:
|
|
32
|
+
CONFIRM: ${{ inputs.confirm }}
|
|
33
|
+
ENVIRONMENT: ${{ inputs.environment }}
|
|
34
|
+
run: |
|
|
35
|
+
if [ "$CONFIRM" != "$ENVIRONMENT" ]; then
|
|
36
|
+
echo "Deployment cancelled: confirmation mismatch."
|
|
37
|
+
echo "Expected: '$ENVIRONMENT', got: '$CONFIRM'"
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
deploy:
|
|
42
|
+
needs: validate
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment: ${{ inputs.environment }}
|
|
45
|
+
permissions:
|
|
46
|
+
contents: read
|
|
47
|
+
steps:
|
|
48
|
+
- name: Checkout code
|
|
49
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
50
|
+
with:
|
|
51
|
+
persist-credentials: false
|
|
52
|
+
|
|
53
|
+
# Stage as staging/observability (not deploy/observability). Upload uses
|
|
54
|
+
# strip_components: 1 so remote is .../app_configs/observability.
|
|
55
|
+
# Host scrape inventory comes from GitHub Environment vars (not the repo).
|
|
56
|
+
- name: Stage observability stack for upload
|
|
57
|
+
env:
|
|
58
|
+
PROMETHEUS_TARGETS_NODE: ${{ vars.PROMETHEUS_TARGETS_NODE }}
|
|
59
|
+
PROMETHEUS_TARGETS_POSTGRES: ${{ vars.PROMETHEUS_TARGETS_POSTGRES }}
|
|
60
|
+
PROMETHEUS_TARGETS_REDIS: ${{ vars.PROMETHEUS_TARGETS_REDIS }}
|
|
61
|
+
run: |
|
|
62
|
+
set -euo pipefail
|
|
63
|
+
mkdir -p staging/observability
|
|
64
|
+
cp -a deploy/observability/. staging/observability/
|
|
65
|
+
rm -f staging/observability/.env
|
|
66
|
+
rm -rf staging/observability/targets.example
|
|
67
|
+
mkdir -p \
|
|
68
|
+
staging/observability/targets/node \
|
|
69
|
+
staging/observability/targets/postgres \
|
|
70
|
+
staging/observability/targets/redis
|
|
71
|
+
rm -f staging/observability/targets/*/.gitkeep
|
|
72
|
+
python3 -m pip install --user -q pyyaml
|
|
73
|
+
python3 <<'PY'
|
|
74
|
+
import os
|
|
75
|
+
import sys
|
|
76
|
+
from pathlib import Path
|
|
77
|
+
|
|
78
|
+
import yaml
|
|
79
|
+
|
|
80
|
+
def write_targets(dest, body, var_name):
|
|
81
|
+
text = body or ""
|
|
82
|
+
stripped = text.strip()
|
|
83
|
+
path = Path(dest)
|
|
84
|
+
if not stripped:
|
|
85
|
+
path.write_text("[]\n", encoding="utf-8")
|
|
86
|
+
print(f"{var_name}: empty → []")
|
|
87
|
+
return
|
|
88
|
+
try:
|
|
89
|
+
data = yaml.safe_load(text)
|
|
90
|
+
except yaml.YAMLError as exc:
|
|
91
|
+
print(f"ERROR: {var_name} is not valid YAML: {exc}", file=sys.stderr)
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
if data is None:
|
|
94
|
+
# Comment-only or empty document
|
|
95
|
+
path.write_text("[]\n", encoding="utf-8")
|
|
96
|
+
print(f"{var_name}: comment-only/null → []")
|
|
97
|
+
return
|
|
98
|
+
if not isinstance(data, list):
|
|
99
|
+
print(
|
|
100
|
+
f"ERROR: {var_name} must be a YAML list of file_sd target groups, "
|
|
101
|
+
f"got {type(data).__name__}",
|
|
102
|
+
file=sys.stderr,
|
|
103
|
+
)
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
out = text if text.endswith("\n") else text + "\n"
|
|
106
|
+
path.write_text(out, encoding="utf-8")
|
|
107
|
+
print(f"{var_name}: wrote {len(data)} target group(s) → {dest}")
|
|
108
|
+
|
|
109
|
+
write_targets(
|
|
110
|
+
"staging/observability/targets/node/hosts.yml",
|
|
111
|
+
os.environ.get("PROMETHEUS_TARGETS_NODE", ""),
|
|
112
|
+
"PROMETHEUS_TARGETS_NODE",
|
|
113
|
+
)
|
|
114
|
+
write_targets(
|
|
115
|
+
"staging/observability/targets/postgres/hosts.yml",
|
|
116
|
+
os.environ.get("PROMETHEUS_TARGETS_POSTGRES", ""),
|
|
117
|
+
"PROMETHEUS_TARGETS_POSTGRES",
|
|
118
|
+
)
|
|
119
|
+
write_targets(
|
|
120
|
+
"staging/observability/targets/redis/hosts.yml",
|
|
121
|
+
os.environ.get("PROMETHEUS_TARGETS_REDIS", ""),
|
|
122
|
+
"PROMETHEUS_TARGETS_REDIS",
|
|
123
|
+
)
|
|
124
|
+
PY
|
|
125
|
+
|
|
126
|
+
- name: Ensure remote app_configs directory
|
|
127
|
+
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
|
128
|
+
env:
|
|
129
|
+
OBSERVABILITY_DEPLOY_USER: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
130
|
+
with:
|
|
131
|
+
host: ${{ vars.OBSERVABILITY_DEPLOY_HOST }}
|
|
132
|
+
username: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
133
|
+
key: ${{ secrets.OBSERVABILITY_DEPLOY_SSH_KEY }}
|
|
134
|
+
port: ${{ vars.OBSERVABILITY_DEPLOY_PORT }}
|
|
135
|
+
envs: OBSERVABILITY_DEPLOY_USER
|
|
136
|
+
script: |
|
|
137
|
+
set -euo pipefail
|
|
138
|
+
mkdir -p "/home/$OBSERVABILITY_DEPLOY_USER/app_configs"
|
|
139
|
+
|
|
140
|
+
# Drop any leftover file_sd YAML under targets/ before upload (SCP overwrite
|
|
141
|
+
# does not delete extras; Prometheus scrapes targets/*/*.yml).
|
|
142
|
+
- name: Reset remote Prometheus targets directory
|
|
143
|
+
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
|
144
|
+
env:
|
|
145
|
+
OBSERVABILITY_DEPLOY_USER: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
146
|
+
with:
|
|
147
|
+
host: ${{ vars.OBSERVABILITY_DEPLOY_HOST }}
|
|
148
|
+
username: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
149
|
+
key: ${{ secrets.OBSERVABILITY_DEPLOY_SSH_KEY }}
|
|
150
|
+
port: ${{ vars.OBSERVABILITY_DEPLOY_PORT }}
|
|
151
|
+
envs: OBSERVABILITY_DEPLOY_USER
|
|
152
|
+
script: |
|
|
153
|
+
set -euo pipefail
|
|
154
|
+
STACK_DIR="/home/$OBSERVABILITY_DEPLOY_USER/app_configs/observability"
|
|
155
|
+
mkdir -p "$STACK_DIR"
|
|
156
|
+
rm -rf "$STACK_DIR/targets"
|
|
157
|
+
mkdir -p \
|
|
158
|
+
"$STACK_DIR/targets/node" \
|
|
159
|
+
"$STACK_DIR/targets/postgres" \
|
|
160
|
+
"$STACK_DIR/targets/redis"
|
|
161
|
+
|
|
162
|
+
- name: Upload observability stack
|
|
163
|
+
uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0
|
|
164
|
+
with:
|
|
165
|
+
host: ${{ vars.OBSERVABILITY_DEPLOY_HOST }}
|
|
166
|
+
username: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
167
|
+
key: ${{ secrets.OBSERVABILITY_DEPLOY_SSH_KEY }}
|
|
168
|
+
port: ${{ vars.OBSERVABILITY_DEPLOY_PORT }}
|
|
169
|
+
# Stage path is staging/observability; strip "staging/" so remote is
|
|
170
|
+
# .../app_configs/observability (not .../app_configs/staging/observability).
|
|
171
|
+
source: "staging/observability"
|
|
172
|
+
target: "/home/${{ vars.OBSERVABILITY_DEPLOY_USER }}/app_configs"
|
|
173
|
+
strip_components: 1
|
|
174
|
+
overwrite: true
|
|
175
|
+
|
|
176
|
+
- name: Compose up on observability host
|
|
177
|
+
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
|
178
|
+
env:
|
|
179
|
+
OBSERVABILITY_DEPLOY_USER: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
180
|
+
GRAFANA_ADMIN_USER: ${{ vars.GRAFANA_ADMIN_USER }}
|
|
181
|
+
GRAFANA_ADMIN_PASSWORD: ${{ secrets.GRAFANA_ADMIN_PASSWORD }}
|
|
182
|
+
GRAFANA_ROOT_URL: ${{ vars.GRAFANA_ROOT_URL }}
|
|
183
|
+
with:
|
|
184
|
+
host: ${{ vars.OBSERVABILITY_DEPLOY_HOST }}
|
|
185
|
+
username: ${{ vars.OBSERVABILITY_DEPLOY_USER }}
|
|
186
|
+
key: ${{ secrets.OBSERVABILITY_DEPLOY_SSH_KEY }}
|
|
187
|
+
port: ${{ vars.OBSERVABILITY_DEPLOY_PORT }}
|
|
188
|
+
envs: OBSERVABILITY_DEPLOY_USER,GRAFANA_ADMIN_USER,GRAFANA_ADMIN_PASSWORD,GRAFANA_ROOT_URL
|
|
189
|
+
script: |
|
|
190
|
+
set -euo pipefail
|
|
191
|
+
|
|
192
|
+
STACK_DIR="/home/$OBSERVABILITY_DEPLOY_USER/app_configs/observability"
|
|
193
|
+
test -d "$STACK_DIR"
|
|
194
|
+
cd "$STACK_DIR"
|
|
195
|
+
|
|
196
|
+
# Never overwrite an existing host .env (password / local tweaks).
|
|
197
|
+
if [ ! -f .env ]; then
|
|
198
|
+
if [ -z "${GRAFANA_ADMIN_PASSWORD:-}" ]; then
|
|
199
|
+
echo "ERROR: $STACK_DIR/.env is missing and GRAFANA_ADMIN_PASSWORD is not set."
|
|
200
|
+
echo "Add the secret in the GitHub environment, then re-run this workflow."
|
|
201
|
+
exit 1
|
|
202
|
+
fi
|
|
203
|
+
ADMIN_USER="${GRAFANA_ADMIN_USER:-admin}"
|
|
204
|
+
# GRAFANA_ROOT_URL optional: set for observability.{ZONE} (Caddy);
|
|
205
|
+
# leave empty for SSH-tunnel-only access.
|
|
206
|
+
umask 077
|
|
207
|
+
printf '%s\n' \
|
|
208
|
+
"GRAFANA_ADMIN_USER=${ADMIN_USER}" \
|
|
209
|
+
"GRAFANA_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}" \
|
|
210
|
+
"GRAFANA_ROOT_URL=${GRAFANA_ROOT_URL:-}" \
|
|
211
|
+
> .env
|
|
212
|
+
if [ -z "${GRAFANA_ROOT_URL:-}" ]; then
|
|
213
|
+
echo "Created .env (first install); GRAFANA_ROOT_URL empty (SSH-tunnel fallback)"
|
|
214
|
+
else
|
|
215
|
+
echo "Created .env (first install); GRAFANA_ROOT_URL=${GRAFANA_ROOT_URL}"
|
|
216
|
+
fi
|
|
217
|
+
else
|
|
218
|
+
echo "Keeping existing .env"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
docker compose pull
|
|
222
|
+
docker compose up -d --force-recreate --remove-orphans
|
|
223
|
+
docker compose ps
|
|
224
|
+
|
|
225
|
+
echo "Observability stack deployment complete"
|
|
@@ -35,7 +35,12 @@ jobs:
|
|
|
35
35
|
run: uv sync --locked --all-extras --dev
|
|
36
36
|
|
|
37
37
|
- name: ruff
|
|
38
|
-
run:
|
|
38
|
+
run: |
|
|
39
|
+
uv run ruff check
|
|
40
|
+
uv run ruff format --check
|
|
41
|
+
|
|
42
|
+
- name: ty
|
|
43
|
+
run: uv run ty check
|
|
39
44
|
|
|
40
45
|
- name: Install Firebase CLI
|
|
41
46
|
working-directory: .github/ci
|
|
@@ -43,11 +48,23 @@ jobs:
|
|
|
43
48
|
|
|
44
49
|
- name: pytest
|
|
45
50
|
run: |
|
|
51
|
+
set -euo pipefail
|
|
46
52
|
export PATH="$PWD/.github/ci/node_modules/.bin:$PATH"
|
|
47
53
|
firebase --version
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
echo "Starting Firebase Auth emulator..."
|
|
55
|
+
firebase emulators:start --only auth --project=test > /dev/null 2>&1 &
|
|
56
|
+
EMULATOR_PID=$!
|
|
57
|
+
# Mirror makefile warm-up; the testing plugin also waits for Identity Toolkit HTTP readiness.
|
|
58
|
+
sleep 3
|
|
59
|
+
echo "Running unit and integration tests with emulator..."
|
|
60
|
+
set +e
|
|
61
|
+
FIREBASE_AUTH_EMULATOR_HOST=127.0.0.1:9099 uv run pytest tests/unit tests/integration -n 2
|
|
62
|
+
TEST_EXIT=$?
|
|
63
|
+
set -e
|
|
64
|
+
echo "Stopping emulator..."
|
|
65
|
+
kill "$EMULATOR_PID" 2>/dev/null || true
|
|
66
|
+
wait "$EMULATOR_PID" 2>/dev/null || true
|
|
67
|
+
exit "$TEST_EXIT"
|
|
51
68
|
|
|
52
69
|
package-smoke:
|
|
53
70
|
runs-on: ubuntu-latest
|
|
@@ -155,7 +172,7 @@ jobs:
|
|
|
155
172
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
156
173
|
with:
|
|
157
174
|
context: .
|
|
158
|
-
file: ./dockerfile
|
|
175
|
+
file: ./deploy/app/dockerfile
|
|
159
176
|
target: api
|
|
160
177
|
push: false
|
|
161
178
|
tags: core-framework:ci
|
|
@@ -164,7 +181,7 @@ jobs:
|
|
|
164
181
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
165
182
|
with:
|
|
166
183
|
context: .
|
|
167
|
-
file: ./dockerfile
|
|
184
|
+
file: ./deploy/app/dockerfile
|
|
168
185
|
target: worker
|
|
169
186
|
push: false
|
|
170
187
|
tags: core-framework-worker:ci
|
|
@@ -19,18 +19,6 @@ repos:
|
|
|
19
19
|
args: ['--maxkb=750']
|
|
20
20
|
exclude: ^uv.lock$
|
|
21
21
|
|
|
22
|
-
- repo: https://github.com/asottile/pyupgrade
|
|
23
|
-
rev: v3.21.2
|
|
24
|
-
hooks:
|
|
25
|
-
- id: pyupgrade
|
|
26
|
-
args: [--py314-plus]
|
|
27
|
-
name: Upgrade code to Python 3.14+
|
|
28
|
-
|
|
29
|
-
- repo: https://github.com/asottile/yesqa
|
|
30
|
-
rev: v1.5.0
|
|
31
|
-
hooks:
|
|
32
|
-
- id: yesqa
|
|
33
|
-
|
|
34
22
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
35
23
|
rev: 0.11.24
|
|
36
24
|
hooks:
|
|
@@ -43,17 +31,20 @@ repos:
|
|
|
43
31
|
entry: uv run --frozen ruff check --fix
|
|
44
32
|
language: system
|
|
45
33
|
types_or: [python, pyi]
|
|
34
|
+
|
|
46
35
|
- id: ruff-format
|
|
47
36
|
name: ruff format
|
|
48
37
|
entry: uv run --frozen ruff format
|
|
49
38
|
language: system
|
|
50
39
|
types_or: [python, pyi]
|
|
40
|
+
|
|
51
41
|
- id: ty
|
|
52
42
|
name: ty check
|
|
53
43
|
entry: uv run --frozen ty check
|
|
54
44
|
language: system
|
|
55
45
|
types_or: [python, pyi]
|
|
56
46
|
pass_filenames: false
|
|
47
|
+
|
|
57
48
|
- id: zizmor
|
|
58
49
|
name: zizmor
|
|
59
50
|
entry: uv run --frozen zizmor .github/workflows
|
|
@@ -4,6 +4,62 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [3.1.0] - 2026-07-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **HTTP request correlation on failures/aborts:** `ContextMiddleware` always emits **`HTTP request completed`** (with **`aborted=true`** / null **`status_code`** when no response starts), always attaches **`X-Request-ID`** (including missing-client 400s), stores **`request_id`** on ASGI scope state for 500 handlers, and stays outermost over profiling so profile HTML keeps the header.
|
|
12
|
+
- **Structlog logger caching:** `setup_logging` keeps `cache_logger_on_first_use=False` so the OTel reconfigure can attach; `configure_observability_providers` (OTLP or kill-switch-off) finalizes with `True`.
|
|
13
|
+
- **Observability polish:** Direct ARQ enqueue propagates **`request_id`** (worker ContextVar + span attribute) so Loki filters match media/variant jobs, not only outbox handlers. ARQ job timeouts/`CancelledError` mark the consumer span ERROR (metrics already set `error.type`). **`shutdown_observability`** uninstruments FastAPI/httpx/asyncpg/Redis before shutting providers. Shared **`PROBE_PATHS`** for health/readiness. **`otlp_endpoint`** requires an **`http(s)://`** base URL (stored stripped) and rejects signal paths (`.../v1/traces` etc.). FastAPI probe **`excluded_urls`** match host + exact path (`://[^/]+/health$`). Collector Compose healthcheck removed (distroless image; Grafana depends on start-order). Tempo→Loki **`tracesToLogsV2`** maps **`service.name`** / **`deployment.environment.name`**. Provisioned dashboards set **`allowUiUpdates: false`** and **`editable: false`**.
|
|
14
|
+
- **Observability review pass:** Structlog OTLP processor skips export when instrumentation is disabled (exporter failure feedback loop guard); trims duplicate **`level`**/**`timestamp`** and native **`trace_id`**/**`span_id`** attributes; truncates large **`exception`** strings. FastAPI instrumentation uses **`exclude_spans=["receive","send"]`**. Sampler uses **`get_value`** for suppress-instrumentation keys. OTLP headers parsed via **`parse_env_headers`**. Worker metrics include **`messaging.system=arq`** and **`error.type`** on generic exceptions. **`shutdown_observability`** isolates per-provider failures and clears the job duration histogram; API and worker shut it down via **`asyncio.to_thread`**. ARQ job metrics skip recording after the kill switch flips. Outbox origin metadata reuses **`capture_request_id_for_job`**. Compose **`mem_limit`** / **`GOMEMLIMIT`** on Tempo, Loki, Prometheus, and Grafana.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Manual Observability Deployment:** GitHub Actions **`manual-observability-deployment.yaml`** syncs **`deploy/observability/`** and runs Compose on the LGTM host. Uses separate **`OBSERVABILITY_DEPLOY_*`** / **`GRAFANA_ADMIN_PASSWORD`** / optional **`GRAFANA_ROOT_URL`** (not app **`DEPLOY_SERVER_*`**). First run seeds host **`.env`**; later runs keep it.
|
|
19
|
+
|
|
20
|
+
- **Grafana hostname:** Preferred UI access is **`observability.{ZONE}`** via Caddy ([`Caddyfile.observability.example`](docs/deployments/examples/Caddyfile.observability.example)) + Cloudflare DNS + WAF IP allowlist. OTLP stays private. Compose sets **`GF_SERVER_ROOT_URL`** from **`GRAFANA_ROOT_URL`**.
|
|
21
|
+
|
|
22
|
+
- **LGTM image bumps:** Collector **0.156.0**, Tempo **3.0.2** (monolithic config: drop `ingester`/`compactor`; retention via `backend_worker.compaction.block_retention`), Loki **3.7.3**, Prometheus **v3.13.0**, Grafana **13.1.0**.
|
|
23
|
+
|
|
24
|
+
- **API request correlation:** Non-probe responses include **`X-Request-ID`** (also exposed for CORS). **`ContextMiddleware`** sets `request_id` on the current HTTP SERVER span after generating the ULID; emits a structured **`HTTP request completed`** log so quiet successes remain searchable in Loki → Tempo. Uvicorn **`--no-access-log`** is unchanged.
|
|
25
|
+
|
|
26
|
+
- **HTTP metrics semconv:** When OTLP is enabled, core sets **`OTEL_SEMCONV_STABILITY_OPT_IN=http`** (unless already set) before FastAPI/ASGI instrumentation so Prometheus series match **`api-http`** (`http_server_request_duration_seconds_*`).
|
|
27
|
+
|
|
28
|
+
- **Loki storage paths:** **`deploy/observability/loki.yaml`** uses **`path_prefix: /loki`** with explicit TSDB index/cache and WAL dirs under **`/loki`**, matching the Compose **`loki-data:/loki`** volume (avoids writing outside the mount).
|
|
29
|
+
|
|
30
|
+
- **Dashboard env filter:** API/worker dashboards include a **`deployment.environment.name`** variable (Prometheus label **`deployment_environment_name`**).
|
|
31
|
+
|
|
32
|
+
- **Worker telemetry coverage:** **`instrument_arq_jobs`** wraps core **`functions`** and **`cron_jobs`** at registration; timeouts/cancellations set **`error.type=CancelledError`**; hosts must wrap custom jobs the same way.
|
|
33
|
+
|
|
34
|
+
- **LGTM ops hardening:** Collector **`memory_limiter`** + Compose **`mem_limit`/`GOMEMLIMIT`**; Prometheus **8GB** size retention; Loki ingestion caps; Loki **`3.6.12`** native **`-health`** (distroless-safe); Tempo and Collector start-order only (distroless — no in-container wget healthcheck); Grafana waits on Loki/Prometheus healthy + Collector/Tempo started; optional exporter scrape jobs commented by default; Grafana password required; Grafana UI via **`observability.{ZONE}`** (Caddy + WAF allowlist) or SSH tunnel; Tempo datasource omits **`nodeGraph`** (metrics_generator off); docs clarify Loki/Tempo are time-retention only (no size quota).
|
|
35
|
+
|
|
36
|
+
- **Observability lifecycle / naming:** **`shutdown_observability`** is process-end only (OTLP globals cannot be unset); clears kill-switch flags; structlog OTel processor no-ops when the kill switch is off; ARQ job span/metric names use ARQ **`Function.name`/`CronJob.name`**; HTTP **`request_id`** via **`ContextMiddleware`** on the SERVER span; **`HTTP request completed`** covers full response duration (structlog OTel processor injects **`trace_id`** for Loki → Tempo); shared-runtime worker docs note API **`service.name`**.
|
|
37
|
+
|
|
38
|
+
- **Same-host exporter scrapes:** Setup guides allow Docker bridge (**`172.16.0.0/12`**) to node/Postgres/Redis exporter ports so Compose Prometheus (`host.docker.internal`) is not blocked by UFW rules that only permit **`{ADMIN_IP}`**.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **Dashboard uid prefix:** Renamed Grafana dashboards **`cf-api-http`** → **`api-http`** and **`cf-worker-jobs`** → **`worker-jobs`** (files and uids). Existing Grafana bookmarks / `/d/cf-*` links need updating after re-provision.
|
|
43
|
+
|
|
44
|
+
### Removed
|
|
45
|
+
|
|
46
|
+
- **Exporter Grafana dashboards:** Dropped **`cf-host.json`**, **`cf-postgres.json`**, and **`cf-redis.json`**. v1 provisioned dashboards are app/worker OTLP only (API HTTP, Worker jobs). Optional Prometheus scrape jobs for node/Postgres/Redis exporters remain commented in **`prometheus.yml`**.
|
|
47
|
+
- **Runtime dashboard shells:** Dropped deferred **`cf-api-runtime.json`** and **`cf-worker-runtime.json`** (no in-app process metrics in v1).
|
|
48
|
+
|
|
49
|
+
### Breaking
|
|
50
|
+
|
|
51
|
+
- **Breaking (hosts — observability):** Replace Logfire with OpenTelemetry OTLP on the API and worker. Remove **`logfire`** / **`LOGFIRE_TOKEN`** / **`observability.logfire_token`**. Add **`observability.otlp_endpoint`** (required when enabled outside **`local`**) and **`observability.otlp_headers`** (TOML; deploy template hardcodes empty). Deploy variables **`OBSERVABILITY_OTLP_ENDPOINT`** (and existing **`OBSERVABILITY_ENABLED`**). Pins: **`opentelemetry-api`/`sdk`/`exporter-otlp-proto-http` ≥1.43.0,\<1.44**, instrumentation + **`opentelemetry-semantic-conventions` ≥0.64b0,\<0.65** (FastAPI OPTIONS / `_IncludedRouter` fix). Resource attribute **`deployment.environment.name`** (not deprecated **`deployment.environment`**). ARQ spans use **`messaging.operation.type=process`**, **`messaging.destination.name=<queue>`**, **`messaging.operation.name=<job>`**. Direct ARQ enqueue propagates W3C context; outbox jobs keep a separate consumer span linked to the originating request via persisted **`event_outbox.metadata`** (**`request_id`**, W3C carrier) plus outbox span attributes (`outbox_id`, `idempotency_key`, …). No in-process **`SystemMetricsInstrumentor`**; v1 ships no host/Postgres/Redis or process-runtime Grafana dashboards (optional exporter scrapes stay commented in **`prometheus.yml`**).
|
|
52
|
+
|
|
53
|
+
- **Breaking (API):** **`POST /posts`**, **`POST /comments`**, and **`POST /comments/{comment_id}/replies`** return **`201`** with **`{ "id": "<ulid>" }`** (first success and idempotency replay return the same id). Previously these returned an empty body. See **`docs/domains/posts/create_post.md`**, **`docs/domains/comments/create_comment.md`**, and **`docs/design/create-idempotency-design.md`**.
|
|
54
|
+
|
|
55
|
+
- **Breaking (hosts — config):** Add **`retention.read_notifications_retention_days`** under **`[retention]`** (default **90**). Deploy variable **`RETENTION_READ_NOTIFICATIONS_DAYS`**. The worker runs **`schedule_prune_read_notifications`** (daily **05:05 UTC**) to delete read notifications past that window; unread rows are never pruned. See **`docs/library/workers.md`** and **`docs/domains/notifications/notification_inbox.md`**.
|
|
56
|
+
|
|
57
|
+
### Migration
|
|
58
|
+
|
|
59
|
+
- **Observability (Logfire → OTLP):** Drop **`LOGFIRE_TOKEN`** / **`observability.logfire_token`**. Add **`observability.otlp_endpoint`** (and optional **`otlp_headers`**) under **`[observability]`**; set **`OBSERVABILITY_OTLP_ENDPOINT`** when **`OBSERVABILITY_ENABLED=true`** outside **`local`**. See **`docs/library/package-api.md`** (Host upgrade — observability OTLP) and **`docs/deployments/guides/setup/observability-lgtm-setup.md`**.
|
|
60
|
+
|
|
61
|
+
- **`notification` schema:** Run **`cf-alembic`** so the stream applies **`2fdd68777706`** (`idx_notifications_read_at_retention` on **`read_at`** where not null) before relying on age-based read-notification pruning at scale.
|
|
62
|
+
|
|
7
63
|
## [3.0.0] - 2026-07-11
|
|
8
64
|
|
|
9
65
|
### Breaking
|
|
@@ -515,4 +571,5 @@ First **SemVer-stable** release per **`docs/library/package-api.md`**.
|
|
|
515
571
|
[2.3.2]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.1...v2.3.2
|
|
516
572
|
[2.3.3]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.2...v2.3.3
|
|
517
573
|
[3.0.0]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.3...v3.0.0
|
|
518
|
-
[
|
|
574
|
+
[3.1.0]: https://github.com/NepNepFFXIV/core-framework/compare/v3.0.0...v3.1.0
|
|
575
|
+
[unreleased]: https://github.com/NepNepFFXIV/core-framework/compare/v3.1.0...HEAD
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-framework
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Core framework package (import as core_framework)
|
|
5
5
|
Project-URL: Homepage, https://github.com/NepNepFFXIV/core-framework
|
|
6
6
|
Project-URL: Repository, https://github.com/NepNepFFXIV/core-framework
|
|
@@ -20,8 +20,15 @@ Requires-Dist: fastapi[standard]>=0.139.0
|
|
|
20
20
|
Requires-Dist: firebase-admin>=7.5.0
|
|
21
21
|
Requires-Dist: httpx[http2]>=0.28.1
|
|
22
22
|
Requires-Dist: itsdangerous>=2.2.0
|
|
23
|
-
Requires-Dist: logfire[asyncpg,fastapi,httpx,redis]>=4.37.0
|
|
24
23
|
Requires-Dist: mashumaro[orjson]>=3.22
|
|
24
|
+
Requires-Dist: opentelemetry-api<1.44,>=1.43.0
|
|
25
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http<1.44,>=1.43.0
|
|
26
|
+
Requires-Dist: opentelemetry-instrumentation-asyncpg<0.65,>=0.64b0
|
|
27
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi<0.65,>=0.64b0
|
|
28
|
+
Requires-Dist: opentelemetry-instrumentation-httpx<0.65,>=0.64b0
|
|
29
|
+
Requires-Dist: opentelemetry-instrumentation-redis<0.65,>=0.64b0
|
|
30
|
+
Requires-Dist: opentelemetry-sdk<1.44,>=1.43.0
|
|
31
|
+
Requires-Dist: opentelemetry-semantic-conventions<0.65,>=0.64b0
|
|
25
32
|
Requires-Dist: orjson>=3.11.9
|
|
26
33
|
Requires-Dist: pillow-heif>=1.4.0
|
|
27
34
|
Requires-Dist: pillow>=12.3.0
|
|
@@ -40,18 +47,30 @@ Description-Content-Type: text/markdown
|
|
|
40
47
|
|
|
41
48
|
Install from PyPI as **`core-framework`**, import **`core_framework`**. MIT — [LICENSE](LICENSE). [Repository](https://github.com/NepNepFFXIV/core-framework), [PyPI](https://pypi.org/project/core-framework/).
|
|
42
49
|
|
|
50
|
+
## Documentation
|
|
51
|
+
|
|
52
|
+
| Doc | Purpose |
|
|
53
|
+
| ---------------------------------------------------------- | --------------------------------------------------------- |
|
|
54
|
+
| [docs/README.md](docs/README.md) | Doc map (platform, design, library, domains, deployments) |
|
|
55
|
+
| [docs/library/package-api.md](docs/library/package-api.md) | Host import surface and upgrade tables |
|
|
56
|
+
| [CHANGELOG.md](CHANGELOG.md) | Release notes (SemVer) |
|
|
57
|
+
|
|
43
58
|
## Install
|
|
44
59
|
|
|
45
60
|
```bash
|
|
46
61
|
uv add core-framework
|
|
47
62
|
```
|
|
48
63
|
|
|
64
|
+
Pin hosts to a locked version. On each bump, read **[CHANGELOG.md](CHANGELOG.md)** and the host-upgrade tables in **[package-api.md](docs/library/package-api.md)**.
|
|
65
|
+
|
|
49
66
|
## Local development
|
|
50
67
|
|
|
51
68
|
Use **Python 3.14**. Install **uv** and **Docker**.
|
|
52
69
|
|
|
70
|
+
Tracked **`config.toml`** at the repo root is the local-dev settings file (dummy values; no production secrets). Production renders from **`config.toml.template`** via deploy **`envsubst`** — see [architecture decisions](docs/platform/architecture-decisions.md).
|
|
71
|
+
|
|
53
72
|
```bash
|
|
54
|
-
docker compose -f docker-compose.dev.yaml up -d
|
|
73
|
+
docker compose -f deploy/app/docker-compose.dev.yaml up -d
|
|
55
74
|
uv sync --locked --all-extras --dev
|
|
56
75
|
uv run cf-alembic
|
|
57
76
|
make run
|
|
@@ -59,7 +78,7 @@ make run
|
|
|
59
78
|
|
|
60
79
|
**Firebase:** copy **`firebase_config.example.json`** to **`firebase_config.json`** at the repo root and replace with your Firebase project’s **service account** JSON from the console.
|
|
61
80
|
|
|
62
|
-
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f docker-compose.dev.yaml down`**.
|
|
81
|
+
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f deploy/app/docker-compose.dev.yaml down`**.
|
|
63
82
|
|
|
64
83
|
**Pre-commit:** `uv sync --dev` installs **pre-commit**. Enable hooks with **`uv run pre-commit install`** (ruff, mdformat, uv-lock, and other checks in **`.pre-commit-config.yaml`**).
|
|
65
84
|
|
|
@@ -92,6 +111,10 @@ def build_app(settings: HostSettings | None = None) -> FastAPI:
|
|
|
92
111
|
|
|
93
112
|
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/library/core-framework-migration.md).
|
|
94
113
|
|
|
114
|
+
**Worker:** production also runs the ARQ worker (`arq core_framework.worker.main.WorkerSettings`, or a host composition that calls the same startup path). Schedules and tasks: [workers.md](docs/library/workers.md). Composition details: [package-api.md](docs/library/package-api.md) (Default deployment entrypoints).
|
|
115
|
+
|
|
116
|
+
**Observability:** OpenTelemetry OTLP (not Logfire). Under **`[observability]`**, set **`enabled`** and **`otlp_endpoint`** (required when enabled outside **`local`**); drop **`logfire_token`** / **`LOGFIRE_TOKEN`**. Same-host Grafana LGTM stack: **`deploy/observability/`** and [observability-lgtm-setup.md](docs/deployments/guides/setup/observability-lgtm-setup.md). Host upgrade table: [package-api.md — observability OTLP](docs/library/package-api.md).
|
|
117
|
+
|
|
95
118
|
## Host pytest
|
|
96
119
|
|
|
97
120
|
In your host repository, add the **`core-framework[testing]`** extra to dev or test dependencies. In **`tests/conftest.py`**, register **`pytest_core_framework_config`** (returns **`TestConfig`**) and a session-scoped **`anyio_backend`** fixture that returns **`"asyncio"`**.
|
|
@@ -2,18 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Install from PyPI as **`core-framework`**, import **`core_framework`**. MIT — [LICENSE](LICENSE). [Repository](https://github.com/NepNepFFXIV/core-framework), [PyPI](https://pypi.org/project/core-framework/).
|
|
4
4
|
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
| Doc | Purpose |
|
|
8
|
+
| ---------------------------------------------------------- | --------------------------------------------------------- |
|
|
9
|
+
| [docs/README.md](docs/README.md) | Doc map (platform, design, library, domains, deployments) |
|
|
10
|
+
| [docs/library/package-api.md](docs/library/package-api.md) | Host import surface and upgrade tables |
|
|
11
|
+
| [CHANGELOG.md](CHANGELOG.md) | Release notes (SemVer) |
|
|
12
|
+
|
|
5
13
|
## Install
|
|
6
14
|
|
|
7
15
|
```bash
|
|
8
16
|
uv add core-framework
|
|
9
17
|
```
|
|
10
18
|
|
|
19
|
+
Pin hosts to a locked version. On each bump, read **[CHANGELOG.md](CHANGELOG.md)** and the host-upgrade tables in **[package-api.md](docs/library/package-api.md)**.
|
|
20
|
+
|
|
11
21
|
## Local development
|
|
12
22
|
|
|
13
23
|
Use **Python 3.14**. Install **uv** and **Docker**.
|
|
14
24
|
|
|
25
|
+
Tracked **`config.toml`** at the repo root is the local-dev settings file (dummy values; no production secrets). Production renders from **`config.toml.template`** via deploy **`envsubst`** — see [architecture decisions](docs/platform/architecture-decisions.md).
|
|
26
|
+
|
|
15
27
|
```bash
|
|
16
|
-
docker compose -f docker-compose.dev.yaml up -d
|
|
28
|
+
docker compose -f deploy/app/docker-compose.dev.yaml up -d
|
|
17
29
|
uv sync --locked --all-extras --dev
|
|
18
30
|
uv run cf-alembic
|
|
19
31
|
make run
|
|
@@ -21,7 +33,7 @@ make run
|
|
|
21
33
|
|
|
22
34
|
**Firebase:** copy **`firebase_config.example.json`** to **`firebase_config.json`** at the repo root and replace with your Firebase project’s **service account** JSON from the console.
|
|
23
35
|
|
|
24
|
-
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f docker-compose.dev.yaml down`**.
|
|
36
|
+
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f deploy/app/docker-compose.dev.yaml down`**.
|
|
25
37
|
|
|
26
38
|
**Pre-commit:** `uv sync --dev` installs **pre-commit**. Enable hooks with **`uv run pre-commit install`** (ruff, mdformat, uv-lock, and other checks in **`.pre-commit-config.yaml`**).
|
|
27
39
|
|
|
@@ -54,6 +66,10 @@ def build_app(settings: HostSettings | None = None) -> FastAPI:
|
|
|
54
66
|
|
|
55
67
|
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/library/core-framework-migration.md).
|
|
56
68
|
|
|
69
|
+
**Worker:** production also runs the ARQ worker (`arq core_framework.worker.main.WorkerSettings`, or a host composition that calls the same startup path). Schedules and tasks: [workers.md](docs/library/workers.md). Composition details: [package-api.md](docs/library/package-api.md) (Default deployment entrypoints).
|
|
70
|
+
|
|
71
|
+
**Observability:** OpenTelemetry OTLP (not Logfire). Under **`[observability]`**, set **`enabled`** and **`otlp_endpoint`** (required when enabled outside **`local`**); drop **`logfire_token`** / **`LOGFIRE_TOKEN`**. Same-host Grafana LGTM stack: **`deploy/observability/`** and [observability-lgtm-setup.md](docs/deployments/guides/setup/observability-lgtm-setup.md). Host upgrade table: [package-api.md — observability OTLP](docs/library/package-api.md).
|
|
72
|
+
|
|
57
73
|
## Host pytest
|
|
58
74
|
|
|
59
75
|
In your host repository, add the **`core-framework[testing]`** extra to dev or test dependencies. In **`tests/conftest.py`**, register **`pytest_core_framework_config`** (returns **`TestConfig`**) and a session-scoped **`anyio_backend`** fixture that returns **`"asyncio"`**.
|