core-framework 2.3.2__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.
Files changed (695) hide show
  1. {core_framework-2.3.2 → core_framework-2.3.3}/CHANGELOG.md +29 -1
  2. {core_framework-2.3.2 → core_framework-2.3.3}/PKG-INFO +1 -1
  3. core_framework-2.3.3/alembic/analytics/alembic/versions/2d61a5e88d76_analytics_utm_events_add_kind.py +36 -0
  4. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/bootstrap.py +2 -0
  5. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/events/README.md +3 -1
  6. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/events/event_service.py +16 -1
  7. core_framework-2.3.3/core_framework/application/events/utm_capture_kinds.py +30 -0
  8. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/README.md +3 -2
  9. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/__init__.py +4 -0
  10. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/constants.py +4 -0
  11. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/repository.py +5 -3
  12. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/service.py +17 -3
  13. core_framework-2.3.3/docs/deployments/guides/app-server-deploy-ssh.md +78 -0
  14. core_framework-2.3.3/docs/deployments/guides/image-server-ssh.md +93 -0
  15. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/guides/ubuntu-server-setup.md +1 -0
  16. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/README.md +10 -10
  17. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/events-ingest-design.md +34 -10
  18. core_framework-2.3.3/docs/design/utm-events-design.md +272 -0
  19. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/events/events.md +31 -20
  20. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/core-framework-migration.md +1 -1
  21. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/package-api.md +29 -0
  22. {core_framework-2.3.2 → core_framework-2.3.3}/pyproject.toml +1 -1
  23. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/events/router_test.py +224 -8
  24. {core_framework-2.3.2 → core_framework-2.3.3}/uv.lock +1 -1
  25. core_framework-2.3.2/docs/deployments/guides/app-server-deploy-ssh.md +0 -55
  26. core_framework-2.3.2/docs/deployments/guides/image-server-ssh.md +0 -62
  27. core_framework-2.3.2/docs/design/utm-events-design.md +0 -233
  28. {core_framework-2.3.2 → core_framework-2.3.3}/.agents/skills/fastapi +0 -0
  29. {core_framework-2.3.2 → core_framework-2.3.3}/.agents/skills/library-skills/.library-skills.json +0 -0
  30. {core_framework-2.3.2 → core_framework-2.3.3}/.agents/skills/library-skills/SKILL.md +0 -0
  31. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/alembic-migrations.mdc +0 -0
  32. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/api-layer.mdc +0 -0
  33. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/api-reference-docs.mdc +0 -0
  34. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/api-validation.mdc +0 -0
  35. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/application-layer.mdc +0 -0
  36. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/constants-final.mdc +0 -0
  37. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/constitution.mdc +0 -0
  38. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/database-triggers.mdc +0 -0
  39. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/docstrings.mdc +0 -0
  40. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/domain-caller-context.mdc +0 -0
  41. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/domain-imports.mdc +0 -0
  42. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/domain-input-guards.mdc +0 -0
  43. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
  44. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/domain-services-and-adapters.mdc +0 -0
  45. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/error-boundary.mdc +0 -0
  46. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/flow-documentation.mdc +0 -0
  47. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/inline-raise-messages.mdc +0 -0
  48. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/integration-test-strategy.mdc +0 -0
  49. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/layer-boundaries.mdc +0 -0
  50. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/no-code-in-docs.mdc +0 -0
  51. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/postgres-config-conventions.mdc +0 -0
  52. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/repository-schema-isolation.mdc +0 -0
  53. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/strong-reads.mdc +0 -0
  54. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/rules/structured-logging.mdc +0 -0
  55. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/add-config/SKILL.md +0 -0
  56. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/add-domain/SKILL.md +0 -0
  57. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/code-review/SKILL.md +0 -0
  58. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/fastapi +0 -0
  59. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/implement-feature/SKILL.md +0 -0
  60. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/recommend-features/SKILL.md +0 -0
  61. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/sync-host-rules/SKILL.md +0 -0
  62. {core_framework-2.3.2 → core_framework-2.3.3}/.cursor/skills/write-flow-doc/SKILL.md +0 -0
  63. {core_framework-2.3.2 → core_framework-2.3.3}/.dockerignore +0 -0
  64. {core_framework-2.3.2 → core_framework-2.3.3}/.github/workflows/_deploy.yml +0 -0
  65. {core_framework-2.3.2 → core_framework-2.3.3}/.github/workflows/dev-ci-cd.yaml +0 -0
  66. {core_framework-2.3.2 → core_framework-2.3.3}/.github/workflows/manual-deployment.yaml +0 -0
  67. {core_framework-2.3.2 → core_framework-2.3.3}/.github/workflows/publish-pypi.yml +0 -0
  68. {core_framework-2.3.2 → core_framework-2.3.3}/.github/workflows/test.yaml +0 -0
  69. {core_framework-2.3.2 → core_framework-2.3.3}/.gitignore +0 -0
  70. {core_framework-2.3.2 → core_framework-2.3.3}/.pre-commit-config.yaml +0 -0
  71. {core_framework-2.3.2 → core_framework-2.3.3}/.python-version +0 -0
  72. {core_framework-2.3.2 → core_framework-2.3.3}/LICENSE +0 -0
  73. {core_framework-2.3.2 → core_framework-2.3.3}/README.md +0 -0
  74. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/README +0 -0
  75. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/env.py +0 -0
  76. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/script.py.mako +0 -0
  77. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/versions/585105e1149e_analytics_add_utm_events.py +0 -0
  78. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/versions/5b9ac98bb150_analytics_daily_fact.py +0 -0
  79. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic/versions/7f2a9c1d4e8b_analytics_daily_fact_day_index.py +0 -0
  80. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/analytics/alembic.ini +0 -0
  81. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/README +0 -0
  82. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/env.py +0 -0
  83. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/script.py.mako +0 -0
  84. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_attachments.py +0 -0
  85. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency.py +0 -0
  86. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency_created_at_index.py +0 -0
  87. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_add_comment_mentions.py +0 -0
  88. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/comment_tombstone_status_model.py +0 -0
  89. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
  90. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/comment/alembic.ini +0 -0
  91. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/extension/alembic/README +0 -0
  92. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/extension/alembic/env.py +0 -0
  93. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/extension/alembic/script.py.mako +0 -0
  94. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
  95. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/extension/alembic.ini +0 -0
  96. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/README +0 -0
  97. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/env.py +0 -0
  98. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/script.py.mako +0 -0
  99. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/versions/media_add_attachment_staging_registry.py +0 -0
  100. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +0 -0
  101. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/versions/media_attachment_staging_registry_published_at.py +0 -0
  102. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
  103. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/media/alembic.ini +0 -0
  104. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/README +0 -0
  105. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/env.py +0 -0
  106. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/script.py.mako +0 -0
  107. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox.py +0 -0
  108. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox_dead_indexes.py +0 -0
  109. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/versions/moderation_add_event_outbox_pending_created_at_index.py +0 -0
  110. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
  111. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/moderation/alembic.ini +0 -0
  112. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/notification/alembic/README +0 -0
  113. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/notification/alembic/env.py +0 -0
  114. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/notification/alembic/script.py.mako +0 -0
  115. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
  116. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/notification/alembic.ini +0 -0
  117. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/README +0 -0
  118. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/env.py +0 -0
  119. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/script.py.mako +0 -0
  120. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_attachments.py +0 -0
  121. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_create_idempotency.py +0 -0
  122. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_create_idempotency_created_at_index.py +0 -0
  123. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_add_post_mentions.py +0 -0
  124. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_post_views_retention_high_water_mark.py +0 -0
  125. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/post_tombstone_status_model.py +0 -0
  126. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
  127. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/post/alembic.ini +0 -0
  128. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/README +0 -0
  129. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/env.py +0 -0
  130. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/script.py.mako +0 -0
  131. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/44df70a45ba6_user_add_signup_events.py +0 -0
  132. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
  133. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +0 -0
  134. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
  135. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox.py +0 -0
  136. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox_dead_indexes.py +0 -0
  137. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_add_event_outbox_pending_created_at_index.py +0 -0
  138. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/user_reserve_sentinel_user_ids.py +0 -0
  139. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
  140. {core_framework-2.3.2 → core_framework-2.3.3}/alembic/user/alembic.ini +0 -0
  141. {core_framework-2.3.2 → core_framework-2.3.3}/config.toml +0 -0
  142. {core_framework-2.3.2 → core_framework-2.3.3}/config.toml.template +0 -0
  143. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/__init__.py +0 -0
  144. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/__init__.py +0 -0
  145. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/__init__.py +0 -0
  146. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/analytics/router.py +0 -0
  147. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/analytics/schemas.py +0 -0
  148. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/cache/router.py +0 -0
  149. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/cache/schemas.py +0 -0
  150. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/comments/router.py +0 -0
  151. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/comments/schemas.py +0 -0
  152. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/moderation/__init__.py +0 -0
  153. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/moderation/router.py +0 -0
  154. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/moderation/schemas.py +0 -0
  155. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/outbox/router.py +0 -0
  156. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/outbox/schemas.py +0 -0
  157. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/posts/router.py +0 -0
  158. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/posts/schemas.py +0 -0
  159. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/router.py +0 -0
  160. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/users/__init__.py +0 -0
  161. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/users/router.py +0 -0
  162. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/admin/users/schemas.py +0 -0
  163. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/attachments/router.py +0 -0
  164. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/attachments/schemas.py +0 -0
  165. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/auth/__init__.py +0 -0
  166. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/auth/router.py +0 -0
  167. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/auth/schemas.py +0 -0
  168. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/authenticated/mappers.py +0 -0
  169. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/authenticated/router.py +0 -0
  170. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/authenticated/schemas.py +0 -0
  171. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/public/router.py +0 -0
  172. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/public/schemas.py +0 -0
  173. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/router.py +0 -0
  174. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/comments/schemas.py +0 -0
  175. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/constants.py +0 -0
  176. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/dependencies.py +0 -0
  177. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/events/router.py +0 -0
  178. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/events/schemas.py +0 -0
  179. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/idempotency/__init__.py +0 -0
  180. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/idempotency/dependencies.py +0 -0
  181. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/notifications/authenticated/router.py +0 -0
  182. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/notifications/authenticated/schemas.py +0 -0
  183. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/notifications/router.py +0 -0
  184. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/authenticated/mappers.py +0 -0
  185. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/authenticated/router.py +0 -0
  186. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/authenticated/schemas.py +0 -0
  187. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/public/router.py +0 -0
  188. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/public/schemas.py +0 -0
  189. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/router.py +0 -0
  190. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/posts/schemas.py +0 -0
  191. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/router.py +0 -0
  192. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/schemas.py +0 -0
  193. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/system/__init__.py +0 -0
  194. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/system/router.py +0 -0
  195. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/__init__.py +0 -0
  196. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/authenticated/__init__.py +0 -0
  197. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/authenticated/mappers.py +0 -0
  198. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/authenticated/router.py +0 -0
  199. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/authenticated/schemas.py +0 -0
  200. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/mappers.py +0 -0
  201. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/public/__init__.py +0 -0
  202. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/public/router.py +0 -0
  203. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/public/schemas.py +0 -0
  204. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/router.py +0 -0
  205. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/api/users/shared/schemas.py +0 -0
  206. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/__init__.py +0 -0
  207. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/bucket_service.py +0 -0
  208. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/prune_service.py +0 -0
  209. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/read_service.py +0 -0
  210. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/refresh_service.py +0 -0
  211. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/registry.py +0 -0
  212. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/sources/comment_created.py +0 -0
  213. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/sources/post_created.py +0 -0
  214. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/sources/post_viewed.py +0 -0
  215. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/analytics/sources/user_registered.py +0 -0
  216. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/auth/__init__.py +0 -0
  217. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/auth/access_service.py +0 -0
  218. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/auth/auth_service.py +0 -0
  219. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/auth/models.py +0 -0
  220. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/cache/invalidate_service.py +0 -0
  221. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/cache/models.py +0 -0
  222. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/comments/admin_service.py +0 -0
  223. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/comments/aggregation_service.py +0 -0
  224. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/comments/authenticated_service.py +0 -0
  225. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/comments/cleanup_service.py +0 -0
  226. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/comments/public_service.py +0 -0
  227. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/events/event_token.py +0 -0
  228. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/events/models.py +0 -0
  229. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/README.md +0 -0
  230. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/attachment_read.py +0 -0
  231. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/attachment_service.py +0 -0
  232. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/avatar_service.py +0 -0
  233. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/banner_service.py +0 -0
  234. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/ingest_guards.py +0 -0
  235. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/media/read_url_config.py +0 -0
  236. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/__init__.py +0 -0
  237. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/appeal_service.py +0 -0
  238. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/moderator_service.py +0 -0
  239. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/report_service.py +0 -0
  240. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/scheduled_service.py +0 -0
  241. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/moderation/user_service.py +0 -0
  242. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/notifications/README.md +0 -0
  243. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/notifications/enums.py +0 -0
  244. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/notifications/inbox_service.py +0 -0
  245. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/notifications/mute_service.py +0 -0
  246. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/notifications/notification_service.py +0 -0
  247. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/block_mirrors.py +0 -0
  248. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/events.py +0 -0
  249. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/exceptions.py +0 -0
  250. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/follow_mirrors.py +0 -0
  251. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/handlers.py +0 -0
  252. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/ops_service.py +0 -0
  253. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/polling_service.py +0 -0
  254. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/processing_service.py +0 -0
  255. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/outbox/restriction_mirrors.py +0 -0
  256. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/posts/admin_service.py +0 -0
  257. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/posts/aggregation_service.py +0 -0
  258. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/posts/authenticated_service.py +0 -0
  259. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/posts/cleanup_service.py +0 -0
  260. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/posts/public_service.py +0 -0
  261. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/shared/__init__.py +0 -0
  262. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/shared/enums.py +0 -0
  263. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/shared/exceptions.py +0 -0
  264. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/shared/request_context.py +0 -0
  265. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/shared/worker_jobs.py +0 -0
  266. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/__init__.py +0 -0
  267. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/admin_service.py +0 -0
  268. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/aggregation_service.py +0 -0
  269. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/authenticated_service.py +0 -0
  270. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/deletion_audit.py +0 -0
  271. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/enums.py +0 -0
  272. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/public_service.py +0 -0
  273. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/scheduled_service.py +0 -0
  274. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/application/users/user_deletion_service.py +0 -0
  275. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/asgi.py +0 -0
  276. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/bundled_alembic.py +0 -0
  277. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/constants.py +0 -0
  278. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/__init__.py +0 -0
  279. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/cache.py +0 -0
  280. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/context.py +0 -0
  281. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/database.py +0 -0
  282. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/exception_handlers/__init__.py +0 -0
  283. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/exception_handlers/application.py +0 -0
  284. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/exception_handlers/common.py +0 -0
  285. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/exception_handlers/setup.py +0 -0
  286. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/exceptions.py +0 -0
  287. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/firebase.py +0 -0
  288. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/http_client.py +0 -0
  289. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/logging.py +0 -0
  290. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/middleware.py +0 -0
  291. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/observability.py +0 -0
  292. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/pagination.py +0 -0
  293. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/redis.py +0 -0
  294. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/runtime.py +0 -0
  295. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/core/settings.py +0 -0
  296. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/__init__.py +0 -0
  297. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/dependencies.py +0 -0
  298. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/exceptions.py +0 -0
  299. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/models.py +0 -0
  300. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/analytics/ports/activity_source.py +0 -0
  301. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/README.md +0 -0
  302. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/__init__.py +0 -0
  303. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/dependencies.py +0 -0
  304. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/exceptions.py +0 -0
  305. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/models.py +0 -0
  306. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/ports/__init__.py +0 -0
  307. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/ports/auth.py +0 -0
  308. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/auth/service.py +0 -0
  309. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/README.md +0 -0
  310. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/__init__.py +0 -0
  311. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/constants.py +0 -0
  312. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/dependencies.py +0 -0
  313. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/enums.py +0 -0
  314. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/exceptions.py +0 -0
  315. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/models.py +0 -0
  316. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/outcomes.py +0 -0
  317. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/repository.py +0 -0
  318. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/comment/service.py +0 -0
  319. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/exceptions.py +0 -0
  320. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/README.md +0 -0
  321. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/__init__.py +0 -0
  322. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/finals_publisher.py +0 -0
  323. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/staging.py +0 -0
  324. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/components/variant_encoder.py +0 -0
  325. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/constants.py +0 -0
  326. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/exceptions.py +0 -0
  327. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/models.py +0 -0
  328. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/finals_publisher.py +0 -0
  329. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/staging.py +0 -0
  330. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/ports/variant_encoder.py +0 -0
  331. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/attachment/service.py +0 -0
  332. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/__init__.py +0 -0
  333. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/__init__.py +0 -0
  334. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/finals_publisher.py +0 -0
  335. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/staging.py +0 -0
  336. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/components/variant_encoder.py +0 -0
  337. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/constants.py +0 -0
  338. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/exceptions.py +0 -0
  339. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/models.py +0 -0
  340. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
  341. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/finals_publisher.py +0 -0
  342. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/staging.py +0 -0
  343. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/ports/variant_encoder.py +0 -0
  344. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/avatar/service.py +0 -0
  345. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/components/finals_publisher.py +0 -0
  346. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/components/staging.py +0 -0
  347. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/components/variant_encoder.py +0 -0
  348. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/constants.py +0 -0
  349. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/exceptions.py +0 -0
  350. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/models.py +0 -0
  351. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/finals_publisher.py +0 -0
  352. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/staging.py +0 -0
  353. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/ports/variant_encoder.py +0 -0
  354. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/banner/service.py +0 -0
  355. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/dependencies.py +0 -0
  356. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/__init__.py +0 -0
  357. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/constants.py +0 -0
  358. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/exceptions.py +0 -0
  359. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/outcomes.py +0 -0
  360. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/repository.py +0 -0
  361. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/service.py +0 -0
  362. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/media/shared/utils.py +0 -0
  363. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/README.md +0 -0
  364. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/__init__.py +0 -0
  365. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/dependencies.py +0 -0
  366. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/enums.py +0 -0
  367. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/exceptions.py +0 -0
  368. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/models.py +0 -0
  369. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/outbox_repository.py +0 -0
  370. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/outbox_service.py +0 -0
  371. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/outcomes.py +0 -0
  372. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/repository.py +0 -0
  373. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/moderation/service.py +0 -0
  374. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/README.md +0 -0
  375. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/__init__.py +0 -0
  376. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/dependencies.py +0 -0
  377. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/enums.py +0 -0
  378. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/exceptions.py +0 -0
  379. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/models.py +0 -0
  380. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/repository.py +0 -0
  381. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/notification/service.py +0 -0
  382. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/README.md +0 -0
  383. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/__init__.py +0 -0
  384. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/dependencies.py +0 -0
  385. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/models.py +0 -0
  386. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/ports/admin.py +0 -0
  387. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/ports/consumer.py +0 -0
  388. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/ports/producer.py +0 -0
  389. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/outbox/service.py +0 -0
  390. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/README.md +0 -0
  391. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/__init__.py +0 -0
  392. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/constants.py +0 -0
  393. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/dependencies.py +0 -0
  394. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/enums.py +0 -0
  395. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/exceptions.py +0 -0
  396. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/models.py +0 -0
  397. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/outcomes.py +0 -0
  398. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/repository.py +0 -0
  399. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/post/service.py +0 -0
  400. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/README.md +0 -0
  401. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/__init__.py +0 -0
  402. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/constants.py +0 -0
  403. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/dependencies.py +0 -0
  404. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/enums.py +0 -0
  405. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/exceptions.py +0 -0
  406. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/models.py +0 -0
  407. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/outbox_repository.py +0 -0
  408. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/outbox_service.py +0 -0
  409. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/outcomes.py +0 -0
  410. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/repository.py +0 -0
  411. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/service.py +0 -0
  412. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/user/utils.py +0 -0
  413. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/domains/utils.py +0 -0
  414. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/__init__.py +0 -0
  415. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/firebase/__init__.py +0 -0
  416. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/firebase/firebase_auth_adapter.py +0 -0
  417. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/__init__.py +0 -0
  418. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/attachment_staging_display_geometry.py +0 -0
  419. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/local_attachment_staging_adapter.py +0 -0
  420. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/local_banner_staging_adapter.py +0 -0
  421. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/local_staging_adapter.py +0 -0
  422. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_attachment_variant_encoder_adapter.py +0 -0
  423. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +0 -0
  424. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +0 -0
  425. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/pillow_staging_image.py +0 -0
  426. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_attachment_finals_publisher_adapter.py +0 -0
  427. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +0 -0
  428. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +0 -0
  429. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/outbox/outbox_consumer_adapter.py +0 -0
  430. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/infrastructure/outbox/outbox_producer_adapter.py +0 -0
  431. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/main.py +0 -0
  432. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/migrate_cli.py +0 -0
  433. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/__init__.py +0 -0
  434. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/arq.py +0 -0
  435. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/auth.py +0 -0
  436. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/config.py +0 -0
  437. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/containers.py +0 -0
  438. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/firebase.py +0 -0
  439. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/firebase_identity_toolkit.py +0 -0
  440. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/hookspecs.py +0 -0
  441. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/httpx_test_client.py +0 -0
  442. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/media.py +0 -0
  443. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/migrations.py +0 -0
  444. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/testing/plugin.py +0 -0
  445. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/__init__.py +0 -0
  446. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/main.py +0 -0
  447. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/__init__.py +0 -0
  448. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/analytics_refresh_cron.py +0 -0
  449. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +0 -0
  450. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +0 -0
  451. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +0 -0
  452. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_expired_account_deletions.py +0 -0
  453. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +0 -0
  454. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_poll_outbox.py +0 -0
  455. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_prune_analytics_daily_facts.py +0 -0
  456. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_prune_post_views.py +0 -0
  457. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +0 -0
  458. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_refresh_analytics.py +0 -0
  459. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_attachment_staging.py +0 -0
  460. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +0 -0
  461. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +0 -0
  462. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/__init__.py +0 -0
  463. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/delete_attachment_finals.py +0 -0
  464. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +0 -0
  465. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/delete_superseded_banner_finals.py +0 -0
  466. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_account_deletion.py +0 -0
  467. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_admin_user_deletion.py +0 -0
  468. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_comment_stats.py +0 -0
  469. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_post_stats.py +0 -0
  470. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_aggregate_user_stats.py +0 -0
  471. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_attachment_asset_variants.py +0 -0
  472. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_banner_asset_variants.py +0 -0
  473. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_cache_pattern_invalidation.py +0 -0
  474. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_destructive_comment_delete.py +0 -0
  475. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_destructive_post_delete.py +0 -0
  476. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_media_asset_variants.py +0 -0
  477. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_mute_lift.py +0 -0
  478. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_outbox_row.py +0 -0
  479. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_refresh_analytics_bucket.py +0 -0
  480. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/tasks/process_user_content_deletion.py +0 -0
  481. {core_framework-2.3.2 → core_framework-2.3.3}/core_framework/worker/worker_context.py +0 -0
  482. {core_framework-2.3.2 → core_framework-2.3.3}/docker-compose.dev.yaml +0 -0
  483. {core_framework-2.3.2 → core_framework-2.3.3}/docker-compose.yml +0 -0
  484. {core_framework-2.3.2 → core_framework-2.3.3}/dockerfile +0 -0
  485. {core_framework-2.3.2 → core_framework-2.3.3}/docs/README.md +0 -0
  486. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/README.md +0 -0
  487. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/deploy-playbook.md +0 -0
  488. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/e2e-smoke-tests-design.md +0 -0
  489. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/edge-upload-limits.md +0 -0
  490. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/examples/Caddyfile.example +0 -0
  491. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/examples/image-server-known-hosts.example +0 -0
  492. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/guides/postgres-setup.md +0 -0
  493. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/guides/redis-setup.md +0 -0
  494. {core_framework-2.3.2 → core_framework-2.3.3}/docs/deployments/release-playbook.md +0 -0
  495. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/analytics-rollup-design.md +0 -0
  496. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/cache-invalidation-design.md +0 -0
  497. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/create-idempotency-design.md +0 -0
  498. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/event-outbox-design.md +0 -0
  499. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/media-storage-topology.md +0 -0
  500. {core_framework-2.3.2 → core_framework-2.3.3}/docs/design/outbox-admin-ops-design.md +0 -0
  501. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/README.md +0 -0
  502. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/analytics/admin_analytics_reads.md +0 -0
  503. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/auth/access_control.md +0 -0
  504. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/auth/registration.md +0 -0
  505. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/cache/admin_cache_invalidation.md +0 -0
  506. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/README.md +0 -0
  507. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/admin_comments.md +0 -0
  508. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/comment_like.md +0 -0
  509. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/comment_report.md +0 -0
  510. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/comment_stats_aggregation.md +0 -0
  511. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/create_comment.md +0 -0
  512. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/delete_comment.md +0 -0
  513. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/edit_comment.md +0 -0
  514. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/comments/retrieve_comments.md +0 -0
  515. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/deletion/comments.md +0 -0
  516. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/deletion/overview.md +0 -0
  517. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/deletion/posts.md +0 -0
  518. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/deletion/users.md +0 -0
  519. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/README.md +0 -0
  520. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/attachment_upload.md +0 -0
  521. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/avatar-upload-design.md +0 -0
  522. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/banner-upload-design.md +0 -0
  523. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/post-comment-attachments-design.md +0 -0
  524. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/upload-pipeline-design.md +0 -0
  525. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/media/upload_pipeline.md +0 -0
  526. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/mentions/mentions_in_content.md +0 -0
  527. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/README.md +0 -0
  528. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/appeals.md +0 -0
  529. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/internal_notes.md +0 -0
  530. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/moderator_actions.md +0 -0
  531. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/reports.md +0 -0
  532. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/moderation/restrictions.md +0 -0
  533. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/notifications/notification_inbox.md +0 -0
  534. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/outbox/admin_outbox_ops.md +0 -0
  535. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/README.md +0 -0
  536. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/admin_posts.md +0 -0
  537. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/author_context.md +0 -0
  538. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/create_post.md +0 -0
  539. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/edit_post.md +0 -0
  540. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/hashtag_discovery.md +0 -0
  541. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/post_like.md +0 -0
  542. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/post_report.md +0 -0
  543. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/post_stats_aggregation.md +0 -0
  544. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/post_visibility.md +0 -0
  545. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/posts/retrieve_posts.md +0 -0
  546. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/account.md +0 -0
  547. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/account_deletion.md +0 -0
  548. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/admin_users.md +0 -0
  549. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/avatar.md +0 -0
  550. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/banner.md +0 -0
  551. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/blocks.md +0 -0
  552. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/change_history.md +0 -0
  553. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/check_username_exists.md +0 -0
  554. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/follow-system-design.md +0 -0
  555. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/follow.md +0 -0
  556. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/my_posts_and_comments.md +0 -0
  557. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/preferences.md +0 -0
  558. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/profile.md +0 -0
  559. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/public_profile.md +0 -0
  560. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/user_removal.md +0 -0
  561. {core_framework-2.3.2 → core_framework-2.3.3}/docs/domains/users/user_stats_aggregation.md +0 -0
  562. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/README.md +0 -0
  563. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/api.md +0 -0
  564. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/capability-wiring.md +0 -0
  565. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/overview.md +0 -0
  566. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/testing-plugin-design.md +0 -0
  567. {core_framework-2.3.2 → core_framework-2.3.3}/docs/library/workers.md +0 -0
  568. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/README.md +0 -0
  569. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/architecture-decisions.md +0 -0
  570. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/client-error-visibility.md +0 -0
  571. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/conventions.md +0 -0
  572. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/database-triggers.md +0 -0
  573. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/domain-services-and-adapters.md +0 -0
  574. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/layers-and-boundaries.md +0 -0
  575. {core_framework-2.3.2 → core_framework-2.3.3}/docs/platform/patch-update-typed-payload.md +0 -0
  576. {core_framework-2.3.2 → core_framework-2.3.3}/docs/testing.md +0 -0
  577. {core_framework-2.3.2 → core_framework-2.3.3}/docs/todo.md +0 -0
  578. {core_framework-2.3.2 → core_framework-2.3.3}/firebase_config.example.json +0 -0
  579. {core_framework-2.3.2 → core_framework-2.3.3}/makefile +0 -0
  580. {core_framework-2.3.2 → core_framework-2.3.3}/tests/__init__.py +0 -0
  581. {core_framework-2.3.2 → core_framework-2.3.3}/tests/conftest.py +0 -0
  582. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/_auth.py +0 -0
  583. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/_canaries.py +0 -0
  584. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/_media.py +0 -0
  585. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/_settings.py +0 -0
  586. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/_upload_payloads.py +0 -0
  587. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/conftest.py +0 -0
  588. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/media/pipeline_test.py +0 -0
  589. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/smoke/canary_test.py +0 -0
  590. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/smoke/media_test.py +0 -0
  591. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/smoke/system_test.py +0 -0
  592. {core_framework-2.3.2 → core_framework-2.3.3}/tests/e2e/smoke/tls_host_test.py +0 -0
  593. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/__init__.py +0 -0
  594. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/_http_error_details.py +0 -0
  595. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/analytics/_helpers.py +0 -0
  596. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/__init__.py +0 -0
  597. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_auth_helpers.py +0 -0
  598. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_destructive_delete_helpers.py +0 -0
  599. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_http_helpers.py +0 -0
  600. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_outbox_helpers.py +0 -0
  601. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_user_deletion_helpers.py +0 -0
  602. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/_user_helpers.py +0 -0
  603. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/__init__.py +0 -0
  604. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/_auth_cases.py +0 -0
  605. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/analytics/__init__.py +0 -0
  606. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/analytics/router_test.py +0 -0
  607. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/cache/__init__.py +0 -0
  608. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/cache/router_test.py +0 -0
  609. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/comments/__init__.py +0 -0
  610. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/comments/router_test.py +0 -0
  611. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/moderation/__init__.py +0 -0
  612. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/moderation/_auth_cases.py +0 -0
  613. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/moderation/router_test.py +0 -0
  614. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/outbox/__init__.py +0 -0
  615. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/outbox/router_test.py +0 -0
  616. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/posts/__init__.py +0 -0
  617. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/posts/router_test.py +0 -0
  618. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/users/__init__.py +0 -0
  619. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/admin/users/router_test.py +0 -0
  620. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/attachments/_helpers.py +0 -0
  621. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/attachments/attachment_upload_test.py +0 -0
  622. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/auth/__init__.py +0 -0
  623. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/auth/router_test.py +0 -0
  624. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/__init__.py +0 -0
  625. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/authenticated/__init__.py +0 -0
  626. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +0 -0
  627. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/comment_attachments_integration_test.py +0 -0
  628. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/public/__init__.py +0 -0
  629. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/comments/public/router_test.py +0 -0
  630. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/create_idempotency_integration_test.py +0 -0
  631. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/media/ingest_contract_test.py +0 -0
  632. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/mentions/mentions_integration_test.py +0 -0
  633. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/notifications/__init__.py +0 -0
  634. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/notifications/router_test.py +0 -0
  635. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/__init__.py +0 -0
  636. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +0 -0
  637. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -0
  638. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/followers_visibility_test.py +0 -0
  639. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/post_attachments_integration_test.py +0 -0
  640. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/post_deletion_integration_test.py +0 -0
  641. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/post_stats_dirty_marking_test.py +0 -0
  642. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/public/__init__.py +0 -0
  643. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/posts/public/router_test.py +0 -0
  644. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/public_read_by_id_unavailable_detail_test.py +0 -0
  645. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/system/__init__.py +0 -0
  646. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/system/router_test.py +0 -0
  647. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/__init__.py +0 -0
  648. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/authenticated/__init__.py +0 -0
  649. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/authenticated/avatar_upload_test.py +0 -0
  650. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/authenticated/banner_upload_test.py +0 -0
  651. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/authenticated/router_test.py +0 -0
  652. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/deletion_audit_integration_test.py +0 -0
  653. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/public/__init__.py +0 -0
  654. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/public/router_test.py +0 -0
  655. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/api/users/user_deletion_integration_test.py +0 -0
  656. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/__init__.py +0 -0
  657. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/_media_upload_helpers.py +0 -0
  658. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/account_deletion_test.py +0 -0
  659. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/aggregate_comment_stats_test.py +0 -0
  660. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/aggregate_post_stats_test.py +0 -0
  661. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/aggregate_user_stats_test.py +0 -0
  662. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/analytics_prune_test.py +0 -0
  663. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/analytics_refresh_test.py +0 -0
  664. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/attachment_upload_test.py +0 -0
  665. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/avatar_upload_test.py +0 -0
  666. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/banner_upload_test.py +0 -0
  667. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/conftest.py +0 -0
  668. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/create_idempotency_retention_test.py +0 -0
  669. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/moderation_outbox_test.py +0 -0
  670. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/mute_lift_test.py +0 -0
  671. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/stale_staging_sweep_test.py +0 -0
  672. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/user_outbox_test.py +0 -0
  673. {core_framework-2.3.2 → core_framework-2.3.3}/tests/integration/worker/utils_test.py +0 -0
  674. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/__init__.py +0 -0
  675. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/api/comments/authenticated/comment_request_schemas_test.py +0 -0
  676. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/api/dedupe_preserving_order_test.py +0 -0
  677. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/api/posts/authenticated/post_update_mapper_test.py +0 -0
  678. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/api/users/profile_update_mapper_test.py +0 -0
  679. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/application/comments/__init__.py +0 -0
  680. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/application/events/event_service_test.py +0 -0
  681. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/application/notifications/inbox_service_test.py +0 -0
  682. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/application/shared/request_context_test.py +0 -0
  683. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/application/users/deletion_audit_test.py +0 -0
  684. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/core/bundled_alembic_test.py +0 -0
  685. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/core/migrate_cli_test.py +0 -0
  686. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/core/pagination_test.py +0 -0
  687. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/docs/_api_reference.py +0 -0
  688. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/docs/api_routes_test.py +0 -0
  689. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/domains/__init__.py +0 -0
  690. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/domains/comment/__init__.py +0 -0
  691. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/domains/post/models_test.py +0 -0
  692. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/domains/user/service_test.py +0 -0
  693. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/infrastructure/__init__.py +0 -0
  694. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/infrastructure/media/__init__.py +0 -0
  695. {core_framework-2.3.2 → core_framework-2.3.3}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +0 -0
@@ -4,6 +4,33 @@ 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
+
7
34
  ## [2.3.2] - 2026-07-05
8
35
 
9
36
  ### Added
@@ -435,4 +462,5 @@ First **SemVer-stable** release per **`docs/library/package-api.md`**.
435
462
  [2.3.0]: https://github.com/NepNepFFXIV/core-framework/compare/v2.2.0...v2.3.0
436
463
  [2.3.1]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.0...v2.3.1
437
464
  [2.3.2]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.1...v2.3.2
438
- [unreleased]: https://github.com/NepNepFFXIV/core-framework/compare/v2.3.2...HEAD
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.2
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
@@ -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
+ """)
@@ -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)
@@ -16,7 +16,9 @@ Platform design and host extension: `docs/design/events-ingest-design.md`.
16
16
  ## Host extension
17
17
 
18
18
  - `register_event_handler(event_type, handler)` — append a handler after `configure_application_dependencies`
19
- - `configure_event_handlers()` — reset registry and register core built-ins
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`)
20
22
  - `type` and `subject_type` are plain strings at the schema boundary
21
23
  - Each handler receives the full batch and filters its own `subject_type` values
22
24
 
@@ -6,9 +6,10 @@ import core_framework.domains.analytics.dependencies as analytics_deps
6
6
  import core_framework.domains.post.dependencies as post_deps
7
7
  import core_framework.domains.user.dependencies as user_deps
8
8
  from core_framework.application.events.models import Event
9
+ from core_framework.application.events.utm_capture_kinds import get_utm_capture_kinds
9
10
  from core_framework.application.posts.aggregation_service import mark_post_stats_dirty
10
11
  from core_framework.application.shared.enums import EventType, SubjectType
11
- from core_framework.domains.analytics import UTM_ALLOWLISTED_KEYS
12
+ from core_framework.domains.analytics import MAX_UTM_KIND_LENGTH, UTM_ALLOWLISTED_KEYS, UTM_KIND_SUBJECT_TYPE
12
13
 
13
14
  logger = get_logger(__name__)
14
15
 
@@ -76,8 +77,12 @@ async def record_signup_events(*, events: list[Event], token: str, request_conte
76
77
 
77
78
  async def record_utm_events(*, events: list[Event], token: str, request_context: dict[str, str]) -> None:
78
79
  """Persist UTM attribution from batched client events."""
80
+ capture_kind: str | None = None
79
81
  utm: dict[str, str] = {}
80
82
  for event in events:
83
+ if event.subject_type == UTM_KIND_SUBJECT_TYPE:
84
+ capture_kind = event.subject
85
+ continue
81
86
  if event.subject_type in UTM_ALLOWLISTED_KEYS:
82
87
  utm[event.subject_type] = event.subject
83
88
  continue
@@ -85,9 +90,19 @@ async def record_utm_events(*, events: list[Event], token: str, request_context:
85
90
  "UTM event item ignored: unknown subject_type",
86
91
  subject_type=event.subject_type,
87
92
  )
93
+ normalized_kind: str | None = None
94
+ if capture_kind is not None:
95
+ trimmed_kind = capture_kind.strip()
96
+ if trimmed_kind:
97
+ normalized_kind = trimmed_kind[:MAX_UTM_KIND_LENGTH]
98
+ if normalized_kind is None or normalized_kind not in get_utm_capture_kinds():
99
+ return
100
+ if not any(value.strip() for value in utm.values()):
101
+ return
88
102
  try:
89
103
  await analytics_deps.analytics_service.add_utm_event(
90
104
  token=token,
105
+ kind=normalized_kind,
91
106
  utm=utm,
92
107
  user_id=request_context.get("viewer_id"),
93
108
  client_context=request_context,
@@ -0,0 +1,30 @@
1
+ from typing import Final
2
+
3
+ from core_framework.domains.analytics import MAX_UTM_KIND_LENGTH
4
+
5
+ CORE_UTM_CAPTURE_KIND_REGISTRATION: Final[str] = "registration"
6
+
7
+ _utm_capture_kinds: set[str] = set()
8
+
9
+
10
+ def configure_utm_capture_kinds() -> None:
11
+ """Reset the capture-kind registry and register core built-in kinds."""
12
+ global _utm_capture_kinds
13
+ _utm_capture_kinds = {CORE_UTM_CAPTURE_KIND_REGISTRATION}
14
+
15
+
16
+ def register_utm_capture_kind(kind: str) -> None:
17
+ """Register one ``utm_data`` capture kind (host extension point)."""
18
+ trimmed = kind.strip()
19
+ if not trimmed:
20
+ raise ValueError("utm capture kind must not be empty or whitespace-only")
21
+ if len(trimmed) > MAX_UTM_KIND_LENGTH:
22
+ raise ValueError(f"utm capture kind exceeds max length ({MAX_UTM_KIND_LENGTH})")
23
+ if trimmed in _utm_capture_kinds:
24
+ raise ValueError(f"duplicate utm capture kind: {trimmed!r}")
25
+ _utm_capture_kinds.add(trimmed)
26
+
27
+
28
+ def get_utm_capture_kinds() -> frozenset[str]:
29
+ """Return registered capture kinds for ``utm_data`` ingest."""
30
+ return frozenset(_utm_capture_kinds)
@@ -35,7 +35,8 @@ Host registration (Phase 8) is documented in the design doc for consuming applic
35
35
  #### utm_events
36
36
 
37
37
  - Append-only UTM attribution captures from `POST /events` with `type: "utm_data"`
38
- - Columns: `id`, `created_at`, `token`, optional `user_id`, `utm` jsonb, `request_context` jsonb
39
- - `utm` holds folded client UTM key/value pairs; `request_context` holds server-derived metadata (same shape as login telemetry)
38
+ - Columns: `id`, `created_at`, `token`, optional `user_id`, `kind`, `utm` jsonb, `request_context` jsonb
39
+ - `kind` names the capture context (for example `registration`); distinct from `daily_fact.kind`
40
+ - `utm` holds folded client UTM key/value pairs only; `request_context` holds server-derived metadata (same shape as login telemetry)
40
41
  - No dedup on `token` — each accepted ingest may append a row
41
42
  - Design: `docs/design/utm-events-design.md`
@@ -1,6 +1,8 @@
1
1
  from core_framework.domains.analytics.constants import (
2
2
  DAILY_FACT_RETENTION_DAYS,
3
+ MAX_UTM_KIND_LENGTH,
3
4
  UTM_ALLOWLISTED_KEYS,
5
+ UTM_KIND_SUBJECT_TYPE,
4
6
  )
5
7
  from core_framework.domains.analytics.exceptions import BaseAnalyticsException
6
8
  from core_framework.domains.analytics.models import DailyFactBucket, DailyFactDayTotal, DailyFactKindTotal
@@ -14,5 +16,7 @@ __all__ = [
14
16
  "DailyFactBucket",
15
17
  "DailyFactDayTotal",
16
18
  "DailyFactKindTotal",
19
+ "MAX_UTM_KIND_LENGTH",
17
20
  "UTM_ALLOWLISTED_KEYS",
21
+ "UTM_KIND_SUBJECT_TYPE",
18
22
  ]
@@ -4,6 +4,10 @@ DAILY_FACT_RETENTION_DAYS: Final[int] = 365
4
4
 
5
5
  MAX_UTM_VALUE_LENGTH: Final[int] = 128
6
6
 
7
+ MAX_UTM_KIND_LENGTH: Final[int] = 64
8
+
9
+ UTM_KIND_SUBJECT_TYPE: Final[str] = "kind"
10
+
7
11
  UTM_ALLOWLISTED_KEYS: Final[frozenset[str]] = frozenset(
8
12
  {
9
13
  "utm_source",
@@ -235,6 +235,7 @@ class AnalyticsRepository:
235
235
  *,
236
236
  token: str,
237
237
  user_id: str | None,
238
+ kind: str,
238
239
  utm: dict[str, str],
239
240
  client_context: dict[str, str],
240
241
  ) -> None:
@@ -244,6 +245,7 @@ class AnalyticsRepository:
244
245
  Args:
245
246
  token: Event ingest token from the client request.
246
247
  user_id: Authenticated user id when present; otherwise ``None``.
248
+ kind: Capture context for this attribution row.
247
249
  utm: Normalized UTM key/value pairs for jsonb storage.
248
250
  client_context: Server-derived request metadata.
249
251
 
@@ -251,8 +253,8 @@ class AnalyticsRepository:
251
253
  None.
252
254
  """
253
255
  query = f"""
254
- insert into {self.schema_sql}.utm_events (token, user_id, utm, request_context)
255
- values ($1, $2, $3::jsonb, $4::jsonb)
256
+ insert into {self.schema_sql}.utm_events (token, user_id, kind, utm, request_context)
257
+ values ($1, $2, $3, $4::jsonb, $5::jsonb)
256
258
  """
257
259
  async with self.write_database.get_connection() as connection:
258
- await connection.execute(query, token, user_id, utm, client_context)
260
+ await connection.execute(query, token, user_id, kind, utm, client_context)
@@ -5,6 +5,7 @@ from structlog import get_logger
5
5
 
6
6
  from core_framework.domains.analytics.constants import (
7
7
  DAILY_FACT_RETENTION_DAYS,
8
+ MAX_UTM_KIND_LENGTH,
8
9
  MAX_UTM_VALUE_LENGTH,
9
10
  UTM_ALLOWLISTED_KEYS,
10
11
  )
@@ -229,30 +230,36 @@ class AnalyticsService:
229
230
  self,
230
231
  *,
231
232
  token: str,
233
+ kind: str,
232
234
  utm: dict[str, str],
233
235
  user_id: str | None,
234
236
  client_context: dict[str, str],
235
237
  ) -> bool:
236
238
  """
237
- Persist one UTM attribution capture when normalized payload is non-empty.
239
+ Persist one UTM attribution capture when normalized payload is valid.
238
240
 
239
241
  Args:
240
242
  token: Event ingest token from the client request.
243
+ kind: Capture context from the ingest batch.
241
244
  utm: Folded UTM key/value pairs from the ingest batch.
242
245
  user_id: Authenticated user id when present; otherwise ``None``.
243
246
  client_context: Server-derived request metadata.
244
247
 
245
248
  Returns:
246
- ``True`` when a row was inserted; ``False`` when validation yields an empty ``utm`` object.
249
+ ``True`` when a row was inserted; ``False`` when validation fails.
247
250
  """
248
- require_non_blank_kwargs(token=token)
251
+ require_non_blank_kwargs(token=token, kind=kind)
249
252
  require_non_blank_if_not_none(user_id=user_id)
253
+ normalized_kind = _normalize_capture_kind(kind)
254
+ if not normalized_kind:
255
+ return False
250
256
  normalized_utm = _normalize_utm_payload(utm)
251
257
  if not normalized_utm:
252
258
  return False
253
259
  await self.repository.insert_utm_event(
254
260
  token=token,
255
261
  user_id=user_id,
262
+ kind=normalized_kind,
256
263
  utm=normalized_utm,
257
264
  client_context=client_context,
258
265
  )
@@ -263,6 +270,13 @@ def _start_of_utc_day(day: date) -> datetime:
263
270
  return datetime.combine(day, time.min, tzinfo=timezone.utc)
264
271
 
265
272
 
273
+ def _normalize_capture_kind(kind: str) -> str | None:
274
+ trimmed = kind.strip()
275
+ if not trimmed:
276
+ return None
277
+ return trimmed[:MAX_UTM_KIND_LENGTH]
278
+
279
+
266
280
  def _normalize_utm_payload(utm: dict[str, str]) -> dict[str, str]:
267
281
  normalized: dict[str, str] = {}
268
282
  for key, value in utm.items():
@@ -0,0 +1,78 @@
1
+ # App server deploy SSH
2
+
3
+ Wire GitHub Actions SSH deploy to the **app server** deploy user. This guide generates
4
+ the key on your **laptop** (`deploy-to-app-server`). For server-side generation during
5
+ [ubuntu-server-setup.md](ubuntu-server-setup.md) section 5 (`~/.ssh/id_ed25519` on the
6
+ deploy user), paste `cat ~/.ssh/id_ed25519` into the same GitHub secret instead — there
7
+ is no `deploy-to-app-server` file in that path.
8
+
9
+ | Machine | Role in this guide |
10
+ | -------------- | ------------------------------------------------------------------------------------------------------- |
11
+ | **Laptop** | Generate keys, install public key via SSH, verify, paste GitHub secrets |
12
+ | **App server** | Receives the public key in `/home/{USER}/.ssh/authorized_keys` — no manual shell commands in this guide |
13
+
14
+ GitHub → Environments → **`development`** / **`production`**:
15
+
16
+ **Variables**
17
+
18
+ - **`DEPLOY_SERVER_HOST`**
19
+ - **`DEPLOY_SERVER_PORT`**
20
+ - **`DEPLOY_SERVER_USER`** — deploy user; must be in **`docker`** group
21
+
22
+ **Secrets**
23
+
24
+ - **`DEPLOY_SERVER_SSH_KEY`** — contents of **`deploy-to-app-server`** (laptop path) or **`~/.ssh/id_ed25519`** (ubuntu-server-setup path)
25
+
26
+ ______________________________________________________________________
27
+
28
+ ## 1. Generate key pair
29
+
30
+ **Where:** your **laptop** (creates `deploy-to-app-server` and `deploy-to-app-server.pub` in the current directory).
31
+
32
+ ```bash
33
+ ssh-keygen -t ed25519 -f deploy-to-app-server -N ""
34
+ ```
35
+
36
+ ______________________________________________________________________
37
+
38
+ ## 2. Install public key on app server
39
+
40
+ **Where:** your **laptop** — SSHs into the **app server** as `root` and configures the deploy user.
41
+
42
+ Install the public key:
43
+
44
+ ```bash
45
+ ssh -p {PORT} root@{HOST} "mkdir -p /home/{USER}/.ssh && chmod 700 /home/{USER}/.ssh && cat >> /home/{USER}/.ssh/authorized_keys && chmod 600 /home/{USER}/.ssh/authorized_keys && chown -R {USER}:{USER} /home/{USER}/.ssh" < deploy-to-app-server.pub
46
+ ```
47
+
48
+ Add the deploy user to the **`docker`** group (required for deploy):
49
+
50
+ ```bash
51
+ ssh -p {PORT} root@{HOST} "usermod -aG docker {USER}"
52
+ ```
53
+
54
+ ______________________________________________________________________
55
+
56
+ ## 3. Add config to GitHub
57
+
58
+ **Where:** your **laptop** — copy the private key, then paste in the GitHub UI.
59
+
60
+ ```bash
61
+ cat deploy-to-app-server
62
+ ```
63
+
64
+ Paste into **`DEPLOY_SERVER_SSH_KEY`** (environment **secret**). Set **`DEPLOY_SERVER_HOST`**, **`DEPLOY_SERVER_PORT`**, and **`DEPLOY_SERVER_USER`** as environment **variables** (same **`{HOST}`** / **`{PORT}`** / **`{USER}`** as above).
65
+
66
+ ______________________________________________________________________
67
+
68
+ ## 4. Verify
69
+
70
+ **Where:** your **laptop**.
71
+
72
+ ```bash
73
+ ssh -i deploy-to-app-server -p {PORT} {USER}@{HOST}
74
+ ```
75
+
76
+ A shell on the app server as the deploy user means the setup is correct.
77
+
78
+ ______________________________________________________________________
@@ -0,0 +1,93 @@
1
+ # Image server SSH
2
+
3
+ Wire SSH from the **app server** (worker) to the **image server** (`root`). Keys are
4
+ generated on your **laptop**; the public key is installed on the image server; the
5
+ private key and host fingerprint go to GitHub for deploy.
6
+
7
+ | Machine | Role in this guide |
8
+ | ---------------- | ---------------------------------------------------------------------------- |
9
+ | **Laptop** | Generate keys, `ssh-keyscan`, paste GitHub secrets |
10
+ | **Image server** | Receives the public key in `/root/.ssh/authorized_keys` — no manual commands |
11
+ | **App server** | Optional verify step (step 5) |
12
+
13
+ GitHub → Environments → **`development`** / **`production`**:
14
+
15
+ **Variables**
16
+
17
+ - **`IMAGE_SERVER_HOST`**
18
+ - **`IMAGE_SERVER_PORT`**
19
+ - **`IMAGE_SERVER_USER`** — **`root`**
20
+
21
+ **Secrets**
22
+
23
+ - **`IMAGE_SERVER_SSH_PRIVATE_KEY`** — contents of **`worker-to-image-server`**
24
+ - **`IMAGE_SERVER_KNOWN_HOSTS`** — output of **`ssh-keyscan`** (step 3); trust anchor, not a credential
25
+
26
+ ______________________________________________________________________
27
+
28
+ ## 1. Generate key pair
29
+
30
+ **Where:** your **laptop** (creates `worker-to-image-server` and `worker-to-image-server.pub` in the current directory).
31
+
32
+ ```bash
33
+ ssh-keygen -t ed25519 -f worker-to-image-server -N ""
34
+ ```
35
+
36
+ ______________________________________________________________________
37
+
38
+ ## 2. Install public key on image server
39
+
40
+ **Where:** your **laptop** — SSHs into the **image server** and appends the public key to `authorized_keys`.
41
+
42
+ ```bash
43
+ ssh -p {PORT} root@{HOST} "mkdir -p /root/.ssh && chmod 700 /root/.ssh && cat >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys" < worker-to-image-server.pub
44
+ ```
45
+
46
+ ______________________________________________________________________
47
+
48
+ ## 3. Get `IMAGE_SERVER_KNOWN_HOSTS`
49
+
50
+ **Where:** your **laptop**.
51
+
52
+ ```bash
53
+ ssh-keyscan -p {PORT} {HOST}
54
+ ```
55
+
56
+ Paste all output into GitHub environment secret **`IMAGE_SERVER_KNOWN_HOSTS`**. Use the same **`{HOST}`** / **`{PORT}`** as the other image-server settings.
57
+
58
+ ______________________________________________________________________
59
+
60
+ ## 4. Add secrets to GitHub
61
+
62
+ **Where:** your **laptop** — copy the private key, then paste in the GitHub UI (step 3 output → **`IMAGE_SERVER_KNOWN_HOSTS`**, below → **`IMAGE_SERVER_SSH_PRIVATE_KEY`**).
63
+
64
+ ```bash
65
+ cat worker-to-image-server
66
+ ```
67
+
68
+ Paste into **`IMAGE_SERVER_SSH_PRIVATE_KEY`**.
69
+
70
+ ______________________________________________________________________
71
+
72
+ ## 5. Verify
73
+
74
+ **Where:** **app server** — confirms the worker host can reach the image server with this key.
75
+
76
+ Copy the private key from your laptop to the app server:
77
+
78
+ **Laptop:**
79
+
80
+ ```bash
81
+ scp -P {DEPLOY_SERVER_PORT} worker-to-image-server {DEPLOY_SERVER_USER}@{APP_SERVER_HOST}:~/
82
+ ```
83
+
84
+ **App server:**
85
+
86
+ ```bash
87
+ chmod 600 ~/worker-to-image-server
88
+ ssh -i ~/worker-to-image-server -p {PORT} root@{HOST}
89
+ ```
90
+
91
+ A shell on the image server means the setup is correct. You can delete `~/worker-to-image-server` on the app server after testing — deploy uses the GitHub secret, not this file.
92
+
93
+ ______________________________________________________________________
@@ -88,6 +88,7 @@ On the server as **`{DEPLOY_USER}`**:
88
88
  ```bash
89
89
  mkdir -p ~/.ssh
90
90
  chmod 700 ~/.ssh
91
+ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
91
92
  cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
92
93
  chmod 600 ~/.ssh/authorized_keys
93
94
  cat ~/.ssh/id_ed25519
@@ -7,16 +7,16 @@ a capability is built, not day-to-day coding rules.
7
7
  **Rules** (conventions, layering, ADRs) live in [`../platform/`](../platform/).
8
8
  **Product flows** and per-domain feature design live in [`../domains/`](../domains/).
9
9
 
10
- | Doc | Purpose |
11
- | -------------------------------------------------------------- | ----------------------------------------------------------------------------- |
12
- | [`event-outbox-design.md`](event-outbox-design.md) | Transactional outbox (mirror fanout) |
13
- | [`events-ingest-design.md`](events-ingest-design.md) | Client events ingest — host-extensible handler dispatch |
14
- | [`analytics-rollup-design.md`](analytics-rollup-design.md) | Analytics rollup domain — time-bucketed activity rollups |
15
- | [`utm-events-design.md`](utm-events-design.md) | UTM attribution ingest — `utm_data` on `POST /events`, `analytics.utm_events` |
16
- | [`outbox-admin-ops-design.md`](outbox-admin-ops-design.md) | Admin API: list dead outbox rows, replay one row |
17
- | [`create-idempotency-design.md`](create-idempotency-design.md) | HTTP create idempotency for post/comment create |
18
- | [`cache-invalidation-design.md`](cache-invalidation-design.md) | Cache invalidation — write-path, admin API, planned events hints |
19
- | [`media-storage-topology.md`](media-storage-topology.md) | Rack media layout: staging vs finals; no S3/R2 |
10
+ | Doc | Purpose |
11
+ | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
12
+ | [`event-outbox-design.md`](event-outbox-design.md) | Transactional outbox (mirror fanout) |
13
+ | [`events-ingest-design.md`](events-ingest-design.md) | Client events ingest — host-extensible handler dispatch |
14
+ | [`analytics-rollup-design.md`](analytics-rollup-design.md) | Analytics rollup domain — time-bucketed activity rollups |
15
+ | [`utm-events-design.md`](utm-events-design.md) | UTM attribution ingest — `utm_data` on `POST /events`, `analytics.utm_events`, capture `kind` |
16
+ | [`outbox-admin-ops-design.md`](outbox-admin-ops-design.md) | Admin API: list dead outbox rows, replay one row |
17
+ | [`create-idempotency-design.md`](create-idempotency-design.md) | HTTP create idempotency for post/comment create |
18
+ | [`cache-invalidation-design.md`](cache-invalidation-design.md) | Cache invalidation — write-path, admin API, planned events hints |
19
+ | [`media-storage-topology.md`](media-storage-topology.md) | Rack media layout: staging vs finals; no S3/R2 |
20
20
 
21
21
  When adding a new cross-cutting mechanism, add a `*-design.md` here and a client
22
22
  flow doc under `docs/domains/` when the HTTP surface is ready.
@@ -1,6 +1,10 @@
1
1
  # Client Events Ingest — Host-Extensible Design
2
2
 
3
- **Status:** **Shipped (v1)** for core event types **`impression`**, **`login`**, **`signup`**, and **`utm_data`**. Hosts may register additional types at bootstrap. Application-level rate limiting is **not** implemented — use edge limits and client-side batching (see [`events.md`](../domains/events/events.md)).
3
+ **Status:** **Shipped** for core event types **`impression`**, **`login`**, **`signup`**, and
4
+ **`utm_data`** (including capture **`kind`** on UTM rows). Hosts may register additional
5
+ event types and `utm_data` capture kinds at bootstrap. Application-level rate limiting
6
+ is **not** implemented — use edge limits and client-side batching (see
7
+ [`events.md`](../domains/events/events.md)).
4
8
 
5
9
  Core provides a generic, token-gated, client-initiated channel for **eventually
6
10
  consistent side effects**. Clients fetch a signed token and post a batch; the
@@ -108,21 +112,22 @@ ______________________________________________________________________
108
112
  | Built-in `impression` | Filters `subject_type == "post"`; dedup by `(post_id, token)`; marks post dirty on new row |
109
113
  | Built-in `login` | Uses `viewer_id` from request context (not the payload); auto-provisions application user row when missing |
110
114
  | Built-in `signup` | Uses `viewer_id` from request context (not the payload) |
111
- | Built-in `utm_data` | Folds allowlisted `events[]` items into `analytics.utm_events`; append-all; optional auth — see [utm-events-design.md](utm-events-design.md) |
115
+ | Built-in `utm_data` | Extracts `kind`, folds allowlisted UTM items into `analytics.utm_events`; append-all; optional auth — see [utm-events-design.md](utm-events-design.md) |
112
116
 
113
117
  `EventType` / `SubjectType` StrEnums in `core_framework/application/shared/enums.py`
114
118
  are **internal constants** for core handler registration only — not schema validators.
115
119
 
116
120
  ### Code locations
117
121
 
118
- | Piece | Location |
119
- | ---------------- | ------------------------------------------------------------------------- |
120
- | Schema | `core_framework/api/events/schemas.py` |
121
- | Model | `core_framework/application/events/models.py` |
122
- | Token | `core_framework/application/events/event_token.py` |
123
- | Handler registry | `core_framework/application/events/event_service.py` |
124
- | Route | `core_framework/api/events/router.py` |
125
- | Bootstrap | `configure_event_handlers()` in `core_framework/application/bootstrap.py` |
122
+ | Piece | Location |
123
+ | ------------------------- | ------------------------------------------------------------------------------------------------------------- |
124
+ | Schema | `core_framework/api/events/schemas.py` |
125
+ | Model | `core_framework/application/events/models.py` |
126
+ | Token | `core_framework/application/events/event_token.py` |
127
+ | Handler registry | `core_framework/application/events/event_service.py` |
128
+ | UTM capture-kind registry | `core_framework/application/events/utm_capture_kinds.py` |
129
+ | Route | `core_framework/api/events/router.py` |
130
+ | Bootstrap | `configure_event_handlers()` and `configure_utm_capture_kinds()` in `core_framework/application/bootstrap.py` |
126
131
 
127
132
  ______________________________________________________________________
128
133
 
@@ -163,6 +168,24 @@ A host **impression** handler should:
163
168
  Core never imports host code. The host owns its `type` and `subject_type` string
164
169
  literals.
165
170
 
171
+ ### `utm_data` capture kinds
172
+
173
+ Hosts extend the **`utm_data`** capture-kind allowlist without a core release:
174
+
175
+ 1. Call `register_utm_capture_kind(kind)` after `configure_application_dependencies`
176
+ (same bootstrap timing as `register_event_handler`).
177
+ 1. Document the new `kind` string in host flow docs — core documents `registration`
178
+ only in [events.md](../domains/events/events.md).
179
+ 1. Clients send the `kind` as an `events[]` item with `subject_type` `kind` and
180
+ `subject` set to the registered string, plus at least one allowlisted UTM item.
181
+
182
+ Core resets and seeds `registration` in `configure_utm_capture_kinds()` during
183
+ application bootstrap. The single core `utm_data` handler enforces the merged
184
+ allowlist; hosts do not register a second handler for additional kinds.
185
+
186
+ See [utm-events-design.md](utm-events-design.md) for persistence rules (`kind` and
187
+ non-empty `utm` both required).
188
+
166
189
  ### Dispatch semantics
167
190
 
168
191
  - All handlers for the event type are scheduled as separate `BackgroundTasks` entries; they run **one after another** after the response (not concurrently).
@@ -194,6 +217,7 @@ ______________________________________________________________________
194
217
  | `EventType` / `SubjectType` as internal constants only | Core handlers use named constants; schema does not gate hosts |
195
218
  | Single global token max-age | Token is type-agnostic; one expiry for all event types |
196
219
  | Multi-handler registry keyed by string | Hosts attach to existing or new event types without core imports |
220
+ | `register_utm_capture_kind` for `utm_data` | Hosts add funnel capture kinds without core releases; single handler and `analytics.utm_events` table |
197
221
  | Each handler filters its own subject types | Post and host handlers coexist on `impression` |
198
222
  | Unknown types accepted as 202, no-op | Typos do not 422; safe for fire-and-forget |
199
223
  | `(subject, token)` dedup for impression handlers | Same semantics as post views |