core-framework 2.3.1__tar.gz → 2.3.3__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.1 → core_framework-2.3.3}/.cursor/rules/api-reference-docs.mdc +9 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/constitution.mdc +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/error-boundary.mdc +3 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/no-code-in-docs.mdc +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/add-domain/SKILL.md +1 -1
- core_framework-2.3.3/.cursor/skills/implement-feature/SKILL.md +93 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/sync-host-rules/SKILL.md +5 -5
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/write-flow-doc/SKILL.md +2 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/CHANGELOG.md +55 -5
- {core_framework-2.3.1 → core_framework-2.3.3}/PKG-INFO +3 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/README.md +2 -0
- core_framework-2.3.3/alembic/analytics/alembic/versions/2d61a5e88d76_analytics_utm_events_add_kind.py +36 -0
- core_framework-2.3.3/alembic/analytics/alembic/versions/585105e1149e_analytics_add_utm_events.py +38 -0
- core_framework-2.3.3/alembic/user/alembic/versions/44df70a45ba6_user_add_signup_events.py +32 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/config.toml +1 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/config.toml.template +1 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/auth/schemas.py +1 -12
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/dependencies.py +12 -14
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/auth/access_service.py +2 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/bootstrap.py +2 -5
- core_framework-2.3.3/core_framework/application/events/README.md +31 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/events/event_service.py +63 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/events/event_token.py +2 -2
- core_framework-2.3.3/core_framework/application/events/utm_capture_kinds.py +30 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/shared/enums.py +3 -1
- core_framework-2.3.3/core_framework/application/shared/request_context.py +66 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/admin_service.py +0 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/public_service.py +4 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/cache.py +18 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/README.md +18 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/__init__.py +9 -1
- core_framework-2.3.3/core_framework/domains/analytics/constants.py +19 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/repository.py +29 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/service.py +65 -1
- core_framework-2.3.3/core_framework/domains/auth/README.md +68 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/README.md +2 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/README.md +3 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/README.md +2 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/README.md +3 -3
- core_framework-2.3.3/core_framework/domains/outbox/README.md +65 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/README.md +2 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/README.md +7 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/repository.py +25 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/service.py +21 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/auth.py +0 -19
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_expired_account_deletions.py +1 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +1 -0
- core_framework-2.3.3/docs/README.md +46 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/README.md +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/deploy-playbook.md +2 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/edge-upload-limits.md +1 -1
- core_framework-2.3.3/docs/deployments/guides/app-server-deploy-ssh.md +78 -0
- core_framework-2.3.3/docs/deployments/guides/image-server-ssh.md +93 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/guides/ubuntu-server-setup.md +1 -0
- core_framework-2.3.3/docs/design/README.md +30 -0
- {core_framework-2.3.1/docs/platform → core_framework-2.3.3/docs/design}/analytics-rollup-design.md +40 -45
- core_framework-2.3.3/docs/design/cache-invalidation-design.md +141 -0
- {core_framework-2.3.1/docs/platform → core_framework-2.3.3/docs/design}/create-idempotency-design.md +19 -18
- {core_framework-2.3.1/docs/platform → core_framework-2.3.3/docs/design}/event-outbox-design.md +50 -169
- core_framework-2.3.3/docs/design/events-ingest-design.md +226 -0
- {core_framework-2.3.1/docs/platform → core_framework-2.3.3/docs/design}/media-storage-topology.md +2 -2
- {core_framework-2.3.1/docs/platform → core_framework-2.3.3/docs/design}/outbox-admin-ops-design.md +3 -3
- core_framework-2.3.3/docs/design/utm-events-design.md +272 -0
- core_framework-2.3.3/docs/domains/README.md +23 -0
- core_framework-2.3.3/docs/domains/analytics/admin_analytics_reads.md +135 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/auth/access_control.md +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/auth/registration.md +4 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/cache/admin_cache_invalidation.md +11 -50
- core_framework-2.3.3/docs/domains/comments/README.md +31 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/admin_comments.md +6 -5
- core_framework-2.3.3/docs/domains/comments/comment_like.md +96 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/comment_report.md +4 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/comment_stats_aggregation.md +6 -7
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/create_comment.md +22 -18
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/edit_comment.md +7 -5
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/retrieve_comments.md +13 -9
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/deletion/comments.md +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/deletion/overview.md +11 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/deletion/posts.md +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/deletion/users.md +65 -63
- core_framework-2.3.3/docs/domains/events/events.md +242 -0
- core_framework-2.3.3/docs/domains/media/README.md +36 -0
- core_framework-2.3.3/docs/domains/media/attachment_upload.md +73 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/media/avatar-upload-design.md +9 -9
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/media/banner-upload-design.md +14 -14
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/media/post-comment-attachments-design.md +9 -9
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/media/upload-pipeline-design.md +51 -46
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/media/upload_pipeline.md +20 -5
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/mentions/mentions_in_content.md +12 -11
- core_framework-2.3.3/docs/domains/moderation/README.md +28 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/moderation/appeals.md +18 -8
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/moderation/internal_notes.md +11 -10
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/moderation/moderator_actions.md +6 -5
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/moderation/reports.md +10 -8
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/moderation/restrictions.md +55 -23
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/notifications/notification_inbox.md +19 -17
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/outbox/admin_outbox_ops.md +8 -6
- core_framework-2.3.3/docs/domains/posts/README.md +33 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/admin_posts.md +8 -6
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/author_context.md +1 -1
- core_framework-2.3.3/docs/domains/posts/create_post.md +112 -0
- core_framework-2.3.3/docs/domains/posts/edit_post.md +80 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/hashtag_discovery.md +6 -4
- core_framework-2.3.3/docs/domains/posts/post_report.md +105 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/post_stats_aggregation.md +7 -8
- core_framework-2.3.3/docs/domains/posts/retrieve_posts.md +190 -0
- core_framework-2.3.3/docs/domains/users/account.md +106 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/account_deletion.md +6 -7
- core_framework-2.3.3/docs/domains/users/admin_users.md +166 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/avatar.md +1 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/banner.md +7 -8
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/blocks.md +10 -9
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/change_history.md +5 -4
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/check_username_exists.md +3 -3
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/follow-system-design.md +26 -32
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/follow.md +13 -10
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/my_posts_and_comments.md +4 -4
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/preferences.md +1 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/public_profile.md +5 -5
- core_framework-2.3.3/docs/domains/users/user_removal.md +86 -0
- core_framework-2.3.3/docs/domains/users/user_stats_aggregation.md +79 -0
- core_framework-2.3.3/docs/library/README.md +15 -0
- core_framework-2.3.3/docs/library/api.md +212 -0
- core_framework-2.3.3/docs/library/capability-wiring.md +123 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/library/core-framework-migration.md +21 -65
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/library/overview.md +19 -17
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/library/package-api.md +37 -7
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/library/testing-plugin-design.md +23 -26
- core_framework-2.3.3/docs/library/workers.md +81 -0
- core_framework-2.3.3/docs/platform/README.md +18 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/architecture-decisions.md +11 -13
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/client-error-visibility.md +100 -56
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/conventions.md +22 -1
- core_framework-2.3.3/docs/platform/domain-services-and-adapters.md +60 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/patch-update-typed-payload.md +2 -1
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/testing.md +14 -13
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/todo.md +1 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/pyproject.toml +2 -2
- core_framework-2.3.3/tests/integration/api/events/router_test.py +759 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/post_stats_dirty_marking_test.py +2 -2
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/application/events/event_service_test.py +47 -1
- core_framework-2.3.3/tests/unit/application/shared/request_context_test.py +30 -0
- core_framework-2.3.3/tests/unit/docs/_api_reference.py +67 -0
- core_framework-2.3.3/tests/unit/docs/api_routes_test.py +54 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/domains/user/service_test.py +46 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/uv.lock +101 -12
- core_framework-2.3.1/.cursor/skills/implement-feature/SKILL.md +0 -66
- core_framework-2.3.1/core_framework/application/events/README.md +0 -35
- core_framework-2.3.1/core_framework/application/shared/user_agent.py +0 -25
- core_framework-2.3.1/core_framework/domains/analytics/constants.py +0 -3
- core_framework-2.3.1/docs/README.md +0 -30
- core_framework-2.3.1/docs/deployments/guides/app-server-deploy-ssh.md +0 -55
- core_framework-2.3.1/docs/deployments/guides/image-server-ssh.md +0 -62
- core_framework-2.3.1/docs/domains/README.md +0 -18
- core_framework-2.3.1/docs/domains/events/events.md +0 -126
- core_framework-2.3.1/docs/domains/users/account.md +0 -61
- core_framework-2.3.1/docs/domains/users/user_removal.md +0 -133
- core_framework-2.3.1/docs/library/README.md +0 -12
- core_framework-2.3.1/docs/library/api.md +0 -205
- core_framework-2.3.1/docs/platform/README.md +0 -19
- core_framework-2.3.1/docs/platform/domain-services-and-adapters.md +0 -116
- core_framework-2.3.1/docs/platform/events-ingest-design.md +0 -109
- core_framework-2.3.1/tests/integration/api/events/router_test.py +0 -180
- {core_framework-2.3.1 → core_framework-2.3.3}/.agents/skills/fastapi +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.agents/skills/library-skills/.library-skills.json +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.agents/skills/library-skills/SKILL.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/alembic-migrations.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/api-layer.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/api-validation.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/application-layer.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/constants-final.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/database-triggers.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/docstrings.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/domain-caller-context.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/domain-imports.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/domain-input-guards.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/domain-services-and-adapters.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/flow-documentation.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/inline-raise-messages.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/integration-test-strategy.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/layer-boundaries.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/postgres-config-conventions.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/repository-schema-isolation.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/strong-reads.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/rules/structured-logging.mdc +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/add-config/SKILL.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/code-review/SKILL.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/fastapi +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.cursor/skills/recommend-features/SKILL.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.dockerignore +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.github/workflows/_deploy.yml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.github/workflows/dev-ci-cd.yaml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.github/workflows/manual-deployment.yaml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.github/workflows/publish-pypi.yml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.github/workflows/test.yaml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.gitignore +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.pre-commit-config.yaml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/.python-version +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/LICENSE +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic/versions/5b9ac98bb150_analytics_daily_fact.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic/versions/7f2a9c1d4e8b_analytics_daily_fact_day_index.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/analytics/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_attachments.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency_created_at_index.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_mentions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_tombstone_status_model.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/comment/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/extension/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/extension/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/extension/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/extension/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/versions/media_add_attachment_staging_registry.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/versions/media_attachment_staging_registry_published_at.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/media/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/moderation/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/notification/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/notification/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/notification/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/notification/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_attachments.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_create_idempotency.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_create_idempotency_created_at_index.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_mentions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_post_views_retention_high_water_mark.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/post_tombstone_status_model.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/post/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/README +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/env.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/script.py.mako +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox_dead_indexes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox_pending_created_at_index.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/user_reserve_sentinel_user_ids.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/alembic/user/alembic.ini +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/analytics/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/analytics/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/cache/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/cache/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/comments/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/comments/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/moderation/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/moderation/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/moderation/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/outbox/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/outbox/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/posts/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/posts/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/users/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/users/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/admin/users/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/attachments/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/attachments/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/auth/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/auth/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/authenticated/mappers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/authenticated/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/authenticated/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/public/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/public/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/comments/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/events/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/events/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/idempotency/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/idempotency/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/notifications/authenticated/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/notifications/authenticated/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/notifications/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/authenticated/mappers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/authenticated/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/authenticated/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/public/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/public/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/posts/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/system/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/system/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/authenticated/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/authenticated/mappers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/authenticated/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/authenticated/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/mappers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/public/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/public/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/public/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/router.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/api/users/shared/schemas.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/bucket_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/prune_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/read_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/refresh_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/registry.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/sources/comment_created.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/sources/post_created.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/sources/post_viewed.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/analytics/sources/user_registered.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/auth/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/auth/auth_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/auth/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/cache/invalidate_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/cache/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/comments/admin_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/comments/aggregation_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/comments/authenticated_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/comments/cleanup_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/comments/public_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/events/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/README.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/attachment_read.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/attachment_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/avatar_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/banner_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/ingest_guards.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/media/read_url_config.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/appeal_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/moderator_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/report_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/scheduled_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/moderation/user_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/notifications/README.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/notifications/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/notifications/inbox_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/notifications/mute_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/notifications/notification_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/block_mirrors.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/events.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/follow_mirrors.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/handlers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/ops_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/polling_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/processing_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/outbox/restriction_mirrors.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/posts/admin_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/posts/aggregation_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/posts/authenticated_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/posts/cleanup_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/posts/public_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/shared/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/shared/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/shared/worker_jobs.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/aggregation_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/authenticated_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/deletion_audit.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/scheduled_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/users/user_deletion_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/asgi.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/bundled_alembic.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/context.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/database.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/exception_handlers/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/exception_handlers/application.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/exception_handlers/common.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/exception_handlers/setup.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/firebase.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/http_client.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/logging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/middleware.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/observability.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/pagination.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/redis.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/runtime.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/core/settings.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/analytics/ports/activity_source.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/ports/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/ports/auth.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/auth/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/outcomes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/comment/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/attachment/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/avatar/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/components/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/components/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/components/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/finals_publisher.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/variant_encoder.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/banner/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/outcomes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/media/shared/utils.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/outbox_repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/outbox_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/outcomes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/moderation/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/notification/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/ports/admin.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/ports/consumer.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/ports/producer.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/outbox/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/outcomes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/post/service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/constants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/dependencies.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/enums.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/exceptions.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/models.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/outbox_repository.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/outbox_service.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/outcomes.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/user/utils.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/domains/utils.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/firebase/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/firebase/firebase_auth_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/attachment_staging_display_geometry.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/local_attachment_staging_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/local_banner_staging_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/local_staging_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_attachment_variant_encoder_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_staging_image.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_attachment_finals_publisher_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/outbox/outbox_consumer_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/infrastructure/outbox/outbox_producer_adapter.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/main.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/migrate_cli.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/arq.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/config.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/containers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/firebase.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/firebase_identity_toolkit.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/hookspecs.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/httpx_test_client.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/media.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/migrations.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/testing/plugin.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/main.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/analytics_refresh_cron.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_poll_outbox.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_prune_analytics_daily_facts.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_prune_post_views.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_refresh_analytics.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_attachment_staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/delete_attachment_finals.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/delete_superseded_banner_finals.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_account_deletion.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_admin_user_deletion.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_comment_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_post_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_user_stats.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_attachment_asset_variants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_banner_asset_variants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_cache_pattern_invalidation.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_destructive_comment_delete.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_destructive_post_delete.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_media_asset_variants.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_mute_lift.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_outbox_row.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_refresh_analytics_bucket.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/tasks/process_user_content_deletion.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/core_framework/worker/worker_context.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docker-compose.dev.yaml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docker-compose.yml +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/dockerfile +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/e2e-smoke-tests-design.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/examples/Caddyfile.example +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/examples/image-server-known-hosts.example +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/guides/postgres-setup.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/guides/redis-setup.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/deployments/release-playbook.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/comments/delete_comment.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/post_like.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/posts/post_visibility.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/domains/users/profile.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/database-triggers.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/docs/platform/layers-and-boundaries.md +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/firebase_config.example.json +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/makefile +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/conftest.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/_auth.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/_canaries.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/_media.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/_settings.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/_upload_payloads.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/conftest.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/media/pipeline_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/smoke/canary_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/smoke/media_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/smoke/system_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/e2e/smoke/tls_host_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/_http_error_details.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/analytics/_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_auth_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_destructive_delete_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_http_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_outbox_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_user_deletion_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/_user_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/_auth_cases.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/analytics/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/analytics/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/cache/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/cache/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/comments/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/comments/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/moderation/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/moderation/_auth_cases.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/moderation/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/outbox/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/outbox/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/posts/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/posts/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/users/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/admin/users/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/attachments/_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/attachments/attachment_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/auth/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/auth/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/authenticated/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/comment_attachments_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/public/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/comments/public/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/create_idempotency_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/media/ingest_contract_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/mentions/mentions_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/notifications/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/notifications/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/followers_visibility_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/post_attachments_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/post_deletion_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/public/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/posts/public/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/public_read_by_id_unavailable_detail_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/system/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/system/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/authenticated/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/authenticated/avatar_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/authenticated/banner_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/authenticated/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/deletion_audit_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/public/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/public/router_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/api/users/user_deletion_integration_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/_media_upload_helpers.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/account_deletion_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/aggregate_comment_stats_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/aggregate_post_stats_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/aggregate_user_stats_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/analytics_prune_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/analytics_refresh_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/attachment_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/avatar_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/banner_upload_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/conftest.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/create_idempotency_retention_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/moderation_outbox_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/mute_lift_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/stale_staging_sweep_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/user_outbox_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/integration/worker/utils_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/api/comments/authenticated/comment_request_schemas_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/api/dedupe_preserving_order_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/api/posts/authenticated/post_update_mapper_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/api/users/profile_update_mapper_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/application/comments/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/application/notifications/inbox_service_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/application/users/deletion_audit_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/core/bundled_alembic_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/core/migrate_cli_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/core/pagination_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/domains/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/domains/comment/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/domains/post/models_test.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/infrastructure/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/infrastructure/media/__init__.py +0 -0
- {core_framework-2.3.1 → core_framework-2.3.3}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +0 -0
|
@@ -29,3 +29,12 @@ globs:
|
|
|
29
29
|
- Detailed behavior notes
|
|
30
30
|
|
|
31
31
|
For detailed API behavior, create or update flow documentation in `docs/domains/` instead.
|
|
32
|
+
|
|
33
|
+
## CI contract
|
|
34
|
+
|
|
35
|
+
`tests/unit/docs/api_routes_test.py` parses this file and asserts **bidirectional** parity with the core FastAPI app:
|
|
36
|
+
|
|
37
|
+
- every listed `(METHOD, path)` exists on the app with **matching path-param names**
|
|
38
|
+
- every app `(METHOD, path)` (GET/POST/PUT/PATCH/DELETE) is listed here
|
|
39
|
+
|
|
40
|
+
Flow docs under `docs/domains/` must not list endpoints in their `http` blocks unless those exact routes appear here. Update this index when adding or renaming routes.
|
|
@@ -39,4 +39,4 @@ Do not edit consuming host repos in the same task as core-framework work unless
|
|
|
39
39
|
|
|
40
40
|
## Feature implementation
|
|
41
41
|
|
|
42
|
-
Greenfield features (DB → API → repository → service → tests): use the **implement-feature** skill — one layer per response unless the user says otherwise.
|
|
42
|
+
Greenfield features (DB → API → repository → service → **documentation** → tests): use the **implement-feature** skill — one layer per response unless the user says otherwise. A feature is **not done** until documentation is updated.
|
|
@@ -16,10 +16,10 @@ Platform contract: **`docs/platform/client-error-visibility.md`**. Domain import
|
|
|
16
16
|
|
|
17
17
|
| Layer | Outward errors | HTTP |
|
|
18
18
|
|-------|----------------|------|
|
|
19
|
-
| **Application** | **`application.shared.exceptions`**, **`InvalidPageTokenError`** | Handlers map type → status +
|
|
19
|
+
| **Application** | **`application.shared.exceptions`**, **`InvalidPageTokenError`** | Handlers map type → status + catalog **`detail`** |
|
|
20
|
+
| **API** | Pydantic; **`HTTPException`** for transport-local guards | **422** field errors; router-chosen status + **`detail`** |
|
|
20
21
|
| **Domain typed** | Internal — not imported by API/application | No typed handlers |
|
|
21
22
|
| **Domain `BaseXxxException`** | Handler catch-all only | **500** if leaked |
|
|
22
|
-
| **API** | Pydantic | **422** |
|
|
23
23
|
|
|
24
24
|
## Application and domain
|
|
25
25
|
|
|
@@ -47,7 +47,7 @@ Platform contract: **`docs/platform/client-error-visibility.md`**. Domain import
|
|
|
47
47
|
|
|
48
48
|
## Validation order
|
|
49
49
|
|
|
50
|
-
User-fixable input shape → API schemas (**422**). Domain backstops → **`DomainValidationError`** → generic **400
|
|
50
|
+
User-fixable input shape → API schemas (**422**) or router **`HTTPException`**. Use-case outcomes → application exceptions + handlers. Domain backstops → **`DomainValidationError`** → generic **400** (never domain text in **`detail`**).
|
|
51
51
|
|
|
52
52
|
## Logging
|
|
53
53
|
|
|
@@ -28,7 +28,7 @@ Documentation under **`docs/`** must not carry **implementation** snippets that
|
|
|
28
28
|
## Exceptions
|
|
29
29
|
|
|
30
30
|
- **Deployment runbooks** under **`docs/deployments/`** (setup guides, deploy/release playbooks, SSH/image-server guides) may include fenced **`bash`** shell blocks. These are operator instructions for interactive server setup, not implementation that drifts from source; copy-paste commands are the practical content. This exemption does **not** extend to **`docs/deployments/*-design.md`** design docs, which follow the general rules above.
|
|
31
|
-
- **Design docs** under **`docs/platform
|
|
31
|
+
- **Design docs** under **`docs/design/`**, **`docs/platform/`**, and **`docs/library/`** (and **`docs/deployments/*-design.md`**) follow the general allow/exclude lists — DDL is allowed, DML and Python are not. Flow docs under **`docs/domains/**`** are stricter: see **`flow-documentation.mdc`** (no DDL, no JSON request bodies, fields described as text/tables).
|
|
32
32
|
|
|
33
33
|
## Rationale
|
|
34
34
|
|
|
@@ -18,7 +18,7 @@ Follow the **implement-feature** skill: one step per response, wait for review.
|
|
|
18
18
|
Not every domain owns persistence. A **capability-only** domain wraps a non-SQL capability (for example `auth`, which wraps Firebase Admin via `domains/auth/ports/`, `domains/auth/service.py`, and `core_framework/infrastructure/firebase/`). For those, **skip** schema config, the Alembic tree, and `ALEMBIC_DOMAINS` entirely — no `schema_<domain>` in `PostgresSchemasConfig` / `[postgres_schemas]`, no `alembic/<domain>/`, no repository. Scaffold only:
|
|
19
19
|
|
|
20
20
|
- `domains/<domain>/{__init__.py, exceptions.py, models.py, ports/, service.py, dependencies.py}`
|
|
21
|
-
- A port (`<Name>Port`) describing the capability, a facade `*Service` over it, and an adapter under `core_framework/infrastructure/<domain>/` wired in `dependencies.py` — see `docs/platform/domain-services-and-adapters.md` (
|
|
21
|
+
- A port (`<Name>Port`) describing the capability, a facade `*Service` over it, and an adapter under `core_framework/infrastructure/<domain>/` wired in `dependencies.py` — see `docs/platform/domain-services-and-adapters.md` (rules) and `docs/library/capability-wiring.md` (Auth example).
|
|
22
22
|
- Export only `Base<Domain>Exception` + public models from `__init__.py`; keep the facade service in `dependencies.py`.
|
|
23
23
|
- Wire `configure_<domain>_dependencies()` in `application/bootstrap.py` (no `runtime` needed when there is no Postgres handle).
|
|
24
24
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implement-feature
|
|
3
|
+
description: Step-by-step feature implementation — DB → API → repository → service/application → documentation → tests. Use when adding a new feature, endpoint, or domain behavior across layers, or when the user asks to follow the implementation workflow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement Feature
|
|
7
|
+
|
|
8
|
+
Implement **one step at a time**. Stop after each step and wait for user review. Do **not** skip ahead or implement multiple layers in one response unless the user **explicitly** says "implement everything" or "do it all at once".
|
|
9
|
+
|
|
10
|
+
## Definition of done
|
|
11
|
+
|
|
12
|
+
A feature is **not complete** until **all** documentation for the shipped behavior is updated. Code merged without matching docs is **unfinished work** — do not treat the feature as done or move on until the documentation step is accepted.
|
|
13
|
+
|
|
14
|
+
## Before you start
|
|
15
|
+
|
|
16
|
+
- Do **not** implement repository, service, or application code when doing the API layer.
|
|
17
|
+
- Do **not** implement multiple layers in a single response.
|
|
18
|
+
- When in doubt, do **less** and wait for review.
|
|
19
|
+
|
|
20
|
+
## 1. Database changes (if needed)
|
|
21
|
+
|
|
22
|
+
- **Only** create the Alembic migration file(s).
|
|
23
|
+
- **No** code changes anywhere else.
|
|
24
|
+
- Wait for the user to review and accept the database structure before proceeding.
|
|
25
|
+
|
|
26
|
+
## 2. API layer (if needed)
|
|
27
|
+
|
|
28
|
+
After the user accepts database changes (or if there were none):
|
|
29
|
+
|
|
30
|
+
- **Only** implement the API layer: schemas and router.
|
|
31
|
+
- Follow the **fastapi** skill (`.agents/skills/fastapi/`) and **`api-layer`** / **`api-validation`** / **`error-boundary`** rules.
|
|
32
|
+
- **No** changes in domain, service, or application layers.
|
|
33
|
+
- Include request/response schemas, error handling, and HTTP-related logic.
|
|
34
|
+
- If the feature is not yet implemented, return 501 Not Implemented from the route.
|
|
35
|
+
- Wait for the user to review and accept before proceeding.
|
|
36
|
+
|
|
37
|
+
## 3. Repository and domain model
|
|
38
|
+
|
|
39
|
+
After the user accepts the API layer (or if there was no API layer):
|
|
40
|
+
|
|
41
|
+
- Implement the **Repository** for the domain layer (Postgres only).
|
|
42
|
+
- Include the **domain model** if data is retrieved from the database.
|
|
43
|
+
- If the feature needs non-SQL I/O (filesystem, HTTP, SSH), add **ports** in the domain and **adapter implementations** under `core_framework/infrastructure/<domain>/` per `docs/platform/domain-services-and-adapters.md` — not in the repository.
|
|
44
|
+
- Wait for the user to review and accept before proceeding.
|
|
45
|
+
|
|
46
|
+
## 4. Service and application layer
|
|
47
|
+
|
|
48
|
+
After the user accepts the repository (and any ports/adapters):
|
|
49
|
+
|
|
50
|
+
- Implement **domain service(s)** (persistence and any port-backed collaborators); wire in `dependencies.py`.
|
|
51
|
+
- Implement the **application** layer (orchestration across domains and transports — no permanent home for raw I/O libraries).
|
|
52
|
+
- Wire everything together (replace 501 with real logic).
|
|
53
|
+
- Wait for the user to review and accept before proceeding.
|
|
54
|
+
|
|
55
|
+
## 5. Documentation (required)
|
|
56
|
+
|
|
57
|
+
After the user accepts the service and application layer:
|
|
58
|
+
|
|
59
|
+
Update **every** doc surface the feature touches. Use the **write-flow-doc** skill for new or changed HTTP behavior. Follow **`no-code-in-docs.mdc`** and **`flow-documentation.mdc`**.
|
|
60
|
+
|
|
61
|
+
| Change | Update |
|
|
62
|
+
| ------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
63
|
+
| New or changed HTTP endpoint | Flow doc under `docs/domains/{domain}/`; add **`Current Implementation Status`** |
|
|
64
|
+
| New or changed route in the index | `docs/library/api.md` (endpoint list only — see **`api-reference-docs.mdc`**) |
|
|
65
|
+
| New flow or design doc file | `docs/domains/README.md` (and `docs/design/README.md` if cross-cutting) |
|
|
66
|
+
| New cross-cutting mechanism | `docs/design/*-design.md` |
|
|
67
|
+
| New or changed worker schedule or ARQ task | `docs/library/workers.md`; link from domain flow or design doc |
|
|
68
|
+
| Domain scope, tables, or invariants changed | `core_framework/domains/{domain}/README.md` |
|
|
69
|
+
| New audit trigger | `docs/platform/database-triggers.md` |
|
|
70
|
+
| Settings / config the host must wire | `docs/library/package-api.md` and/or **add-config** skill targets |
|
|
71
|
+
| Accepted policy or ADR | `docs/platform/architecture-decisions.md` when the feature locks a new decision |
|
|
72
|
+
|
|
73
|
+
**Do not** mark a feature done while any row above still applies and is missing an update.
|
|
74
|
+
|
|
75
|
+
Wait for the user to review and accept documentation before proceeding (or before declaring the feature complete when tests are skipped).
|
|
76
|
+
|
|
77
|
+
## 6. Tests (when requested)
|
|
78
|
+
|
|
79
|
+
After documentation is accepted:
|
|
80
|
+
|
|
81
|
+
- Add or update integration tests when the user asks for tests in this task.
|
|
82
|
+
- If the user did not ask for tests, the feature is **done** after step 5 is accepted.
|
|
83
|
+
|
|
84
|
+
## Flexibility
|
|
85
|
+
|
|
86
|
+
If the feature has no database change (e.g., pure logic, workers) or no API layer (e.g., background workers, internal jobs), skip the irrelevant steps and follow the remaining order. **Documentation (step 5) still applies** whenever behavior ships.
|
|
87
|
+
|
|
88
|
+
## Checklist (verify before every response)
|
|
89
|
+
|
|
90
|
+
- [ ] Did I implement only one step?
|
|
91
|
+
- [ ] Did I stop and wait for review?
|
|
92
|
+
- [ ] Did I skip ahead to other layers? (If yes, roll back and redo.)
|
|
93
|
+
- [ ] If this step finishes the feature: is **all** required documentation updated? (If no, the feature is **not** done.)
|
|
@@ -12,7 +12,7 @@ Consuming applications embed **core-framework** as a dependency.
|
|
|
12
12
|
When changing **core-framework** code, migrations, tests, or **`docs/`**:
|
|
13
13
|
|
|
14
14
|
- **Do not** edit host repos in the same task.
|
|
15
|
-
- **Do not** port **`docs/platform/`**, **`docs/deployments/`**, **`.cursor/rules/`**, or **`.cursor/skills/`** to hosts proactively.
|
|
15
|
+
- **Do not** port **`docs/platform/`**, **`docs/design/`**, **`docs/deployments/`**, **`.cursor/rules/`**, or **`.cursor/skills/`** to hosts proactively.
|
|
16
16
|
- Mention that host sync is **deferred until the host bumps its core-framework version** (unless the user asked otherwise).
|
|
17
17
|
|
|
18
18
|
## When host changes are allowed
|
|
@@ -35,7 +35,7 @@ Diff by **basename** against the host's **`.cursor/`** and applicable **`docs/`*
|
|
|
35
35
|
|
|
36
36
|
**Core `docs/` must stay host-agnostic** — no references to specific consuming applications.
|
|
37
37
|
|
|
38
|
-
| Core path
|
|
39
|
-
|
|
|
40
|
-
| **`docs/platform/`**, **`docs/deployments/`** | Sync on dependency upgrade or explicit sync request |
|
|
41
|
-
| **`docs/domains/`**, **`docs/library/`**
|
|
38
|
+
| Core path | Host behavior |
|
|
39
|
+
| ----------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
40
|
+
| **`docs/platform/`**, **`docs/design/`**, **`docs/deployments/`** | Sync on dependency upgrade or explicit sync request |
|
|
41
|
+
| **`docs/domains/`**, **`docs/library/`** | Canonical in core only — do not mirror product trees to hosts |
|
|
@@ -74,5 +74,6 @@ Concise, active voice, present tense, client perspective. Horizontal rules betwe
|
|
|
74
74
|
|
|
75
75
|
- [ ] Endpoint list at top; each endpoint has Goal, Preconditions, Flow, Errors
|
|
76
76
|
- [ ] No implementation identifiers or code snippets
|
|
77
|
-
- [ ] Links to **`docs/platform/architecture-decisions.md`** when referencing
|
|
77
|
+
- [ ] Links to **`docs/platform/architecture-decisions.md`** when referencing accepted policy or ADR decisions
|
|
78
|
+
- [ ] Links to **`docs/design/`** when referencing cross-cutting mechanisms (outbox, events ingest, idempotency, analytics rollup, etc.)
|
|
78
79
|
```
|
|
@@ -4,6 +4,52 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.3.3] - 2026-07-05
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **UTM capture `kind`:** `POST /events` with `type: "utm_data"` requires a `kind`
|
|
12
|
+
item in `events[]` (`subject_type` `kind`, `subject` the capture context). Core
|
|
13
|
+
ships `registration`; hosts register additional kinds via
|
|
14
|
+
`register_utm_capture_kind`. See **`docs/design/utm-events-design.md`** and
|
|
15
|
+
**`docs/domains/events/events.md`**.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **`analytics` schema:** **`2d61a5e88d76_analytics_utm_events_add_kind`** — `utm_events.kind`
|
|
20
|
+
column and `idx_utm_events_kind_created_at`. **Deletes all existing `utm_events` rows**
|
|
21
|
+
before adding the column (legacy UTM-only rows are not backfilled). Run **`cf-alembic`**
|
|
22
|
+
when upgrading.
|
|
23
|
+
|
|
24
|
+
### Breaking
|
|
25
|
+
|
|
26
|
+
- **Breaking (clients — `utm_data`):** Batches without a valid `kind` item and at
|
|
27
|
+
least one allowlisted UTM key no longer persist. UTM-only payloads from 2.3.2
|
|
28
|
+
stop writing rows.
|
|
29
|
+
|
|
30
|
+
- **Breaking (operators — `utm_events` data):** Upgrading through
|
|
31
|
+
**`2d61a5e88d76_analytics_utm_events_add_kind`** clears **`analytics.utm_events`**
|
|
32
|
+
before the **`kind`** column is added.
|
|
33
|
+
|
|
34
|
+
## [2.3.2] - 2026-07-05
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **UTM attribution ingest:** `POST /events` with `type: "utm_data"` records `analytics.utm_events` (`utm` and `request_context` jsonb; optional `user_id`). UTM keys are sent as `events[]` items (`subject_type` = field name, `subject` = value). See **`docs/domains/events/events.md`** and **`docs/design/utm-events-design.md`**.
|
|
39
|
+
- **Signup telemetry:** `POST /events` with `type: "signup"` records `user_signup_events` (one row per user, `request_context` jsonb) after `POST /auth/register`. See **`docs/domains/events/events.md`**.
|
|
40
|
+
- **Request context parsing:** `application/shared/request_context.py` normalizes `User-Agent`, `client-referrer` (`referrer_url`, `referrer_host`), and `Cf-Ipcountry` for events ingest.
|
|
41
|
+
|
|
42
|
+
### Breaking
|
|
43
|
+
|
|
44
|
+
- **Breaking (clients — events ingest):** Traffic source for request context uses the **`client-referrer`** header instead of browser **`Referer`**. Clients should send an explicit referrer URL (for example captured from `document.referrer` on first load).
|
|
45
|
+
- **Breaking (clients — events ingest):** Rename event type **`view`** → **`impression`** on `POST /events`. Clients and hosts must send `type: "impression"` for subject-impression batches (post views, calculator opens, etc.). Core enum: **`EventType.IMPRESSION`** (replaces **`EventType.VIEW`**). Host handlers registered on `"view"` must re-register on **`"impression"`** (for example Henry calculator view ingest).
|
|
46
|
+
- **Breaking (hosts — imports):** Rename **`EVENT_TOKEN_MAX_AGE_VIEW_SECONDS`** → **`EVENT_TOKEN_MAX_AGE_SECONDS`** in **`core_framework.application.events.event_token`** (behavior unchanged; token max-age remains 600s for all event types).
|
|
47
|
+
|
|
48
|
+
### Migration
|
|
49
|
+
|
|
50
|
+
- **`analytics` schema:** **`585105e1149e_analytics_add_utm_events`** — `utm_events` table. Run **`cf-alembic`** when upgrading.
|
|
51
|
+
- **`user` schema:** **`44df70a45ba6_user_add_signup_events`** — `user_signup_events` table (`user_id` unique, `request_context` jsonb). Run **`cf-alembic`** when upgrading.
|
|
52
|
+
|
|
7
53
|
## [2.3.1] - 2026-07-03
|
|
8
54
|
|
|
9
55
|
### Added
|
|
@@ -23,7 +69,7 @@ Analytics rollup domain (materialized daily activity counts), admin read API, an
|
|
|
23
69
|
|
|
24
70
|
### Added
|
|
25
71
|
|
|
26
|
-
- **Analytics rollup (Phase 1):** `analytics` domain scaffold, `schema_analytics`, `[analytics].refresh_interval_seconds` (required on **`Settings`**; core **`config.toml`** ships **300**), Alembic tree with `daily_fact` table (PK only), and activity source registry shell. See **`docs/
|
|
72
|
+
- **Analytics rollup (Phase 1):** `analytics` domain scaffold, `schema_analytics`, `[analytics].refresh_interval_seconds` (required on **`Settings`**; core **`config.toml`** ships **300**), Alembic tree with `daily_fact` table (PK only), and activity source registry shell. See **`docs/design/analytics-rollup-design.md`**.
|
|
27
73
|
- **Analytics rollup (Phase 2):** `AnalyticsService.list_refreshable_days` and `is_final_bucket_refresh` (planner inputs), `refresh_daily_fact_bucket` (single-bucket executor), optional `refresh_all_open_buckets` for tests; transactional `replace_daily_fact_bucket`; admin read helpers.
|
|
28
74
|
- **Analytics rollup (Phase 3):** `post` / `created` activity source, planner (`enqueue_refresh_analytics_buckets`) and executor (`refresh_analytics_bucket`) application entrypoints, `schedule_refresh_analytics` + `process_refresh_analytics_bucket` worker (cron from `refresh_interval_seconds`).
|
|
29
75
|
- **Analytics rollup (Phase 4):** `comment` / `created`, `user` / `registered`, and `post` / `viewed` activity sources with domain UTC-day count accessors and registry registration.
|
|
@@ -43,7 +89,7 @@ Transactional outbox (block, follow, restriction), post views retention, and inc
|
|
|
43
89
|
### Added
|
|
44
90
|
|
|
45
91
|
- **Post views retention:** Incremental **`view_count`** aggregation via **`post_stats.view_count_aggregated_up_to`** (high-water mark on **`post_views.created_at`**); daily worker **`schedule_prune_post_views`** (05:00 UTC) deletes aggregated rows older than **`retention.post_views_retention_days`** (default **90**). See **`docs/domains/posts/post_stats_aggregation.md`**.
|
|
46
|
-
- **Transactional outbox (block pilot):** `user.event_outbox`, worker poller/handler for **`user.block.relationship_changed`**, durable post/comment/notification block mirror fanout. See **`docs/
|
|
92
|
+
- **Transactional outbox (block pilot):** `user.event_outbox`, worker poller/handler for **`user.block.relationship_changed`**, durable post/comment/notification block mirror fanout. See **`docs/design/event-outbox-design.md`**.
|
|
47
93
|
- **Transactional outbox (follow, Phase 2):** **`user.follow.relationship_changed`** enqueued with truth changes; worker reconciles **`post.user_followers_lookup`** (outbox-only mirror path, matching block). Non-retryable handler errors dead-letter immediately (decision **#22**).
|
|
48
94
|
- **Transactional outbox (restriction, Phase 3):** **`moderation.restriction.relationship_changed`** enqueued on truth changes and no-op healing; worker reconciles post/comment/user/notification restriction lookup mirrors (outbox-only, matching block/follow). Poller E2E in **`tests/integration/worker/moderation_outbox_test.py`**. Run **`cf-alembic`** for **`moderation_add_event_outbox`**.
|
|
49
95
|
|
|
@@ -88,7 +134,7 @@ First production-ready **2.x** release. Hosts must run **`cf-alembic`**, configu
|
|
|
88
134
|
|
|
89
135
|
- **Post and comment image attachments (v1):** **`POST /attachments`** compose-time ingest; worker encodes and publishes **`thumb`** / **`display`** WebP finals; **`attachment_ids`** on post/comment create and **`PATCH`** diff edit — attach is **best-effort per added asset** on create **and** edit (failing assets are skipped and burned; the post/comment write still succeeds and mention notifications proceed; malformed sets — duplicates or over-cap — fail request validation with **`422`**, with the same guards re-checked in the post/comment domain services); public and admin read **`attachments`** wrapper on post/comment responses; staging housekeeping sweeps; admin hard delete and account removal enqueue attachment finals cleanup. Tables **`post_image_attachments`**, **`comment_image_attachments`**, **`attachment_staging_registry`**. Config **`[attachment]`** and deploy vars **`ATTACHMENT_*`**. See **`docs/domains/media/post-comment-attachments-design.md`**.
|
|
90
136
|
|
|
91
|
-
- **HTTP create idempotency (v1):** Optional **`Idempotency-Key`** on **`POST /posts`**, **`POST /comments`**, and **`POST /comments/{comment_id}/replies`**. At most one committed row per **`(author_id, key, operation)`**; replays return **`201`** with empty body and skip mention notifications, attachment attach, and stats-dirty side effects. See **`docs/
|
|
137
|
+
- **HTTP create idempotency (v1):** Optional **`Idempotency-Key`** on **`POST /posts`**, **`POST /comments`**, and **`POST /comments/{comment_id}/replies`**. At most one committed row per **`(author_id, key, operation)`**; replays return **`201`** with empty body and skip mention notifications, attachment attach, and stats-dirty side effects. See **`docs/design/create-idempotency-design.md`**.
|
|
92
138
|
|
|
93
139
|
- **Request profiling (opt-in):** **`PROFILING_ENABLED`** and **`PROFILING_KEY`** — pyinstrument middleware gated by **`Profiling-Key`** header.
|
|
94
140
|
|
|
@@ -149,7 +195,7 @@ Run **`uv run cf-alembic`** (or host **`cf-alembic`**) before deploying **2.0.0*
|
|
|
149
195
|
|
|
150
196
|
### Documentation
|
|
151
197
|
|
|
152
|
-
- **`docs/platform/client-error-visibility.md`**, **`docs/
|
|
198
|
+
- **`docs/platform/client-error-visibility.md`**, **`docs/design/create-idempotency-design.md`**, **`docs/deployments/edge-upload-limits.md`**, **`docs/deployments/deploy-playbook.md`**, deletion refactor docs under **`docs/domains/deletion/`**.
|
|
153
199
|
|
|
154
200
|
## [1.8.1] - 2026-06-07
|
|
155
201
|
|
|
@@ -413,4 +459,8 @@ First **SemVer-stable** release per **`docs/library/package-api.md`**.
|
|
|
413
459
|
[2.0.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.8.1...v2.0.0
|
|
414
460
|
[2.1.0]: https://github.com/NepNepFFXIV/core-framework/compare/v2.0.0...v2.1.0
|
|
415
461
|
[2.2.0]: https://github.com/NepNepFFXIV/core-framework/compare/v2.1.0...v2.2.0
|
|
416
|
-
[
|
|
462
|
+
[2.3.0]: https://github.com/NepNepFFXIV/core-framework/compare/v2.2.0...v2.3.0
|
|
463
|
+
[2.3.1]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.0...v2.3.1
|
|
464
|
+
[2.3.2]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.1...v2.3.2
|
|
465
|
+
[2.3.3]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.2...v2.3.3
|
|
466
|
+
[unreleased]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.3...HEAD
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-framework
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.3
|
|
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
|
|
@@ -10,7 +10,6 @@ Requires-Python: >=3.14
|
|
|
10
10
|
Requires-Dist: aiofiles>=25.1.0
|
|
11
11
|
Requires-Dist: alembic>=1.18.4
|
|
12
12
|
Requires-Dist: arq>=0.28.0
|
|
13
|
-
Requires-Dist: async-lru>=2.1.0
|
|
14
13
|
Requires-Dist: asyncer>=0.0.14
|
|
15
14
|
Requires-Dist: asyncpg>=0.31.0
|
|
16
15
|
Requires-Dist: asyncssh>=2.23.0
|
|
@@ -62,6 +61,8 @@ make run
|
|
|
62
61
|
|
|
63
62
|
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f docker-compose.dev.yaml down`**.
|
|
64
63
|
|
|
64
|
+
**Pre-commit:** `uv sync --dev` installs **pre-commit**. Enable hooks with **`uv run pre-commit install`** (ruff, mdformat, uv-lock, and other checks in **`.pre-commit-config.yaml`**).
|
|
65
|
+
|
|
65
66
|
## Hosts
|
|
66
67
|
|
|
67
68
|
In your host app, load **`Settings`** or a **`Settings`** subclass from **`core_framework.core.settings`**, pass it to **`init_app`** from **`core_framework.main`**, then wire host-specific dependencies, exception handlers, and routers.
|
|
@@ -23,6 +23,8 @@ make run
|
|
|
23
23
|
|
|
24
24
|
For **`make test`**, use the Firebase CLI (Auth emulator). Stop DB/Redis: **`docker compose -f docker-compose.dev.yaml down`**.
|
|
25
25
|
|
|
26
|
+
**Pre-commit:** `uv sync --dev` installs **pre-commit**. Enable hooks with **`uv run pre-commit install`** (ruff, mdformat, uv-lock, and other checks in **`.pre-commit-config.yaml`**).
|
|
27
|
+
|
|
26
28
|
## Hosts
|
|
27
29
|
|
|
28
30
|
In your host app, load **`Settings`** or a **`Settings`** subclass from **`core_framework.core.settings`**, pass it to **`init_app`** from **`core_framework.main`**, then wire host-specific dependencies, exception handlers, and routers.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""analytics utm_events add capture kind column
|
|
2
|
+
|
|
3
|
+
Revision ID: 2d61a5e88d76
|
|
4
|
+
Revises: 585105e1149e
|
|
5
|
+
Create Date: 2026-07-05 13:30:00.000000
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
|
|
11
|
+
from alembic import op
|
|
12
|
+
|
|
13
|
+
revision: str = "2d61a5e88d76"
|
|
14
|
+
down_revision: str | Sequence[str] | None = "585105e1149e"
|
|
15
|
+
branch_labels: str | Sequence[str] | None = None
|
|
16
|
+
depends_on: str | Sequence[str] | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
op.execute("delete from utm_events;")
|
|
21
|
+
op.execute("""
|
|
22
|
+
alter table utm_events
|
|
23
|
+
add column kind varchar(64) not null;
|
|
24
|
+
""")
|
|
25
|
+
op.execute("""
|
|
26
|
+
create index if not exists idx_utm_events_kind_created_at
|
|
27
|
+
on utm_events (kind, created_at);
|
|
28
|
+
""")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def downgrade() -> None:
|
|
32
|
+
op.execute("drop index if exists idx_utm_events_kind_created_at;")
|
|
33
|
+
op.execute("""
|
|
34
|
+
alter table utm_events
|
|
35
|
+
drop column if exists kind;
|
|
36
|
+
""")
|
core_framework-2.3.3/alembic/analytics/alembic/versions/585105e1149e_analytics_add_utm_events.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""analytics utm_events for client UTM attribution ingest
|
|
2
|
+
|
|
3
|
+
Revision ID: 585105e1149e
|
|
4
|
+
Revises: 7f2a9c1d4e8b
|
|
5
|
+
Create Date: 2026-07-05 12:00:00.000000
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
|
|
11
|
+
from alembic import op
|
|
12
|
+
|
|
13
|
+
revision: str = "585105e1149e"
|
|
14
|
+
down_revision: str | Sequence[str] | None = "7f2a9c1d4e8b"
|
|
15
|
+
branch_labels: str | Sequence[str] | None = None
|
|
16
|
+
depends_on: str | Sequence[str] | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
op.execute("""
|
|
21
|
+
create table utm_events (
|
|
22
|
+
id bigint generated always as identity primary key,
|
|
23
|
+
created_at timestamptz not null default now(),
|
|
24
|
+
token varchar(256) not null,
|
|
25
|
+
user_id varchar(128),
|
|
26
|
+
utm jsonb not null default '{}'::jsonb,
|
|
27
|
+
request_context jsonb not null default '{}'::jsonb
|
|
28
|
+
);
|
|
29
|
+
""")
|
|
30
|
+
op.execute("""
|
|
31
|
+
create index if not exists idx_utm_events_created_at
|
|
32
|
+
on utm_events (created_at);
|
|
33
|
+
""")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def downgrade() -> None:
|
|
37
|
+
op.execute("drop index if exists idx_utm_events_created_at;")
|
|
38
|
+
op.execute("drop table if exists utm_events;")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""add user_signup_events for registration telemetry
|
|
2
|
+
|
|
3
|
+
Revision ID: 44df70a45ba6
|
|
4
|
+
Revises: 9d9611e47ce2
|
|
5
|
+
Create Date: 2026-07-04 12:00:00.000000
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
|
|
11
|
+
from alembic import op
|
|
12
|
+
|
|
13
|
+
revision: str = "44df70a45ba6"
|
|
14
|
+
down_revision: str | Sequence[str] | None = "9d9611e47ce2"
|
|
15
|
+
branch_labels: str | Sequence[str] | None = None
|
|
16
|
+
depends_on: str | Sequence[str] | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
op.execute("""
|
|
21
|
+
create table user_signup_events (
|
|
22
|
+
id bigint generated always as identity primary key,
|
|
23
|
+
user_id varchar(128) not null references users(user_id) on delete cascade,
|
|
24
|
+
created_at timestamptz not null default now(),
|
|
25
|
+
request_context jsonb not null default '{}'::jsonb,
|
|
26
|
+
constraint user_signup_events_user_id_unique unique (user_id)
|
|
27
|
+
);
|
|
28
|
+
""")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def downgrade() -> None:
|
|
32
|
+
op.execute("drop table if exists user_signup_events")
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic import BaseModel, EmailStr, Field
|
|
1
|
+
from pydantic import BaseModel, EmailStr
|
|
4
2
|
|
|
5
3
|
from core_framework.api.users.shared.schemas import UserID, Username
|
|
6
4
|
|
|
7
|
-
CountryCode = Annotated[
|
|
8
|
-
str,
|
|
9
|
-
Field(
|
|
10
|
-
description="ISO 3166-1 alpha-2 country code",
|
|
11
|
-
pattern="^[A-Z]{2}$",
|
|
12
|
-
examples=["US", "GB"],
|
|
13
|
-
),
|
|
14
|
-
]
|
|
15
|
-
|
|
16
5
|
|
|
17
6
|
class CreatedUserResponse(BaseModel):
|
|
18
7
|
user_id: UserID
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
from typing import Annotated
|
|
2
2
|
|
|
3
|
-
from async_lru import alru_cache
|
|
4
3
|
from fastapi import Depends, Header, Query, Security
|
|
5
4
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
6
5
|
from pydantic import ValidationError
|
|
7
6
|
|
|
8
7
|
import core_framework.domains.auth.dependencies as auth_deps
|
|
9
|
-
from core_framework.api.auth.schemas import
|
|
8
|
+
from core_framework.api.auth.schemas import FirebaseUser
|
|
10
9
|
from core_framework.api.users.shared.schemas import UserID, parse_user_id
|
|
11
10
|
from core_framework.application.auth.access_service import get_user_detail
|
|
12
11
|
from core_framework.application.auth.models import UserDetail
|
|
13
12
|
from core_framework.application.shared.exceptions import BadRequestException, ForbiddenException, UnauthorizedException
|
|
14
|
-
from core_framework.application.shared.
|
|
13
|
+
from core_framework.application.shared.request_context import (
|
|
14
|
+
parse_cf_ipcountry,
|
|
15
|
+
parse_client_referrer,
|
|
16
|
+
parse_user_agent,
|
|
17
|
+
)
|
|
15
18
|
from core_framework.application.users.admin_service import retrieve_admin_user_ids
|
|
16
19
|
from core_framework.core.context import user_id
|
|
17
20
|
from core_framework.domains.auth import VerifiedTokenClaims
|
|
@@ -21,11 +24,6 @@ from core_framework.domains.user import UserIdentity
|
|
|
21
24
|
bearer_scheme = HTTPBearer(auto_error=False)
|
|
22
25
|
|
|
23
26
|
|
|
24
|
-
@alru_cache(maxsize=5000, ttl=300) # ~10MB per worker, 5 minutes TTL
|
|
25
|
-
async def _verify_id_token(token: str) -> VerifiedTokenClaims | None:
|
|
26
|
-
return await auth_deps.auth_service.verify_id_token(token=token)
|
|
27
|
-
|
|
28
|
-
|
|
29
27
|
def _build_firebase_user_from_claims(claims: VerifiedTokenClaims) -> FirebaseUser | None:
|
|
30
28
|
try:
|
|
31
29
|
return FirebaseUser(
|
|
@@ -54,7 +52,7 @@ async def _get_firebase_user(token: Annotated[str | None, Depends(_get_bearer_to
|
|
|
54
52
|
if not token:
|
|
55
53
|
return None
|
|
56
54
|
|
|
57
|
-
claims = await
|
|
55
|
+
claims = await auth_deps.auth_service.verify_id_token(token=token)
|
|
58
56
|
if claims is None:
|
|
59
57
|
return None
|
|
60
58
|
|
|
@@ -106,18 +104,18 @@ async def check_not_banned(user_detail: Annotated[UserDetail, Depends(_get_user_
|
|
|
106
104
|
async def _get_request_context(
|
|
107
105
|
firebase_user: Annotated[FirebaseUser | None, Depends(_get_firebase_user)],
|
|
108
106
|
user_agent: Annotated[str | None, Header()] = None,
|
|
109
|
-
cf_ipcountry: Annotated[
|
|
107
|
+
cf_ipcountry: Annotated[str | None, Header()] = None,
|
|
108
|
+
client_referrer: Annotated[str | None, Header()] = None,
|
|
110
109
|
) -> dict[str, str]:
|
|
111
110
|
metadata: dict[str, str] = {}
|
|
112
111
|
|
|
113
112
|
if firebase_user:
|
|
114
113
|
metadata["viewer_id"] = firebase_user.user_id
|
|
115
114
|
metadata["provider"] = firebase_user.sign_in_provider
|
|
116
|
-
if cf_ipcountry:
|
|
117
|
-
metadata["country_code"] = cf_ipcountry
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
metadata.update(
|
|
116
|
+
metadata.update(parse_cf_ipcountry(cf_ipcountry=cf_ipcountry))
|
|
117
|
+
metadata.update(parse_client_referrer(client_referrer=client_referrer))
|
|
118
|
+
metadata.update(parse_user_agent(user_agent=user_agent))
|
|
121
119
|
|
|
122
120
|
return {k: v for k, v in metadata.items() if v is not None}
|
|
123
121
|
|
{core_framework-2.3.1 → core_framework-2.3.3}/core_framework/application/auth/access_service.py
RENAMED
|
@@ -9,8 +9,9 @@ from core_framework.core import CacheKey
|
|
|
9
9
|
from core_framework.domains.user import UserIdentity
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
@cache.
|
|
12
|
+
@cache.early(
|
|
13
13
|
ttl=lambda *_args, **_kwargs: CacheKey.USER_DETAIL.ttl_seconds,
|
|
14
|
+
early_ttl=lambda *_args, **_kwargs: CacheKey.USER_DETAIL.early_ttl_seconds,
|
|
14
15
|
key=CacheKey.USER_DETAIL.key_template,
|
|
15
16
|
condition=lambda result, args, kwargs, key=None: result.identity != UserIdentity.DEFAULT,
|
|
16
17
|
)
|
|
@@ -2,6 +2,7 @@ import core_framework.domains.moderation.dependencies as moderation_deps
|
|
|
2
2
|
import core_framework.domains.user.dependencies as user_deps
|
|
3
3
|
from core_framework.application.analytics.registry import configure_activity_sources
|
|
4
4
|
from core_framework.application.events.event_service import configure_event_handlers
|
|
5
|
+
from core_framework.application.events.utm_capture_kinds import configure_utm_capture_kinds
|
|
5
6
|
from core_framework.application.shared.worker_jobs import configure_worker_jobs
|
|
6
7
|
from core_framework.core.cache import configure_cashews_backend
|
|
7
8
|
from core_framework.core.runtime import CoreRuntime
|
|
@@ -19,6 +20,7 @@ from core_framework.domains.user.dependencies import configure_user_dependencies
|
|
|
19
20
|
def configure_application_dependencies(*, runtime: CoreRuntime) -> None:
|
|
20
21
|
"""Wire application-level dependencies from the shared runtime."""
|
|
21
22
|
configure_event_handlers()
|
|
23
|
+
configure_utm_capture_kinds()
|
|
22
24
|
configure_activity_sources()
|
|
23
25
|
configure_worker_jobs(runtime=runtime)
|
|
24
26
|
configure_cashews_backend(redis_cache_url=runtime.settings.redis.redis_cache_url)
|
|
@@ -39,8 +41,3 @@ def configure_application_dependencies(*, runtime: CoreRuntime) -> None:
|
|
|
39
41
|
runtime.settings.postgres_schemas.schema_moderation: moderation_deps.moderation_outbox_service,
|
|
40
42
|
}
|
|
41
43
|
)
|
|
42
|
-
|
|
43
|
-
# alru_cache on user id set must not survive a rebound UserService instance
|
|
44
|
-
import core_framework.application.users.admin_service as admin_service
|
|
45
|
-
|
|
46
|
-
admin_service.retrieve_admin_user_ids.cache_clear()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Events Application Layer
|
|
2
|
+
|
|
3
|
+
Client-initiated, eventually consistent side effects: token verification, handler
|
|
4
|
+
registry, and built-in handlers.
|
|
5
|
+
|
|
6
|
+
## Role
|
|
7
|
+
|
|
8
|
+
`POST /events` dispatches batched client work to registered handlers. Handlers are
|
|
9
|
+
**loss-tolerant** (errors logged, not raised to the client).
|
|
10
|
+
|
|
11
|
+
**Canonical core event catalog** (shipped and planned `type` values, auth, dedup,
|
|
12
|
+
side effects): `docs/domains/events/events.md` → **Core event catalog**.
|
|
13
|
+
|
|
14
|
+
Platform design and host extension: `docs/design/events-ingest-design.md`.
|
|
15
|
+
|
|
16
|
+
## Host extension
|
|
17
|
+
|
|
18
|
+
- `register_event_handler(event_type, handler)` — append a handler after `configure_application_dependencies`
|
|
19
|
+
- `register_utm_capture_kind(kind)` — append a `utm_data` capture kind after `configure_application_dependencies`
|
|
20
|
+
- `configure_event_handlers()` — reset handler registry and register core built-ins
|
|
21
|
+
- `configure_utm_capture_kinds()` — reset capture-kind registry and seed core kinds (`registration`)
|
|
22
|
+
- `type` and `subject_type` are plain strings at the schema boundary
|
|
23
|
+
- Each handler receives the full batch and filters its own `subject_type` values
|
|
24
|
+
|
|
25
|
+
## Flow
|
|
26
|
+
|
|
27
|
+
1. Client obtains a token via `GET /events/token`
|
|
28
|
+
1. Client posts via `POST /events` with `type`, `token`, and `events`
|
|
29
|
+
1. Invalid token → early return (HTTP still 202)
|
|
30
|
+
1. Registered handlers for `type` are queued on FastAPI `BackgroundTasks` and run **sequentially** after the response
|
|
31
|
+
1. Unknown `type` → warning log, no handler run
|