core-framework 2.3.0__tar.gz → 2.3.1__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-2.3.0 → core_framework-2.3.1}/.cursor/rules/postgres-config-conventions.mdc +9 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/repository-schema-isolation.mdc +21 -8
- {core_framework-2.3.0 → core_framework-2.3.1}/CHANGELOG.md +13 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/PKG-INFO +1 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/outbox/schemas.py +7 -3
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/read_service.py +25 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/comment_created.py +7 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/post_created.py +7 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/post_viewed.py +7 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/user_registered.py +7 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/models.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/cache/models.py +4 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/models.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_read.py +1 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_service.py +15 -3
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/read_url_config.py +4 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/enums.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/events.py +9 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/enums.py +6 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/exceptions.py +20 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/deletion_audit.py +1 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/enums.py +4 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/user_deletion_service.py +21 -2
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/database.py +5 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/__init__.py +2 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/dependencies.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/models.py +6 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/ports/activity_source.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/repository.py +68 -13
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/service.py +33 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/ports/auth.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/dependencies.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/repository.py +219 -208
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/staging.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/staging.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/staging.py +3 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/staging.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/staging.py +3 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/finals_publisher.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/staging.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/variant_encoder.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/dependencies.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/repository.py +63 -52
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/dependencies.py +14 -6
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outbox_repository.py +19 -11
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/repository.py +104 -102
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/dependencies.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/repository.py +85 -74
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/consumer.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/producer.py +4 -4
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/dependencies.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/repository.py +238 -227
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/dependencies.py +14 -6
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outbox_repository.py +19 -11
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/repository.py +128 -126
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/service.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/attachment_staging_display_geometry.py +4 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_attachment_staging_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_banner_staging_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_staging_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_attachment_variant_encoder_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_attachment_finals_publisher_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/outbox/outbox_consumer_adapter.py +21 -10
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/outbox/outbox_producer_adapter.py +6 -4
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/auth.py +20 -11
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/main.py +6 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/analytics_refresh_cron.py +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/worker_context.py +4 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/README.md +2 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/e2e-smoke-tests-design.md +1 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/users.md +48 -8
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/post-comment-attachments-design.md +1 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/user_removal.md +10 -6
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/README.md +2 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/package-api.md +1 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/testing-plugin-design.md +7 -6
- core_framework-2.3.1/docs/testing.md +149 -0
- core_framework-2.3.1/docs/todo.md +76 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/pyproject.toml +1 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/analytics/_helpers.py +9 -4
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_outbox_helpers.py +4 -7
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/router_test.py +13 -7
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/posts/router_test.py +14 -8
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/users/router_test.py +9 -2
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/comment_attachments_integration_test.py +236 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/create_idempotency_integration_test.py +16 -10
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/notifications/router_test.py +9 -4
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_attachments_integration_test.py +294 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_deletion_integration_test.py +14 -9
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/deletion_audit_integration_test.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/user_deletion_integration_test.py +134 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/account_deletion_test.py +16 -8
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/create_idempotency_retention_test.py +14 -8
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/moderation_outbox_test.py +15 -7
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/stale_staging_sweep_test.py +6 -1
- {core_framework-2.3.0 → core_framework-2.3.1}/uv.lock +1 -1
- core_framework-2.3.0/docs/todo.md +0 -11
- {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/fastapi +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/library-skills/.library-skills.json +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/library-skills/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/alembic-migrations.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-layer.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-reference-docs.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-validation.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/application-layer.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/constants-final.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/constitution.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/database-triggers.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/docstrings.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-caller-context.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-imports.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-input-guards.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-services-and-adapters.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/error-boundary.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/flow-documentation.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/inline-raise-messages.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/integration-test-strategy.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/layer-boundaries.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/no-code-in-docs.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/strong-reads.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/structured-logging.mdc +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/add-config/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/add-domain/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/code-review/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/fastapi +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/implement-feature/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/recommend-features/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/sync-host-rules/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/write-flow-doc/SKILL.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.dockerignore +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/_deploy.yml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/dev-ci-cd.yaml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/manual-deployment.yaml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/publish-pypi.yml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/test.yaml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.gitignore +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.pre-commit-config.yaml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/.python-version +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/LICENSE +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/versions/5b9ac98bb150_analytics_daily_fact.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/versions/7f2a9c1d4e8b_analytics_daily_fact_day_index.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_attachments.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency_created_at_index.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_mentions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_tombstone_status_model.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_add_attachment_staging_registry.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_attachment_staging_registry_published_at.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_attachments.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_create_idempotency.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_create_idempotency_created_at_index.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_mentions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_post_views_retention_high_water_mark.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_tombstone_status_model.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/README +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/env.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/script.py.mako +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_reserve_sentinel_user_ids.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic.ini +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/config.toml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/config.toml.template +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/analytics/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/analytics/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/cache/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/cache/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/comments/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/comments/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/outbox/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/posts/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/posts/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/attachments/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/attachments/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/mappers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/public/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/public/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/dependencies.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/events/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/events/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/idempotency/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/idempotency/dependencies.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/authenticated/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/authenticated/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/mappers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/public/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/public/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/system/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/system/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/mappers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/mappers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/router.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/shared/schemas.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/bucket_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/prune_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/refresh_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/registry.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/access_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/auth_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/bootstrap.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/cache/invalidate_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/admin_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/aggregation_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/authenticated_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/cleanup_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/public_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/event_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/event_token.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/avatar_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/banner_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/ingest_guards.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/appeal_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/moderator_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/report_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/scheduled_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/user_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/inbox_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/mute_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/notification_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/block_mirrors.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/follow_mirrors.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/handlers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/ops_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/polling_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/processing_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/restriction_mirrors.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/admin_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/aggregation_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/authenticated_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/cleanup_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/public_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/user_agent.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/worker_jobs.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/admin_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/aggregation_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/authenticated_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/public_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/scheduled_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/asgi.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/bundled_alembic.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/cache.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/context.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/application.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/common.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/setup.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/firebase.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/http_client.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/logging.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/middleware.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/observability.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/pagination.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/redis.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/runtime.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/settings.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/dependencies.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/ports/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/enums.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/outcomes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/outcomes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/utils.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/enums.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outbox_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outcomes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/enums.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/dependencies.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/admin.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/enums.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/outcomes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/constants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/enums.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/exceptions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/models.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outbox_service.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outcomes.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/utils.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/utils.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/firebase/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/firebase/firebase_auth_adapter.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_staging_image.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/main.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/migrate_cli.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/arq.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/config.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/containers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/firebase.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/firebase_identity_toolkit.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/hookspecs.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/httpx_test_client.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/media.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/migrations.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/plugin.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_expired_account_deletions.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_poll_outbox.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_prune_analytics_daily_facts.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_prune_post_views.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_refresh_analytics.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_attachment_staging.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_attachment_finals.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_superseded_banner_finals.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_account_deletion.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_admin_user_deletion.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_comment_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_post_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_user_stats.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_attachment_asset_variants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_banner_asset_variants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_cache_pattern_invalidation.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_destructive_comment_delete.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_destructive_post_delete.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_media_asset_variants.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_mute_lift.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_outbox_row.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_refresh_analytics_bucket.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_user_content_deletion.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docker-compose.dev.yaml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docker-compose.yml +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/dockerfile +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/deploy-playbook.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/edge-upload-limits.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/examples/Caddyfile.example +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/examples/image-server-known-hosts.example +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/app-server-deploy-ssh.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/image-server-ssh.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/postgres-setup.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/redis-setup.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/ubuntu-server-setup.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/release-playbook.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/auth/access_control.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/auth/registration.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/cache/admin_cache_invalidation.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/admin_comments.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/comment_report.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/comment_stats_aggregation.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/create_comment.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/delete_comment.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/edit_comment.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/retrieve_comments.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/comments.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/overview.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/posts.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/events/events.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/avatar-upload-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/banner-upload-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/upload-pipeline-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/upload_pipeline.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/mentions/mentions_in_content.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/appeals.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/internal_notes.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/moderator_actions.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/reports.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/restrictions.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/notifications/notification_inbox.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/outbox/admin_outbox_ops.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/admin_posts.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/author_context.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/hashtag_discovery.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_like.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_stats_aggregation.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_visibility.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/account.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/account_deletion.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/avatar.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/banner.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/blocks.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/change_history.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/check_username_exists.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/follow-system-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/follow.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/my_posts_and_comments.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/preferences.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/profile.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/public_profile.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/api.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/core-framework-migration.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/overview.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/README.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/analytics-rollup-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/architecture-decisions.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/client-error-visibility.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/conventions.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/create-idempotency-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/database-triggers.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/domain-services-and-adapters.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/event-outbox-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/events-ingest-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/layers-and-boundaries.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/media-storage-topology.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/outbox-admin-ops-design.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/patch-update-typed-payload.md +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/firebase_config.example.json +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/makefile +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/conftest.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_auth.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_canaries.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_media.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_settings.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_upload_payloads.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/conftest.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/media/pipeline_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/canary_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/media_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/system_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/tls_host_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/_http_error_details.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_auth_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_destructive_delete_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_http_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_user_deletion_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_user_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/_auth_cases.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/analytics/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/analytics/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/cache/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/cache/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/comments/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/comments/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/_auth_cases.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/outbox/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/outbox/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/posts/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/users/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/attachments/_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/attachments/attachment_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/auth/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/auth/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/authenticated/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/public/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/public/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/events/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/media/ingest_contract_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/mentions/mentions_integration_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/notifications/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/followers_visibility_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_stats_dirty_marking_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/public/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/public/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/public_read_by_id_unavailable_detail_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/system/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/system/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/avatar_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/banner_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/public/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/public/router_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/_media_upload_helpers.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_comment_stats_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_post_stats_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_user_stats_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/analytics_prune_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/analytics_refresh_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/attachment_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/avatar_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/banner_upload_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/conftest.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/mute_lift_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/user_outbox_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/utils_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/comments/authenticated/comment_request_schemas_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/dedupe_preserving_order_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/posts/authenticated/post_update_mapper_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/users/profile_update_mapper_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/comments/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/events/event_service_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/notifications/inbox_service_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/users/deletion_audit_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/bundled_alembic_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/migrate_cli_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/pagination_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/comment/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/post/models_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/user/service_test.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/media/__init__.py +0 -0
- {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +0 -0
|
@@ -45,3 +45,12 @@ Use explicit write/read configuration and keep schema names shared.
|
|
|
45
45
|
- `read_postgres`
|
|
46
46
|
- Domain dependencies pass `(write, read, strong)` explicitly to repositories.
|
|
47
47
|
- Until a dedicated strong instance exists, use write instance for the strong argument intentionally.
|
|
48
|
+
|
|
49
|
+
## Schema names in SQL
|
|
50
|
+
|
|
51
|
+
- Schema names come only from `settings.postgres_schemas` (see **Settings Model** above).
|
|
52
|
+
- Domain `dependencies.py` passes unquoted `schema=runtime.settings.postgres_schemas.schema_<domain>` into repositories (keyword-only `__init__`).
|
|
53
|
+
- Repositories cache `self.schema_sql = quote_postgres_identifier(schema)` and use `{self.schema_sql}.table` in f-string SQL — never hard-coded `"post".` literals.
|
|
54
|
+
- Outbox producer adapter is wired per domain with `schema` at construction; consumer adapter receives unquoted `schema` per call and caches quoted SQL.
|
|
55
|
+
|
|
56
|
+
Repository isolation rules (no cross-domain schema access): **`repository-schema-isolation.mdc`**.
|
|
@@ -11,10 +11,19 @@ Each domain repository may only read/write tables in **its own** Postgres schema
|
|
|
11
11
|
|
|
12
12
|
Canonical rule: `docs/platform/layers-and-boundaries.md` — *no cross-domain schema reads, writes, joins, or foreign keys*.
|
|
13
13
|
|
|
14
|
+
## Schema qualification
|
|
15
|
+
|
|
16
|
+
Repositories receive unquoted `schema` from `runtime.settings.postgres_schemas` in `dependencies.py` (keyword-only `__init__` arg). In `__init__`:
|
|
17
|
+
|
|
18
|
+
- `self.schema` — config schema name (e.g. `post`)
|
|
19
|
+
- `self.schema_sql` — `quote_postgres_identifier(schema)` for SQL interpolation
|
|
20
|
+
|
|
21
|
+
Use `{self.schema_sql}.table` in f-string SQL — not hard-coded `"post".` literals.
|
|
22
|
+
|
|
14
23
|
## Allowed in a repository
|
|
15
24
|
|
|
16
|
-
- SQL qualified with that domain's schema only (e.g. `
|
|
17
|
-
- **Within-schema** policy gates (e.g. `insert_post_like` checks `
|
|
25
|
+
- SQL qualified with that domain's schema only (e.g. `{self.schema_sql}.posts` in `PostRepository`).
|
|
26
|
+
- **Within-schema** policy gates (e.g. `insert_post_like` checks `{self.schema_sql}.posts.status = active`).
|
|
18
27
|
- **Lookup mirrors** in the same schema (`user_blocks_lookup`, `user_restrictions_lookup`, `user_followers_lookup`) — synced by application flows; mirrors are not authoritative.
|
|
19
28
|
|
|
20
29
|
## Forbidden in a repository
|
|
@@ -23,18 +32,18 @@ Canonical rule: `docs/platform/layers-and-boundaries.md` — *no cross-domain sc
|
|
|
23
32
|
- Importing another domain's `service`, `repository`, or models to enforce policy.
|
|
24
33
|
|
|
25
34
|
```python
|
|
26
|
-
# ❌ moderation/repository.py — cross-domain EXISTS
|
|
27
|
-
insert into
|
|
35
|
+
# ❌ moderation/repository.py — cross-domain EXISTS (illustrative schema literals)
|
|
36
|
+
insert into {moderation_schema_sql}.post_reports (...)
|
|
28
37
|
select $1, $2, $3, $4
|
|
29
38
|
where exists (
|
|
30
|
-
select 1 from
|
|
39
|
+
select 1 from {post_schema_sql}.posts
|
|
31
40
|
where id = $2 and status = 'active'
|
|
32
41
|
)
|
|
33
42
|
|
|
34
43
|
# ❌ notification/repository.py — cross-domain mute gate
|
|
35
|
-
insert into
|
|
44
|
+
insert into {notification_schema_sql}.notification_mutes (...)
|
|
36
45
|
select ...
|
|
37
|
-
where exists (select 1 from
|
|
46
|
+
where exists (select 1 from {comment_schema_sql}.comments where ...)
|
|
38
47
|
```
|
|
39
48
|
|
|
40
49
|
## Alembic migrations (different convention)
|
|
@@ -69,4 +78,8 @@ Before adding a repository write that depends on another domain's row state:
|
|
|
69
78
|
|
|
70
79
|
## Self-check (repositories only)
|
|
71
80
|
|
|
72
|
-
In `domains/<name>/repository.py
|
|
81
|
+
In `domains/<name>/repository.py`:
|
|
82
|
+
|
|
83
|
+
- Every table/type qualifier in SQL must use `{self.schema_sql}.…` (that domain's schema only).
|
|
84
|
+
- Do not hard-code `"user".`, `"post".`, etc. — use `self.schema` / `self.schema_sql` from config.
|
|
85
|
+
- Mirror lookup tables (`user_blocks_lookup`, etc.) still live under `{self.schema_sql}` when they belong to that domain's schema.
|
|
@@ -4,6 +4,19 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.3.1] - 2026-07-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Partial admin user deletions:** `tombstone_authored_posts_only` and `tombstone_authored_comments_only` on `POST /admin/users/{user_id}/deletions` — moderator tombstone of authored posts or comments while keeping the account. See **`docs/domains/deletion/users.md`**.
|
|
12
|
+
- **`docs/testing.md`** — usage-focused pytest plugin guide for host adopters (wiring, fixtures, tiers, troubleshooting). Design reference remains **`docs/library/testing-plugin-design.md`**.
|
|
13
|
+
- **Post/comment attachment integration tests:** v1.1 create/edit coverage — best-effort attach (unknown or already-linked assets), attach before worker publish, edit-budget enforcement, clear-all patch, and tombstone finals cleanup. See **`tests/integration/api/posts/post_attachments_integration_test.py`** and **`tests/integration/api/comments/comment_attachments_integration_test.py`**.
|
|
14
|
+
- **Analytics rollup:** `retrieve_daily_fact_kind_totals_for_range` on `AnalyticsService` and `retrieve_analytics_kind_totals_for_range` in `application/analytics/read_service` — sum `daily_fact` counts per `kind` over an inclusive UTC day range (for host catalog and similar reads).
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **Admin outbox schemas:** rename response field `schema` to `producing_schema` with JSON alias `schema` so Pydantic no longer warns about shadowing `BaseModel.schema`.
|
|
19
|
+
|
|
7
20
|
## [2.3.0] - 2026-07-03
|
|
8
21
|
|
|
9
22
|
Analytics rollup domain (materialized daily activity counts), admin read API, and retention prune. Hosts must add **`[analytics]`** and **`schema_analytics`**, run **`cf-alembic`**, and run the worker for rollup refresh and daily-fact prune.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-framework
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
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
|
|
@@ -2,7 +2,7 @@ from datetime import datetime
|
|
|
2
2
|
from typing import Annotated, Any
|
|
3
3
|
|
|
4
4
|
from fastapi import Path, Query
|
|
5
|
-
from pydantic import BaseModel
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
6
|
|
|
7
7
|
OutboxRowId = Annotated[
|
|
8
8
|
int,
|
|
@@ -34,7 +34,9 @@ class OutboxOldestPendingRow(BaseModel):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class OutboxSummaryResponse(BaseModel):
|
|
37
|
-
|
|
37
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
38
|
+
|
|
39
|
+
producing_schema: str = Field(alias="schema")
|
|
38
40
|
total_pending: int
|
|
39
41
|
total_dead: int
|
|
40
42
|
pending_by_event: list[OutboxEventCountItem]
|
|
@@ -43,8 +45,10 @@ class OutboxSummaryResponse(BaseModel):
|
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
class OutboxDeadRowResponse(BaseModel):
|
|
48
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
49
|
+
|
|
46
50
|
id: int
|
|
47
|
-
|
|
51
|
+
producing_schema: str = Field(alias="schema")
|
|
48
52
|
event_name: str
|
|
49
53
|
aggregate_type: str
|
|
50
54
|
aggregate_id: str
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/read_service.py
RENAMED
|
@@ -27,6 +27,31 @@ async def retrieve_analytics_daily_range(
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
async def retrieve_analytics_kind_totals_for_range(
|
|
31
|
+
*,
|
|
32
|
+
subject_type: str,
|
|
33
|
+
activity_type: str,
|
|
34
|
+
from_day: date,
|
|
35
|
+
to_day: date,
|
|
36
|
+
kind: str | None = None,
|
|
37
|
+
) -> dict[str, Any]:
|
|
38
|
+
"""Return per-kind rollup totals summed over an inclusive UTC day range."""
|
|
39
|
+
totals = await analytics_deps.analytics_service.retrieve_daily_fact_kind_totals_for_range(
|
|
40
|
+
subject_type=subject_type,
|
|
41
|
+
activity_type=activity_type,
|
|
42
|
+
from_day=from_day,
|
|
43
|
+
to_day=to_day,
|
|
44
|
+
kind=kind,
|
|
45
|
+
)
|
|
46
|
+
return {
|
|
47
|
+
"subject_type": subject_type,
|
|
48
|
+
"activity_type": activity_type,
|
|
49
|
+
"from_day": from_day,
|
|
50
|
+
"to_day": to_day,
|
|
51
|
+
"items": [{"kind": total.kind, "count": total.count} for total in totals],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
30
55
|
async def retrieve_analytics_daily_day(
|
|
31
56
|
*,
|
|
32
57
|
subject_type: str,
|
|
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class CommentCreatedSource:
|
|
8
|
+
"""Activity source for comment creation counts."""
|
|
9
|
+
|
|
8
10
|
@property
|
|
9
11
|
def subject_type(self) -> str:
|
|
12
|
+
"""Return the analytics subject type for this source."""
|
|
13
|
+
|
|
10
14
|
return "comment"
|
|
11
15
|
|
|
12
16
|
@property
|
|
13
17
|
def activity_type(self) -> str:
|
|
18
|
+
"""Return the analytics activity type for this source."""
|
|
19
|
+
|
|
14
20
|
return "created"
|
|
15
21
|
|
|
16
22
|
async def retrieve_activity_counts_for_day(
|
|
@@ -19,6 +25,7 @@ class CommentCreatedSource:
|
|
|
19
25
|
*,
|
|
20
26
|
final: bool = False,
|
|
21
27
|
) -> list[ActivityCount]:
|
|
28
|
+
"""Return per-kind comment created counts for one UTC day."""
|
|
22
29
|
if final:
|
|
23
30
|
rows = await comment_deps.comment_service.retrieve_comment_created_activity_counts_for_day_strong(day=day)
|
|
24
31
|
else:
|
|
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class PostCreatedSource:
|
|
8
|
+
"""Activity source for post creation counts."""
|
|
9
|
+
|
|
8
10
|
@property
|
|
9
11
|
def subject_type(self) -> str:
|
|
12
|
+
"""Return the analytics subject type for this source."""
|
|
13
|
+
|
|
10
14
|
return "post"
|
|
11
15
|
|
|
12
16
|
@property
|
|
13
17
|
def activity_type(self) -> str:
|
|
18
|
+
"""Return the analytics activity type for this source."""
|
|
19
|
+
|
|
14
20
|
return "created"
|
|
15
21
|
|
|
16
22
|
async def retrieve_activity_counts_for_day(
|
|
@@ -19,6 +25,7 @@ class PostCreatedSource:
|
|
|
19
25
|
*,
|
|
20
26
|
final: bool = False,
|
|
21
27
|
) -> list[ActivityCount]:
|
|
28
|
+
"""Return per-kind post created counts for one UTC day."""
|
|
22
29
|
if final:
|
|
23
30
|
rows = await post_deps.post_service.retrieve_post_created_activity_counts_for_day_strong(day=day)
|
|
24
31
|
else:
|
|
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class PostViewedSource:
|
|
8
|
+
"""Activity source for post view counts."""
|
|
9
|
+
|
|
8
10
|
@property
|
|
9
11
|
def subject_type(self) -> str:
|
|
12
|
+
"""Return the analytics subject type for this source."""
|
|
13
|
+
|
|
10
14
|
return "post"
|
|
11
15
|
|
|
12
16
|
@property
|
|
13
17
|
def activity_type(self) -> str:
|
|
18
|
+
"""Return the analytics activity type for this source."""
|
|
19
|
+
|
|
14
20
|
return "viewed"
|
|
15
21
|
|
|
16
22
|
async def retrieve_activity_counts_for_day(
|
|
@@ -19,6 +25,7 @@ class PostViewedSource:
|
|
|
19
25
|
*,
|
|
20
26
|
final: bool = False,
|
|
21
27
|
) -> list[ActivityCount]:
|
|
28
|
+
"""Return per-kind post viewed counts for one UTC day."""
|
|
22
29
|
if final:
|
|
23
30
|
rows = await post_deps.post_service.retrieve_post_viewed_activity_counts_for_day_strong(day=day)
|
|
24
31
|
else:
|
|
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class UserRegisteredSource:
|
|
8
|
+
"""Activity source for user registration counts."""
|
|
9
|
+
|
|
8
10
|
@property
|
|
9
11
|
def subject_type(self) -> str:
|
|
12
|
+
"""Return the analytics subject type for this source."""
|
|
13
|
+
|
|
10
14
|
return "user"
|
|
11
15
|
|
|
12
16
|
@property
|
|
13
17
|
def activity_type(self) -> str:
|
|
18
|
+
"""Return the analytics activity type for this source."""
|
|
19
|
+
|
|
14
20
|
return "registered"
|
|
15
21
|
|
|
16
22
|
async def retrieve_activity_counts_for_day(
|
|
@@ -19,6 +25,7 @@ class UserRegisteredSource:
|
|
|
19
25
|
*,
|
|
20
26
|
final: bool = False,
|
|
21
27
|
) -> list[ActivityCount]:
|
|
28
|
+
"""Return per-kind user registered counts for one UTC day."""
|
|
22
29
|
if final:
|
|
23
30
|
rows = await user_deps.user_service.retrieve_user_registered_activity_counts_for_day_strong(day=day)
|
|
24
31
|
else:
|
|
@@ -5,11 +5,15 @@ from core_framework.core import CacheKey
|
|
|
5
5
|
|
|
6
6
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
7
7
|
class CacheInvalidateTarget:
|
|
8
|
+
"""One exact cache key invalidation target."""
|
|
9
|
+
|
|
8
10
|
resource: CacheKey
|
|
9
11
|
params: dict[str, str]
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
13
15
|
class CacheInvalidatePatternTarget:
|
|
16
|
+
"""One pattern-based cache invalidation target."""
|
|
17
|
+
|
|
14
18
|
resource: CacheKey
|
|
15
19
|
params: dict[str, str]
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_read.py
RENAMED
|
@@ -52,6 +52,7 @@ def _serialize_attachment_variant(
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def serialize_image_attachments(*, attachment_links: Sequence[_ImageAttachmentLink]) -> dict[str, Any]:
|
|
55
|
+
"""Serialize image attachment links into API-ready thumb and display variant payloads."""
|
|
55
56
|
_, _, default_fallback_url = require_attachment_read_urls()
|
|
56
57
|
sorted_attachment_links = sorted(attachment_links, key=lambda link: link.asset_id)
|
|
57
58
|
return {
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_service.py
RENAMED
|
@@ -116,6 +116,8 @@ async def attachment_asset_has_link_row(*, asset_id: str) -> bool:
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
class _InsertImageAttachmentLink(Protocol):
|
|
119
|
+
"""Insert one image attachment link row for a content item."""
|
|
120
|
+
|
|
119
121
|
def __call__(
|
|
120
122
|
self,
|
|
121
123
|
*,
|
|
@@ -123,15 +125,25 @@ class _InsertImageAttachmentLink(Protocol):
|
|
|
123
125
|
asset_id: str,
|
|
124
126
|
display_width: int | None,
|
|
125
127
|
display_height: int | None,
|
|
126
|
-
) -> Awaitable[bool]:
|
|
128
|
+
) -> Awaitable[bool]:
|
|
129
|
+
"""Insert a link row and return whether a new row was created."""
|
|
130
|
+
...
|
|
127
131
|
|
|
128
132
|
|
|
129
133
|
class _DeleteImageAttachmentLink(Protocol):
|
|
130
|
-
|
|
134
|
+
"""Delete one image attachment link row for a content item."""
|
|
135
|
+
|
|
136
|
+
def __call__(self, *, content_id: str, asset_id: str) -> Awaitable[bool]:
|
|
137
|
+
"""Delete a link row and return whether a row was removed."""
|
|
138
|
+
...
|
|
131
139
|
|
|
132
140
|
|
|
133
141
|
class _SelectImageAttachmentAssetIds(Protocol):
|
|
134
|
-
|
|
142
|
+
"""List image attachment asset ids linked to a content item."""
|
|
143
|
+
|
|
144
|
+
def __call__(self, *, content_id: str) -> Awaitable[list[str]]:
|
|
145
|
+
"""Return asset ids currently linked to the content item."""
|
|
146
|
+
...
|
|
135
147
|
|
|
136
148
|
|
|
137
149
|
@dataclass(frozen=True)
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/read_url_config.py
RENAMED
|
@@ -12,6 +12,7 @@ _attachment_default_fallback_url: str | None = None
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def configure_media_read_urls(*, settings: Settings) -> None:
|
|
15
|
+
"""Load avatar, banner, and attachment public read URL settings from bootstrap config."""
|
|
15
16
|
global _avatar_default_url, _avatar_public_base_url, _avatar_extension
|
|
16
17
|
global _banner_default_url, _banner_public_base_url, _banner_extension
|
|
17
18
|
global _attachment_public_base_url, _attachment_extension, _attachment_default_fallback_url
|
|
@@ -27,6 +28,7 @@ def configure_media_read_urls(*, settings: Settings) -> None:
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def require_avatar_read_urls() -> tuple[str, str, str]:
|
|
31
|
+
"""Return configured avatar default URL, public base URL, and file extension."""
|
|
30
32
|
if _avatar_default_url is None or _avatar_public_base_url is None or _avatar_extension is None:
|
|
31
33
|
raise RuntimeError(
|
|
32
34
|
"Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
|
|
@@ -35,6 +37,7 @@ def require_avatar_read_urls() -> tuple[str, str, str]:
|
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
def require_banner_read_urls() -> tuple[str, str, str]:
|
|
40
|
+
"""Return configured banner default URL, public base URL, and file extension."""
|
|
38
41
|
if _banner_default_url is None or _banner_public_base_url is None or _banner_extension is None:
|
|
39
42
|
raise RuntimeError(
|
|
40
43
|
"Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
|
|
@@ -43,6 +46,7 @@ def require_banner_read_urls() -> tuple[str, str, str]:
|
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
def require_attachment_read_urls() -> tuple[str, str, str]:
|
|
49
|
+
"""Return configured attachment public base URL, file extension, and default fallback URL."""
|
|
46
50
|
if _attachment_public_base_url is None or _attachment_extension is None or _attachment_default_fallback_url is None:
|
|
47
51
|
raise RuntimeError(
|
|
48
52
|
"Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
|
|
@@ -9,6 +9,8 @@ USER_BLOCK_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "user.block"
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class UserBlockRelationshipChangedPayload(TypedDict):
|
|
12
|
+
"""Outbox payload for a user block relationship change."""
|
|
13
|
+
|
|
12
14
|
blocker_id: str
|
|
13
15
|
blocked_id: str
|
|
14
16
|
|
|
@@ -24,6 +26,7 @@ def build_user_block_relationship_changed_enqueue(
|
|
|
24
26
|
blocked_id: str,
|
|
25
27
|
commit_token: str,
|
|
26
28
|
) -> OutboxEnqueue:
|
|
29
|
+
"""Build an outbox enqueue for a user block relationship change."""
|
|
27
30
|
aggregate_id = aggregate_id_for_user_block(blocker_id=blocker_id, blocked_id=blocked_id)
|
|
28
31
|
payload: UserBlockRelationshipChangedPayload = {
|
|
29
32
|
"blocker_id": blocker_id,
|
|
@@ -46,6 +49,8 @@ USER_FOLLOW_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "user.follow"
|
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
class UserFollowRelationshipChangedPayload(TypedDict):
|
|
52
|
+
"""Outbox payload for a user follow relationship change."""
|
|
53
|
+
|
|
49
54
|
follower_id: str
|
|
50
55
|
followee_id: str
|
|
51
56
|
|
|
@@ -61,6 +66,7 @@ def build_user_follow_relationship_changed_enqueue(
|
|
|
61
66
|
followee_id: str,
|
|
62
67
|
commit_token: str,
|
|
63
68
|
) -> OutboxEnqueue:
|
|
69
|
+
"""Build an outbox enqueue for a user follow relationship change."""
|
|
64
70
|
aggregate_id = aggregate_id_for_user_follow(follower_id=follower_id, followee_id=followee_id)
|
|
65
71
|
payload: UserFollowRelationshipChangedPayload = {
|
|
66
72
|
"follower_id": follower_id,
|
|
@@ -83,6 +89,8 @@ MODERATION_RESTRICTION_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "moderation.res
|
|
|
83
89
|
|
|
84
90
|
|
|
85
91
|
class ModerationRestrictionRelationshipChangedPayload(TypedDict):
|
|
92
|
+
"""Outbox payload for a moderation restriction relationship change."""
|
|
93
|
+
|
|
86
94
|
user_id: str
|
|
87
95
|
|
|
88
96
|
|
|
@@ -96,6 +104,7 @@ def build_moderation_restriction_relationship_changed_enqueue(
|
|
|
96
104
|
user_id: str,
|
|
97
105
|
commit_token: str,
|
|
98
106
|
) -> OutboxEnqueue:
|
|
107
|
+
"""Build an outbox enqueue for a moderation restriction relationship change."""
|
|
99
108
|
payload: ModerationRestrictionRelationshipChangedPayload = {
|
|
100
109
|
"user_id": user_id,
|
|
101
110
|
}
|
|
@@ -2,16 +2,22 @@ from enum import StrEnum
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class EventType(StrEnum):
|
|
5
|
+
"""Analytics event kinds recorded for subject activity."""
|
|
6
|
+
|
|
5
7
|
LOGIN = "login"
|
|
6
8
|
VIEW = "view"
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class SubjectType(StrEnum):
|
|
12
|
+
"""Analytics subject kinds aggregated in daily facts."""
|
|
13
|
+
|
|
10
14
|
POST = "post"
|
|
11
15
|
USER = "user"
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
class WorkerJobName(StrEnum):
|
|
19
|
+
"""Registered ARQ worker job names."""
|
|
20
|
+
|
|
15
21
|
PROCESS_ACCOUNT_DELETION = "process_account_deletion"
|
|
16
22
|
PROCESS_USER_CONTENT_DELETION = "process_user_content_deletion"
|
|
17
23
|
PROCESS_ADMIN_USER_DELETION = "process_admin_user_deletion"
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/exceptions.py
RENAMED
|
@@ -1,58 +1,78 @@
|
|
|
1
1
|
class UnauthorizedException(Exception):
|
|
2
|
+
"""Signal that the caller lacks valid authentication."""
|
|
3
|
+
|
|
2
4
|
def __init__(self, message: str = "Unauthorized") -> None:
|
|
3
5
|
self.message = message
|
|
4
6
|
super().__init__(self.message)
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class ForbiddenException(Exception):
|
|
10
|
+
"""Signal that the caller is authenticated but not permitted."""
|
|
11
|
+
|
|
8
12
|
def __init__(self, message: str = "Forbidden") -> None:
|
|
9
13
|
self.message = message
|
|
10
14
|
super().__init__(self.message)
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class UserNotFoundException(Exception):
|
|
18
|
+
"""Signal that the requested user does not exist or is not visible."""
|
|
19
|
+
|
|
14
20
|
def __init__(self, message: str = "User not found") -> None:
|
|
15
21
|
self.message = message
|
|
16
22
|
super().__init__(self.message)
|
|
17
23
|
|
|
18
24
|
|
|
19
25
|
class ContentNotFoundException(Exception):
|
|
26
|
+
"""Signal that the requested content does not exist or is not visible."""
|
|
27
|
+
|
|
20
28
|
def __init__(self, message: str = "Content not found") -> None:
|
|
21
29
|
self.message = message
|
|
22
30
|
super().__init__(self.message)
|
|
23
31
|
|
|
24
32
|
|
|
25
33
|
class BadRequestException(Exception):
|
|
34
|
+
"""Signal a caller mistake that should map to HTTP 400."""
|
|
35
|
+
|
|
26
36
|
def __init__(self, message: str = "Bad request") -> None:
|
|
27
37
|
self.message = message
|
|
28
38
|
super().__init__(self.message)
|
|
29
39
|
|
|
30
40
|
|
|
31
41
|
class ConflictException(Exception):
|
|
42
|
+
"""Signal a state conflict that should map to HTTP 409."""
|
|
43
|
+
|
|
32
44
|
def __init__(self, message: str = "Conflict") -> None:
|
|
33
45
|
self.message = message
|
|
34
46
|
super().__init__(self.message)
|
|
35
47
|
|
|
36
48
|
|
|
37
49
|
class IngestBodyTooLargeException(Exception):
|
|
50
|
+
"""Signal that an ingest payload exceeds the configured size limit."""
|
|
51
|
+
|
|
38
52
|
def __init__(self, message: str = "Ingest body too large") -> None:
|
|
39
53
|
self.message = message
|
|
40
54
|
super().__init__(self.message)
|
|
41
55
|
|
|
42
56
|
|
|
43
57
|
class IngestUnsupportedMediaTypeException(Exception):
|
|
58
|
+
"""Signal that an ingest Content-Type is not allowed."""
|
|
59
|
+
|
|
44
60
|
def __init__(self, message: str = "Ingest unsupported media type") -> None:
|
|
45
61
|
self.message = message
|
|
46
62
|
super().__init__(self.message)
|
|
47
63
|
|
|
48
64
|
|
|
49
65
|
class AppealAlreadyDecidedException(Exception):
|
|
66
|
+
"""Signal that a moderation appeal was already decided."""
|
|
67
|
+
|
|
50
68
|
def __init__(self, message: str = "Appeal already decided") -> None:
|
|
51
69
|
self.message = message
|
|
52
70
|
super().__init__(self.message)
|
|
53
71
|
|
|
54
72
|
|
|
55
73
|
class InvariantViolationException(Exception):
|
|
74
|
+
"""Signal an internal invariant breach that should map to HTTP 500."""
|
|
75
|
+
|
|
56
76
|
def __init__(self, message: str = "Invariant violation") -> None:
|
|
57
77
|
self.message = message
|
|
58
78
|
super().__init__(self.message)
|
{core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/deletion_audit.py
RENAMED
|
@@ -3,6 +3,7 @@ from core_framework.domains.user import UserIdentity
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def username_for_audit_from_identity(*, identity: UserIdentity) -> str | None:
|
|
6
|
+
"""Return a username for deletion audit logs, or ``None`` for the default identity."""
|
|
6
7
|
return identity.username if identity != UserIdentity.DEFAULT else None
|
|
7
8
|
|
|
8
9
|
|
|
@@ -2,5 +2,9 @@ from enum import StrEnum
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class AdminUserDeletionType(StrEnum):
|
|
5
|
+
"""Admin-initiated user deletion strategies."""
|
|
6
|
+
|
|
5
7
|
REMOVE_ACCOUNT_TOMBSTONE_AUTHORED_CONTENT = "remove_account_tombstone_authored_content"
|
|
6
8
|
REMOVE_ACCOUNT_DELETE_AUTHORED_CONTENT = "remove_account_delete_authored_content"
|
|
9
|
+
TOMBSTONE_AUTHORED_POSTS_ONLY = "tombstone_authored_posts_only"
|
|
10
|
+
TOMBSTONE_AUTHORED_COMMENTS_ONLY = "tombstone_authored_comments_only"
|
|
@@ -145,14 +145,25 @@ async def _run_remove_account_delete_authored_content(*, target_user_id: str) ->
|
|
|
145
145
|
await _remove_user(target_user_id=target_user_id, preserve_authored_content=False)
|
|
146
146
|
|
|
147
147
|
|
|
148
|
-
async def
|
|
149
|
-
|
|
148
|
+
async def _run_tombstone_authored_posts_only(*, target_user_id: str) -> None:
|
|
149
|
+
await _tombstone_moderator_authored_posts_for_user(user_id=target_user_id)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
async def _run_tombstone_authored_comments_only(*, target_user_id: str) -> None:
|
|
153
|
+
await _tombstone_moderator_authored_comments_for_user(user_id=target_user_id)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
async def _tombstone_moderator_authored_posts_for_user(*, user_id: str) -> None:
|
|
157
|
+
"""Tombstone active authored posts as ``tombstoned_by_moderator`` without per-item audit."""
|
|
150
158
|
post_impact = await post_deps.post_service.tombstone_posts_by_author_id(
|
|
151
159
|
author_id=user_id,
|
|
152
160
|
tombstone_status=PostStatus.TOMBSTONED_BY_MODERATOR,
|
|
153
161
|
)
|
|
154
162
|
await finalize_author_posts_tombstone_cleanup(impact=post_impact)
|
|
155
163
|
|
|
164
|
+
|
|
165
|
+
async def _tombstone_moderator_authored_comments_for_user(*, user_id: str) -> None:
|
|
166
|
+
"""Tombstone active authored comments as ``tombstoned_by_moderator`` without per-item audit."""
|
|
156
167
|
comment_impact = await comment_deps.comment_service.tombstone_comments_by_author_id(
|
|
157
168
|
author_id=user_id,
|
|
158
169
|
tombstone_status=CommentStatus.TOMBSTONED_BY_MODERATOR,
|
|
@@ -164,6 +175,12 @@ async def _tombstone_moderator_authored_content_for_user(*, user_id: str) -> Non
|
|
|
164
175
|
)
|
|
165
176
|
|
|
166
177
|
|
|
178
|
+
async def _tombstone_moderator_authored_content_for_user(*, user_id: str) -> None:
|
|
179
|
+
"""Tombstone active authored posts and comments as ``tombstoned_by_moderator`` without per-item audit."""
|
|
180
|
+
await _tombstone_moderator_authored_posts_for_user(user_id=user_id)
|
|
181
|
+
await _tombstone_moderator_authored_comments_for_user(user_id=user_id)
|
|
182
|
+
|
|
183
|
+
|
|
167
184
|
async def _destructive_authored_content_purge(*, author_id: str) -> None:
|
|
168
185
|
"""Destructively remove all posts and remaining comments authored by ``author_id``."""
|
|
169
186
|
authored_post_ids = frozenset(
|
|
@@ -216,6 +233,8 @@ async def _mark_stats_dirty_for_author_comment_impacts(
|
|
|
216
233
|
_ADMIN_USER_DELETION_STRATEGIES: dict[AdminUserDeletionType, AdminUserDeletionRunner] = {
|
|
217
234
|
AdminUserDeletionType.REMOVE_ACCOUNT_TOMBSTONE_AUTHORED_CONTENT: _run_remove_account_tombstone_authored_content,
|
|
218
235
|
AdminUserDeletionType.REMOVE_ACCOUNT_DELETE_AUTHORED_CONTENT: _run_remove_account_delete_authored_content,
|
|
236
|
+
AdminUserDeletionType.TOMBSTONE_AUTHORED_POSTS_ONLY: _run_tombstone_authored_posts_only,
|
|
237
|
+
AdminUserDeletionType.TOMBSTONE_AUTHORED_COMMENTS_ONLY: _run_tombstone_authored_comments_only,
|
|
219
238
|
}
|
|
220
239
|
|
|
221
240
|
|
|
@@ -14,6 +14,11 @@ DB_NOT_CONNECTED_MSG: Final[str] = "Database is not connected"
|
|
|
14
14
|
DB_ALREADY_CONNECTED_MSG: Final[str] = "Database is already connected"
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def quote_postgres_identifier(identifier: str) -> str:
|
|
18
|
+
"""Return a double-quoted Postgres identifier (schema, table, or column name)."""
|
|
19
|
+
return f'"{identifier.replace('"', '""')}"'
|
|
20
|
+
|
|
21
|
+
|
|
17
22
|
class Postgres:
|
|
18
23
|
__slots__ = ("_pool", "_database_url", "_min_connections", "_max_connections")
|
|
19
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from core_framework.domains.analytics.constants import DAILY_FACT_RETENTION_DAYS
|
|
2
2
|
from core_framework.domains.analytics.exceptions import BaseAnalyticsException
|
|
3
|
-
from core_framework.domains.analytics.models import DailyFactBucket, DailyFactDayTotal
|
|
3
|
+
from core_framework.domains.analytics.models import DailyFactBucket, DailyFactDayTotal, DailyFactKindTotal
|
|
4
4
|
from core_framework.domains.analytics.ports.activity_source import ActivityCount, ActivitySourcePort
|
|
5
5
|
|
|
6
6
|
__all__ = [
|
|
@@ -10,4 +10,5 @@ __all__ = [
|
|
|
10
10
|
"DAILY_FACT_RETENTION_DAYS",
|
|
11
11
|
"DailyFactBucket",
|
|
12
12
|
"DailyFactDayTotal",
|
|
13
|
+
"DailyFactKindTotal",
|
|
13
14
|
]
|