core-framework 2.3.0__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/postgres-config-conventions.mdc +9 -0
  2. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/repository-schema-isolation.mdc +21 -8
  3. {core_framework-2.3.0 → core_framework-2.3.1}/CHANGELOG.md +13 -0
  4. {core_framework-2.3.0 → core_framework-2.3.1}/PKG-INFO +1 -1
  5. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/outbox/schemas.py +7 -3
  6. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/read_service.py +25 -0
  7. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/comment_created.py +7 -0
  8. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/post_created.py +7 -0
  9. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/post_viewed.py +7 -0
  10. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/sources/user_registered.py +7 -0
  11. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/models.py +2 -0
  12. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/cache/models.py +4 -0
  13. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/models.py +2 -0
  14. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_read.py +1 -0
  15. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/attachment_service.py +15 -3
  16. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/read_url_config.py +4 -0
  17. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/enums.py +2 -0
  18. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/events.py +9 -0
  19. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/enums.py +6 -0
  20. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/exceptions.py +20 -0
  21. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/deletion_audit.py +1 -0
  22. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/enums.py +4 -0
  23. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/user_deletion_service.py +21 -2
  24. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/database.py +5 -0
  25. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/__init__.py +2 -1
  26. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/dependencies.py +6 -1
  27. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/models.py +6 -0
  28. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/ports/activity_source.py +2 -0
  29. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/repository.py +68 -13
  30. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/service.py +33 -1
  31. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/ports/auth.py +2 -0
  32. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/dependencies.py +6 -1
  33. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/repository.py +219 -208
  34. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/service.py +2 -0
  35. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/finals_publisher.py +2 -0
  36. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/staging.py +2 -0
  37. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/components/variant_encoder.py +2 -0
  38. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/finals_publisher.py +2 -0
  39. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/staging.py +2 -0
  40. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/ports/variant_encoder.py +2 -0
  41. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/service.py +2 -0
  42. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/finals_publisher.py +2 -0
  43. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/staging.py +3 -0
  44. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/variant_encoder.py +2 -0
  45. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/finals_publisher.py +2 -0
  46. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/staging.py +2 -0
  47. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/variant_encoder.py +2 -0
  48. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/service.py +2 -0
  49. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/finals_publisher.py +2 -0
  50. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/staging.py +3 -0
  51. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/components/variant_encoder.py +2 -0
  52. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/finals_publisher.py +2 -0
  53. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/staging.py +2 -0
  54. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/ports/variant_encoder.py +2 -0
  55. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/service.py +2 -0
  56. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/dependencies.py +6 -1
  57. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/repository.py +63 -52
  58. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/service.py +2 -0
  59. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/dependencies.py +14 -6
  60. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outbox_repository.py +19 -11
  61. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/repository.py +104 -102
  62. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/service.py +2 -0
  63. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/dependencies.py +6 -1
  64. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/repository.py +85 -74
  65. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/service.py +2 -0
  66. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/consumer.py +2 -0
  67. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/producer.py +4 -4
  68. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/dependencies.py +6 -1
  69. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/repository.py +238 -227
  70. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/service.py +2 -0
  71. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/dependencies.py +14 -6
  72. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outbox_repository.py +19 -11
  73. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/repository.py +128 -126
  74. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/service.py +2 -0
  75. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/attachment_staging_display_geometry.py +4 -0
  76. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_attachment_staging_adapter.py +2 -0
  77. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_banner_staging_adapter.py +2 -0
  78. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/local_staging_adapter.py +2 -0
  79. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_attachment_variant_encoder_adapter.py +2 -0
  80. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +2 -0
  81. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +2 -0
  82. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_attachment_finals_publisher_adapter.py +2 -0
  83. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +2 -0
  84. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +2 -0
  85. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/outbox/outbox_consumer_adapter.py +21 -10
  86. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/outbox/outbox_producer_adapter.py +6 -4
  87. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/auth.py +20 -11
  88. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/main.py +6 -0
  89. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/analytics_refresh_cron.py +2 -0
  90. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/worker_context.py +4 -0
  91. {core_framework-2.3.0 → core_framework-2.3.1}/docs/README.md +2 -0
  92. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/e2e-smoke-tests-design.md +1 -1
  93. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/users.md +48 -8
  94. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/post-comment-attachments-design.md +1 -1
  95. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/user_removal.md +10 -6
  96. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/README.md +2 -1
  97. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/package-api.md +1 -0
  98. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/testing-plugin-design.md +7 -6
  99. core_framework-2.3.1/docs/testing.md +149 -0
  100. core_framework-2.3.1/docs/todo.md +76 -0
  101. {core_framework-2.3.0 → core_framework-2.3.1}/pyproject.toml +1 -1
  102. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/analytics/_helpers.py +9 -4
  103. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_outbox_helpers.py +4 -7
  104. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/router_test.py +13 -7
  105. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/posts/router_test.py +14 -8
  106. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/users/router_test.py +9 -2
  107. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/comment_attachments_integration_test.py +236 -0
  108. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/create_idempotency_integration_test.py +16 -10
  109. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/notifications/router_test.py +9 -4
  110. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_attachments_integration_test.py +294 -0
  111. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_deletion_integration_test.py +14 -9
  112. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/deletion_audit_integration_test.py +6 -1
  113. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/user_deletion_integration_test.py +134 -0
  114. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/account_deletion_test.py +16 -8
  115. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/create_idempotency_retention_test.py +14 -8
  116. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/moderation_outbox_test.py +15 -7
  117. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/stale_staging_sweep_test.py +6 -1
  118. {core_framework-2.3.0 → core_framework-2.3.1}/uv.lock +1 -1
  119. core_framework-2.3.0/docs/todo.md +0 -11
  120. {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/fastapi +0 -0
  121. {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/library-skills/.library-skills.json +0 -0
  122. {core_framework-2.3.0 → core_framework-2.3.1}/.agents/skills/library-skills/SKILL.md +0 -0
  123. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/alembic-migrations.mdc +0 -0
  124. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-layer.mdc +0 -0
  125. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-reference-docs.mdc +0 -0
  126. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/api-validation.mdc +0 -0
  127. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/application-layer.mdc +0 -0
  128. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/constants-final.mdc +0 -0
  129. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/constitution.mdc +0 -0
  130. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/database-triggers.mdc +0 -0
  131. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/docstrings.mdc +0 -0
  132. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-caller-context.mdc +0 -0
  133. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-imports.mdc +0 -0
  134. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-input-guards.mdc +0 -0
  135. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
  136. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/domain-services-and-adapters.mdc +0 -0
  137. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/error-boundary.mdc +0 -0
  138. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/flow-documentation.mdc +0 -0
  139. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/inline-raise-messages.mdc +0 -0
  140. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/integration-test-strategy.mdc +0 -0
  141. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/layer-boundaries.mdc +0 -0
  142. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/no-code-in-docs.mdc +0 -0
  143. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/strong-reads.mdc +0 -0
  144. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/rules/structured-logging.mdc +0 -0
  145. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/add-config/SKILL.md +0 -0
  146. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/add-domain/SKILL.md +0 -0
  147. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/code-review/SKILL.md +0 -0
  148. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/fastapi +0 -0
  149. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/implement-feature/SKILL.md +0 -0
  150. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/recommend-features/SKILL.md +0 -0
  151. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/sync-host-rules/SKILL.md +0 -0
  152. {core_framework-2.3.0 → core_framework-2.3.1}/.cursor/skills/write-flow-doc/SKILL.md +0 -0
  153. {core_framework-2.3.0 → core_framework-2.3.1}/.dockerignore +0 -0
  154. {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/_deploy.yml +0 -0
  155. {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/dev-ci-cd.yaml +0 -0
  156. {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/manual-deployment.yaml +0 -0
  157. {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/publish-pypi.yml +0 -0
  158. {core_framework-2.3.0 → core_framework-2.3.1}/.github/workflows/test.yaml +0 -0
  159. {core_framework-2.3.0 → core_framework-2.3.1}/.gitignore +0 -0
  160. {core_framework-2.3.0 → core_framework-2.3.1}/.pre-commit-config.yaml +0 -0
  161. {core_framework-2.3.0 → core_framework-2.3.1}/.python-version +0 -0
  162. {core_framework-2.3.0 → core_framework-2.3.1}/LICENSE +0 -0
  163. {core_framework-2.3.0 → core_framework-2.3.1}/README.md +0 -0
  164. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/README +0 -0
  165. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/env.py +0 -0
  166. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/script.py.mako +0 -0
  167. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/versions/5b9ac98bb150_analytics_daily_fact.py +0 -0
  168. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic/versions/7f2a9c1d4e8b_analytics_daily_fact_day_index.py +0 -0
  169. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/analytics/alembic.ini +0 -0
  170. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/README +0 -0
  171. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/env.py +0 -0
  172. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/script.py.mako +0 -0
  173. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_attachments.py +0 -0
  174. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency.py +0 -0
  175. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_create_idempotency_created_at_index.py +0 -0
  176. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_add_comment_mentions.py +0 -0
  177. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/comment_tombstone_status_model.py +0 -0
  178. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
  179. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/comment/alembic.ini +0 -0
  180. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/README +0 -0
  181. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/env.py +0 -0
  182. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/script.py.mako +0 -0
  183. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
  184. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/extension/alembic.ini +0 -0
  185. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/README +0 -0
  186. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/env.py +0 -0
  187. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/script.py.mako +0 -0
  188. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_add_attachment_staging_registry.py +0 -0
  189. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +0 -0
  190. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/media_attachment_staging_registry_published_at.py +0 -0
  191. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
  192. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/media/alembic.ini +0 -0
  193. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/README +0 -0
  194. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/env.py +0 -0
  195. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/script.py.mako +0 -0
  196. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox.py +0 -0
  197. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox_dead_indexes.py +0 -0
  198. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/moderation_add_event_outbox_pending_created_at_index.py +0 -0
  199. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
  200. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/moderation/alembic.ini +0 -0
  201. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/README +0 -0
  202. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/env.py +0 -0
  203. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/script.py.mako +0 -0
  204. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
  205. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/notification/alembic.ini +0 -0
  206. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/README +0 -0
  207. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/env.py +0 -0
  208. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/script.py.mako +0 -0
  209. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_attachments.py +0 -0
  210. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_create_idempotency.py +0 -0
  211. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_create_idempotency_created_at_index.py +0 -0
  212. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_add_post_mentions.py +0 -0
  213. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_post_views_retention_high_water_mark.py +0 -0
  214. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/post_tombstone_status_model.py +0 -0
  215. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
  216. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/post/alembic.ini +0 -0
  217. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/README +0 -0
  218. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/env.py +0 -0
  219. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/script.py.mako +0 -0
  220. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
  221. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +0 -0
  222. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
  223. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox.py +0 -0
  224. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox_dead_indexes.py +0 -0
  225. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_add_event_outbox_pending_created_at_index.py +0 -0
  226. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/user_reserve_sentinel_user_ids.py +0 -0
  227. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
  228. {core_framework-2.3.0 → core_framework-2.3.1}/alembic/user/alembic.ini +0 -0
  229. {core_framework-2.3.0 → core_framework-2.3.1}/config.toml +0 -0
  230. {core_framework-2.3.0 → core_framework-2.3.1}/config.toml.template +0 -0
  231. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/__init__.py +0 -0
  232. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/__init__.py +0 -0
  233. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/__init__.py +0 -0
  234. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/analytics/router.py +0 -0
  235. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/analytics/schemas.py +0 -0
  236. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/cache/router.py +0 -0
  237. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/cache/schemas.py +0 -0
  238. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/comments/router.py +0 -0
  239. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/comments/schemas.py +0 -0
  240. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/__init__.py +0 -0
  241. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/router.py +0 -0
  242. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/moderation/schemas.py +0 -0
  243. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/outbox/router.py +0 -0
  244. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/posts/router.py +0 -0
  245. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/posts/schemas.py +0 -0
  246. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/router.py +0 -0
  247. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/__init__.py +0 -0
  248. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/router.py +0 -0
  249. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/admin/users/schemas.py +0 -0
  250. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/attachments/router.py +0 -0
  251. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/attachments/schemas.py +0 -0
  252. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/__init__.py +0 -0
  253. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/router.py +0 -0
  254. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/auth/schemas.py +0 -0
  255. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/mappers.py +0 -0
  256. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/router.py +0 -0
  257. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/authenticated/schemas.py +0 -0
  258. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/public/router.py +0 -0
  259. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/public/schemas.py +0 -0
  260. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/router.py +0 -0
  261. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/comments/schemas.py +0 -0
  262. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/constants.py +0 -0
  263. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/dependencies.py +0 -0
  264. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/events/router.py +0 -0
  265. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/events/schemas.py +0 -0
  266. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/idempotency/__init__.py +0 -0
  267. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/idempotency/dependencies.py +0 -0
  268. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/authenticated/router.py +0 -0
  269. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/authenticated/schemas.py +0 -0
  270. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/notifications/router.py +0 -0
  271. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/mappers.py +0 -0
  272. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/router.py +0 -0
  273. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/authenticated/schemas.py +0 -0
  274. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/public/router.py +0 -0
  275. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/public/schemas.py +0 -0
  276. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/router.py +0 -0
  277. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/posts/schemas.py +0 -0
  278. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/router.py +0 -0
  279. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/schemas.py +0 -0
  280. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/system/__init__.py +0 -0
  281. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/system/router.py +0 -0
  282. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/__init__.py +0 -0
  283. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/__init__.py +0 -0
  284. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/mappers.py +0 -0
  285. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/router.py +0 -0
  286. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/authenticated/schemas.py +0 -0
  287. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/mappers.py +0 -0
  288. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/__init__.py +0 -0
  289. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/router.py +0 -0
  290. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/public/schemas.py +0 -0
  291. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/router.py +0 -0
  292. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/api/users/shared/schemas.py +0 -0
  293. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/__init__.py +0 -0
  294. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/bucket_service.py +0 -0
  295. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/prune_service.py +0 -0
  296. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/refresh_service.py +0 -0
  297. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/analytics/registry.py +0 -0
  298. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/__init__.py +0 -0
  299. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/access_service.py +0 -0
  300. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/auth/auth_service.py +0 -0
  301. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/bootstrap.py +0 -0
  302. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/cache/invalidate_service.py +0 -0
  303. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/admin_service.py +0 -0
  304. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/aggregation_service.py +0 -0
  305. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/authenticated_service.py +0 -0
  306. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/cleanup_service.py +0 -0
  307. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/comments/public_service.py +0 -0
  308. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/README.md +0 -0
  309. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/event_service.py +0 -0
  310. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/events/event_token.py +0 -0
  311. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/README.md +0 -0
  312. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/avatar_service.py +0 -0
  313. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/banner_service.py +0 -0
  314. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/media/ingest_guards.py +0 -0
  315. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/__init__.py +0 -0
  316. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/appeal_service.py +0 -0
  317. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/moderator_service.py +0 -0
  318. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/report_service.py +0 -0
  319. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/scheduled_service.py +0 -0
  320. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/moderation/user_service.py +0 -0
  321. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/README.md +0 -0
  322. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/inbox_service.py +0 -0
  323. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/mute_service.py +0 -0
  324. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/notifications/notification_service.py +0 -0
  325. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/block_mirrors.py +0 -0
  326. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/exceptions.py +0 -0
  327. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/follow_mirrors.py +0 -0
  328. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/handlers.py +0 -0
  329. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/ops_service.py +0 -0
  330. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/polling_service.py +0 -0
  331. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/processing_service.py +0 -0
  332. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/outbox/restriction_mirrors.py +0 -0
  333. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/admin_service.py +0 -0
  334. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/aggregation_service.py +0 -0
  335. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/authenticated_service.py +0 -0
  336. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/cleanup_service.py +0 -0
  337. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/posts/public_service.py +0 -0
  338. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/__init__.py +0 -0
  339. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/user_agent.py +0 -0
  340. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/shared/worker_jobs.py +0 -0
  341. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/__init__.py +0 -0
  342. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/admin_service.py +0 -0
  343. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/aggregation_service.py +0 -0
  344. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/authenticated_service.py +0 -0
  345. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/public_service.py +0 -0
  346. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/application/users/scheduled_service.py +0 -0
  347. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/asgi.py +0 -0
  348. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/bundled_alembic.py +0 -0
  349. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/constants.py +0 -0
  350. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/__init__.py +0 -0
  351. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/cache.py +0 -0
  352. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/context.py +0 -0
  353. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/__init__.py +0 -0
  354. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/application.py +0 -0
  355. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/common.py +0 -0
  356. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exception_handlers/setup.py +0 -0
  357. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/exceptions.py +0 -0
  358. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/firebase.py +0 -0
  359. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/http_client.py +0 -0
  360. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/logging.py +0 -0
  361. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/middleware.py +0 -0
  362. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/observability.py +0 -0
  363. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/pagination.py +0 -0
  364. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/redis.py +0 -0
  365. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/runtime.py +0 -0
  366. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/core/settings.py +0 -0
  367. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/__init__.py +0 -0
  368. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/README.md +0 -0
  369. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/constants.py +0 -0
  370. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/analytics/exceptions.py +0 -0
  371. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/__init__.py +0 -0
  372. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/dependencies.py +0 -0
  373. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/exceptions.py +0 -0
  374. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/models.py +0 -0
  375. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/ports/__init__.py +0 -0
  376. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/auth/service.py +0 -0
  377. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/README.md +0 -0
  378. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/__init__.py +0 -0
  379. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/constants.py +0 -0
  380. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/enums.py +0 -0
  381. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/exceptions.py +0 -0
  382. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/models.py +0 -0
  383. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/comment/outcomes.py +0 -0
  384. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/exceptions.py +0 -0
  385. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/README.md +0 -0
  386. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/__init__.py +0 -0
  387. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/constants.py +0 -0
  388. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/exceptions.py +0 -0
  389. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/attachment/models.py +0 -0
  390. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/__init__.py +0 -0
  391. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/components/__init__.py +0 -0
  392. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/constants.py +0 -0
  393. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/exceptions.py +0 -0
  394. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/models.py +0 -0
  395. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
  396. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/constants.py +0 -0
  397. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/exceptions.py +0 -0
  398. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/banner/models.py +0 -0
  399. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/__init__.py +0 -0
  400. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/constants.py +0 -0
  401. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/exceptions.py +0 -0
  402. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/outcomes.py +0 -0
  403. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/media/shared/utils.py +0 -0
  404. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/README.md +0 -0
  405. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/__init__.py +0 -0
  406. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/enums.py +0 -0
  407. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/exceptions.py +0 -0
  408. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/models.py +0 -0
  409. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outbox_service.py +0 -0
  410. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/moderation/outcomes.py +0 -0
  411. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/README.md +0 -0
  412. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/__init__.py +0 -0
  413. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/enums.py +0 -0
  414. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/exceptions.py +0 -0
  415. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/notification/models.py +0 -0
  416. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/__init__.py +0 -0
  417. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/dependencies.py +0 -0
  418. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/models.py +0 -0
  419. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/ports/admin.py +0 -0
  420. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/outbox/service.py +0 -0
  421. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/README.md +0 -0
  422. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/__init__.py +0 -0
  423. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/constants.py +0 -0
  424. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/enums.py +0 -0
  425. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/exceptions.py +0 -0
  426. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/models.py +0 -0
  427. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/post/outcomes.py +0 -0
  428. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/README.md +0 -0
  429. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/__init__.py +0 -0
  430. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/constants.py +0 -0
  431. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/enums.py +0 -0
  432. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/exceptions.py +0 -0
  433. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/models.py +0 -0
  434. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outbox_service.py +0 -0
  435. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/outcomes.py +0 -0
  436. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/user/utils.py +0 -0
  437. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/domains/utils.py +0 -0
  438. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/__init__.py +0 -0
  439. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/firebase/__init__.py +0 -0
  440. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/firebase/firebase_auth_adapter.py +0 -0
  441. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/__init__.py +0 -0
  442. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/infrastructure/media/pillow_staging_image.py +0 -0
  443. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/main.py +0 -0
  444. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/migrate_cli.py +0 -0
  445. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/__init__.py +0 -0
  446. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/arq.py +0 -0
  447. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/config.py +0 -0
  448. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/containers.py +0 -0
  449. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/firebase.py +0 -0
  450. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/firebase_identity_toolkit.py +0 -0
  451. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/hookspecs.py +0 -0
  452. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/httpx_test_client.py +0 -0
  453. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/media.py +0 -0
  454. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/migrations.py +0 -0
  455. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/testing/plugin.py +0 -0
  456. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/__init__.py +0 -0
  457. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/__init__.py +0 -0
  458. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +0 -0
  459. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +0 -0
  460. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +0 -0
  461. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_expired_account_deletions.py +0 -0
  462. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +0 -0
  463. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_poll_outbox.py +0 -0
  464. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_prune_analytics_daily_facts.py +0 -0
  465. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_prune_post_views.py +0 -0
  466. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_purge_expired_create_idempotency_keys.py +0 -0
  467. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_refresh_analytics.py +0 -0
  468. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_attachment_staging.py +0 -0
  469. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +0 -0
  470. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +0 -0
  471. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/__init__.py +0 -0
  472. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_attachment_finals.py +0 -0
  473. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +0 -0
  474. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/delete_superseded_banner_finals.py +0 -0
  475. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_account_deletion.py +0 -0
  476. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_admin_user_deletion.py +0 -0
  477. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_comment_stats.py +0 -0
  478. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_post_stats.py +0 -0
  479. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_aggregate_user_stats.py +0 -0
  480. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_attachment_asset_variants.py +0 -0
  481. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_banner_asset_variants.py +0 -0
  482. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_cache_pattern_invalidation.py +0 -0
  483. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_destructive_comment_delete.py +0 -0
  484. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_destructive_post_delete.py +0 -0
  485. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_media_asset_variants.py +0 -0
  486. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_mute_lift.py +0 -0
  487. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_outbox_row.py +0 -0
  488. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_refresh_analytics_bucket.py +0 -0
  489. {core_framework-2.3.0 → core_framework-2.3.1}/core_framework/worker/tasks/process_user_content_deletion.py +0 -0
  490. {core_framework-2.3.0 → core_framework-2.3.1}/docker-compose.dev.yaml +0 -0
  491. {core_framework-2.3.0 → core_framework-2.3.1}/docker-compose.yml +0 -0
  492. {core_framework-2.3.0 → core_framework-2.3.1}/dockerfile +0 -0
  493. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/README.md +0 -0
  494. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/deploy-playbook.md +0 -0
  495. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/edge-upload-limits.md +0 -0
  496. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/examples/Caddyfile.example +0 -0
  497. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/examples/image-server-known-hosts.example +0 -0
  498. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/app-server-deploy-ssh.md +0 -0
  499. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/image-server-ssh.md +0 -0
  500. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/postgres-setup.md +0 -0
  501. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/redis-setup.md +0 -0
  502. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/guides/ubuntu-server-setup.md +0 -0
  503. {core_framework-2.3.0 → core_framework-2.3.1}/docs/deployments/release-playbook.md +0 -0
  504. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/README.md +0 -0
  505. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/auth/access_control.md +0 -0
  506. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/auth/registration.md +0 -0
  507. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/cache/admin_cache_invalidation.md +0 -0
  508. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/admin_comments.md +0 -0
  509. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/comment_report.md +0 -0
  510. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/comment_stats_aggregation.md +0 -0
  511. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/create_comment.md +0 -0
  512. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/delete_comment.md +0 -0
  513. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/edit_comment.md +0 -0
  514. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/comments/retrieve_comments.md +0 -0
  515. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/comments.md +0 -0
  516. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/overview.md +0 -0
  517. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/deletion/posts.md +0 -0
  518. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/events/events.md +0 -0
  519. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/avatar-upload-design.md +0 -0
  520. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/banner-upload-design.md +0 -0
  521. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/upload-pipeline-design.md +0 -0
  522. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/media/upload_pipeline.md +0 -0
  523. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/mentions/mentions_in_content.md +0 -0
  524. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/appeals.md +0 -0
  525. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/internal_notes.md +0 -0
  526. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/moderator_actions.md +0 -0
  527. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/reports.md +0 -0
  528. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/moderation/restrictions.md +0 -0
  529. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/notifications/notification_inbox.md +0 -0
  530. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/outbox/admin_outbox_ops.md +0 -0
  531. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/admin_posts.md +0 -0
  532. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/author_context.md +0 -0
  533. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/hashtag_discovery.md +0 -0
  534. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_like.md +0 -0
  535. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_stats_aggregation.md +0 -0
  536. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/posts/post_visibility.md +0 -0
  537. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/account.md +0 -0
  538. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/account_deletion.md +0 -0
  539. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/avatar.md +0 -0
  540. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/banner.md +0 -0
  541. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/blocks.md +0 -0
  542. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/change_history.md +0 -0
  543. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/check_username_exists.md +0 -0
  544. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/follow-system-design.md +0 -0
  545. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/follow.md +0 -0
  546. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/my_posts_and_comments.md +0 -0
  547. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/preferences.md +0 -0
  548. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/profile.md +0 -0
  549. {core_framework-2.3.0 → core_framework-2.3.1}/docs/domains/users/public_profile.md +0 -0
  550. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/api.md +0 -0
  551. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/core-framework-migration.md +0 -0
  552. {core_framework-2.3.0 → core_framework-2.3.1}/docs/library/overview.md +0 -0
  553. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/README.md +0 -0
  554. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/analytics-rollup-design.md +0 -0
  555. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/architecture-decisions.md +0 -0
  556. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/client-error-visibility.md +0 -0
  557. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/conventions.md +0 -0
  558. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/create-idempotency-design.md +0 -0
  559. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/database-triggers.md +0 -0
  560. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/domain-services-and-adapters.md +0 -0
  561. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/event-outbox-design.md +0 -0
  562. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/events-ingest-design.md +0 -0
  563. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/layers-and-boundaries.md +0 -0
  564. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/media-storage-topology.md +0 -0
  565. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/outbox-admin-ops-design.md +0 -0
  566. {core_framework-2.3.0 → core_framework-2.3.1}/docs/platform/patch-update-typed-payload.md +0 -0
  567. {core_framework-2.3.0 → core_framework-2.3.1}/firebase_config.example.json +0 -0
  568. {core_framework-2.3.0 → core_framework-2.3.1}/makefile +0 -0
  569. {core_framework-2.3.0 → core_framework-2.3.1}/tests/__init__.py +0 -0
  570. {core_framework-2.3.0 → core_framework-2.3.1}/tests/conftest.py +0 -0
  571. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_auth.py +0 -0
  572. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_canaries.py +0 -0
  573. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_media.py +0 -0
  574. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_settings.py +0 -0
  575. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/_upload_payloads.py +0 -0
  576. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/conftest.py +0 -0
  577. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/media/pipeline_test.py +0 -0
  578. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/canary_test.py +0 -0
  579. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/media_test.py +0 -0
  580. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/system_test.py +0 -0
  581. {core_framework-2.3.0 → core_framework-2.3.1}/tests/e2e/smoke/tls_host_test.py +0 -0
  582. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/__init__.py +0 -0
  583. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/_http_error_details.py +0 -0
  584. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/__init__.py +0 -0
  585. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_auth_helpers.py +0 -0
  586. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_destructive_delete_helpers.py +0 -0
  587. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_http_helpers.py +0 -0
  588. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_user_deletion_helpers.py +0 -0
  589. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/_user_helpers.py +0 -0
  590. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/__init__.py +0 -0
  591. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/_auth_cases.py +0 -0
  592. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/analytics/__init__.py +0 -0
  593. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/analytics/router_test.py +0 -0
  594. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/cache/__init__.py +0 -0
  595. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/cache/router_test.py +0 -0
  596. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/comments/__init__.py +0 -0
  597. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/comments/router_test.py +0 -0
  598. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/__init__.py +0 -0
  599. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/moderation/_auth_cases.py +0 -0
  600. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/outbox/__init__.py +0 -0
  601. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/outbox/router_test.py +0 -0
  602. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/posts/__init__.py +0 -0
  603. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/admin/users/__init__.py +0 -0
  604. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/attachments/_helpers.py +0 -0
  605. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/attachments/attachment_upload_test.py +0 -0
  606. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/auth/__init__.py +0 -0
  607. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/auth/router_test.py +0 -0
  608. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/__init__.py +0 -0
  609. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/authenticated/__init__.py +0 -0
  610. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +0 -0
  611. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/public/__init__.py +0 -0
  612. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/comments/public/router_test.py +0 -0
  613. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/events/router_test.py +0 -0
  614. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/media/ingest_contract_test.py +0 -0
  615. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/mentions/mentions_integration_test.py +0 -0
  616. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/notifications/__init__.py +0 -0
  617. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/__init__.py +0 -0
  618. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +0 -0
  619. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -0
  620. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/followers_visibility_test.py +0 -0
  621. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/post_stats_dirty_marking_test.py +0 -0
  622. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/public/__init__.py +0 -0
  623. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/posts/public/router_test.py +0 -0
  624. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/public_read_by_id_unavailable_detail_test.py +0 -0
  625. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/system/__init__.py +0 -0
  626. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/system/router_test.py +0 -0
  627. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/__init__.py +0 -0
  628. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/__init__.py +0 -0
  629. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/avatar_upload_test.py +0 -0
  630. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/banner_upload_test.py +0 -0
  631. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/authenticated/router_test.py +0 -0
  632. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/public/__init__.py +0 -0
  633. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/api/users/public/router_test.py +0 -0
  634. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/__init__.py +0 -0
  635. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/_media_upload_helpers.py +0 -0
  636. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_comment_stats_test.py +0 -0
  637. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_post_stats_test.py +0 -0
  638. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/aggregate_user_stats_test.py +0 -0
  639. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/analytics_prune_test.py +0 -0
  640. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/analytics_refresh_test.py +0 -0
  641. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/attachment_upload_test.py +0 -0
  642. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/avatar_upload_test.py +0 -0
  643. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/banner_upload_test.py +0 -0
  644. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/conftest.py +0 -0
  645. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/mute_lift_test.py +0 -0
  646. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/user_outbox_test.py +0 -0
  647. {core_framework-2.3.0 → core_framework-2.3.1}/tests/integration/worker/utils_test.py +0 -0
  648. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/__init__.py +0 -0
  649. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/comments/authenticated/comment_request_schemas_test.py +0 -0
  650. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/dedupe_preserving_order_test.py +0 -0
  651. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/posts/authenticated/post_update_mapper_test.py +0 -0
  652. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/api/users/profile_update_mapper_test.py +0 -0
  653. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/comments/__init__.py +0 -0
  654. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/events/event_service_test.py +0 -0
  655. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/notifications/inbox_service_test.py +0 -0
  656. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/application/users/deletion_audit_test.py +0 -0
  657. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/bundled_alembic_test.py +0 -0
  658. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/migrate_cli_test.py +0 -0
  659. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/core/pagination_test.py +0 -0
  660. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/__init__.py +0 -0
  661. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/comment/__init__.py +0 -0
  662. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/post/models_test.py +0 -0
  663. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/domains/user/service_test.py +0 -0
  664. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/__init__.py +0 -0
  665. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/media/__init__.py +0 -0
  666. {core_framework-2.3.0 → core_framework-2.3.1}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +0 -0
@@ -45,3 +45,12 @@ Use explicit write/read configuration and keep schema names shared.
45
45
  - `read_postgres`
46
46
  - Domain dependencies pass `(write, read, strong)` explicitly to repositories.
47
47
  - Until a dedicated strong instance exists, use write instance for the strong argument intentionally.
48
+
49
+ ## Schema names in SQL
50
+
51
+ - Schema names come only from `settings.postgres_schemas` (see **Settings Model** above).
52
+ - Domain `dependencies.py` passes unquoted `schema=runtime.settings.postgres_schemas.schema_<domain>` into repositories (keyword-only `__init__`).
53
+ - Repositories cache `self.schema_sql = quote_postgres_identifier(schema)` and use `{self.schema_sql}.table` in f-string SQL — never hard-coded `"post".` literals.
54
+ - Outbox producer adapter is wired per domain with `schema` at construction; consumer adapter receives unquoted `schema` per call and caches quoted SQL.
55
+
56
+ Repository isolation rules (no cross-domain schema access): **`repository-schema-isolation.mdc`**.
@@ -11,10 +11,19 @@ Each domain repository may only read/write tables in **its own** Postgres schema
11
11
 
12
12
  Canonical rule: `docs/platform/layers-and-boundaries.md` — *no cross-domain schema reads, writes, joins, or foreign keys*.
13
13
 
14
+ ## Schema qualification
15
+
16
+ Repositories receive unquoted `schema` from `runtime.settings.postgres_schemas` in `dependencies.py` (keyword-only `__init__` arg). In `__init__`:
17
+
18
+ - `self.schema` — config schema name (e.g. `post`)
19
+ - `self.schema_sql` — `quote_postgres_identifier(schema)` for SQL interpolation
20
+
21
+ Use `{self.schema_sql}.table` in f-string SQL — not hard-coded `"post".` literals.
22
+
14
23
  ## Allowed in a repository
15
24
 
16
- - SQL qualified with that domain's schema only (e.g. `"post".posts` in `PostRepository`).
17
- - **Within-schema** policy gates (e.g. `insert_post_like` checks `"post".posts.status = active`).
25
+ - SQL qualified with that domain's schema only (e.g. `{self.schema_sql}.posts` in `PostRepository`).
26
+ - **Within-schema** policy gates (e.g. `insert_post_like` checks `{self.schema_sql}.posts.status = active`).
18
27
  - **Lookup mirrors** in the same schema (`user_blocks_lookup`, `user_restrictions_lookup`, `user_followers_lookup`) — synced by application flows; mirrors are not authoritative.
19
28
 
20
29
  ## Forbidden in a repository
@@ -23,18 +32,18 @@ Canonical rule: `docs/platform/layers-and-boundaries.md` — *no cross-domain sc
23
32
  - Importing another domain's `service`, `repository`, or models to enforce policy.
24
33
 
25
34
  ```python
26
- # ❌ moderation/repository.py — cross-domain EXISTS
27
- insert into "moderation".post_reports (...)
35
+ # ❌ moderation/repository.py — cross-domain EXISTS (illustrative schema literals)
36
+ insert into {moderation_schema_sql}.post_reports (...)
28
37
  select $1, $2, $3, $4
29
38
  where exists (
30
- select 1 from "post".posts
39
+ select 1 from {post_schema_sql}.posts
31
40
  where id = $2 and status = 'active'
32
41
  )
33
42
 
34
43
  # ❌ notification/repository.py — cross-domain mute gate
35
- insert into "notification".notification_mutes (...)
44
+ insert into {notification_schema_sql}.notification_mutes (...)
36
45
  select ...
37
- where exists (select 1 from "comment".comments where ...)
46
+ where exists (select 1 from {comment_schema_sql}.comments where ...)
38
47
  ```
39
48
 
40
49
  ## Alembic migrations (different convention)
@@ -69,4 +78,8 @@ Before adding a repository write that depends on another domain's row state:
69
78
 
70
79
  ## Self-check (repositories only)
71
80
 
72
- In `domains/<name>/repository.py`, every `"<schema>".` qualifier in SQL must be `<name>` (or that domain's documented mirror tables in the same schema).
81
+ In `domains/<name>/repository.py`:
82
+
83
+ - Every table/type qualifier in SQL must use `{self.schema_sql}.…` (that domain's schema only).
84
+ - Do not hard-code `"user".`, `"post".`, etc. — use `self.schema` / `self.schema_sql` from config.
85
+ - Mirror lookup tables (`user_blocks_lookup`, etc.) still live under `{self.schema_sql}` when they belong to that domain's schema.
@@ -4,6 +4,19 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.3.1] - 2026-07-03
8
+
9
+ ### Added
10
+
11
+ - **Partial admin user deletions:** `tombstone_authored_posts_only` and `tombstone_authored_comments_only` on `POST /admin/users/{user_id}/deletions` — moderator tombstone of authored posts or comments while keeping the account. See **`docs/domains/deletion/users.md`**.
12
+ - **`docs/testing.md`** — usage-focused pytest plugin guide for host adopters (wiring, fixtures, tiers, troubleshooting). Design reference remains **`docs/library/testing-plugin-design.md`**.
13
+ - **Post/comment attachment integration tests:** v1.1 create/edit coverage — best-effort attach (unknown or already-linked assets), attach before worker publish, edit-budget enforcement, clear-all patch, and tombstone finals cleanup. See **`tests/integration/api/posts/post_attachments_integration_test.py`** and **`tests/integration/api/comments/comment_attachments_integration_test.py`**.
14
+ - **Analytics rollup:** `retrieve_daily_fact_kind_totals_for_range` on `AnalyticsService` and `retrieve_analytics_kind_totals_for_range` in `application/analytics/read_service` — sum `daily_fact` counts per `kind` over an inclusive UTC day range (for host catalog and similar reads).
15
+
16
+ ### Fixed
17
+
18
+ - **Admin outbox schemas:** rename response field `schema` to `producing_schema` with JSON alias `schema` so Pydantic no longer warns about shadowing `BaseModel.schema`.
19
+
7
20
  ## [2.3.0] - 2026-07-03
8
21
 
9
22
  Analytics rollup domain (materialized daily activity counts), admin read API, and retention prune. Hosts must add **`[analytics]`** and **`schema_analytics`**, run **`cf-alembic`**, and run the worker for rollup refresh and daily-fact prune.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-framework
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Core framework package (import as core_framework)
5
5
  Project-URL: Homepage, https://github.com/NepNepFFXIV/core-framework
6
6
  Project-URL: Repository, https://github.com/NepNepFFXIV/core-framework
@@ -2,7 +2,7 @@ from datetime import datetime
2
2
  from typing import Annotated, Any
3
3
 
4
4
  from fastapi import Path, Query
5
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
7
  OutboxRowId = Annotated[
8
8
  int,
@@ -34,7 +34,9 @@ class OutboxOldestPendingRow(BaseModel):
34
34
 
35
35
 
36
36
  class OutboxSummaryResponse(BaseModel):
37
- schema: str
37
+ model_config = ConfigDict(populate_by_name=True)
38
+
39
+ producing_schema: str = Field(alias="schema")
38
40
  total_pending: int
39
41
  total_dead: int
40
42
  pending_by_event: list[OutboxEventCountItem]
@@ -43,8 +45,10 @@ class OutboxSummaryResponse(BaseModel):
43
45
 
44
46
 
45
47
  class OutboxDeadRowResponse(BaseModel):
48
+ model_config = ConfigDict(populate_by_name=True)
49
+
46
50
  id: int
47
- schema: str
51
+ producing_schema: str = Field(alias="schema")
48
52
  event_name: str
49
53
  aggregate_type: str
50
54
  aggregate_id: str
@@ -27,6 +27,31 @@ async def retrieve_analytics_daily_range(
27
27
  }
28
28
 
29
29
 
30
+ async def retrieve_analytics_kind_totals_for_range(
31
+ *,
32
+ subject_type: str,
33
+ activity_type: str,
34
+ from_day: date,
35
+ to_day: date,
36
+ kind: str | None = None,
37
+ ) -> dict[str, Any]:
38
+ """Return per-kind rollup totals summed over an inclusive UTC day range."""
39
+ totals = await analytics_deps.analytics_service.retrieve_daily_fact_kind_totals_for_range(
40
+ subject_type=subject_type,
41
+ activity_type=activity_type,
42
+ from_day=from_day,
43
+ to_day=to_day,
44
+ kind=kind,
45
+ )
46
+ return {
47
+ "subject_type": subject_type,
48
+ "activity_type": activity_type,
49
+ "from_day": from_day,
50
+ "to_day": to_day,
51
+ "items": [{"kind": total.kind, "count": total.count} for total in totals],
52
+ }
53
+
54
+
30
55
  async def retrieve_analytics_daily_day(
31
56
  *,
32
57
  subject_type: str,
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
5
5
 
6
6
 
7
7
  class CommentCreatedSource:
8
+ """Activity source for comment creation counts."""
9
+
8
10
  @property
9
11
  def subject_type(self) -> str:
12
+ """Return the analytics subject type for this source."""
13
+
10
14
  return "comment"
11
15
 
12
16
  @property
13
17
  def activity_type(self) -> str:
18
+ """Return the analytics activity type for this source."""
19
+
14
20
  return "created"
15
21
 
16
22
  async def retrieve_activity_counts_for_day(
@@ -19,6 +25,7 @@ class CommentCreatedSource:
19
25
  *,
20
26
  final: bool = False,
21
27
  ) -> list[ActivityCount]:
28
+ """Return per-kind comment created counts for one UTC day."""
22
29
  if final:
23
30
  rows = await comment_deps.comment_service.retrieve_comment_created_activity_counts_for_day_strong(day=day)
24
31
  else:
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
5
5
 
6
6
 
7
7
  class PostCreatedSource:
8
+ """Activity source for post creation counts."""
9
+
8
10
  @property
9
11
  def subject_type(self) -> str:
12
+ """Return the analytics subject type for this source."""
13
+
10
14
  return "post"
11
15
 
12
16
  @property
13
17
  def activity_type(self) -> str:
18
+ """Return the analytics activity type for this source."""
19
+
14
20
  return "created"
15
21
 
16
22
  async def retrieve_activity_counts_for_day(
@@ -19,6 +25,7 @@ class PostCreatedSource:
19
25
  *,
20
26
  final: bool = False,
21
27
  ) -> list[ActivityCount]:
28
+ """Return per-kind post created counts for one UTC day."""
22
29
  if final:
23
30
  rows = await post_deps.post_service.retrieve_post_created_activity_counts_for_day_strong(day=day)
24
31
  else:
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
5
5
 
6
6
 
7
7
  class PostViewedSource:
8
+ """Activity source for post view counts."""
9
+
8
10
  @property
9
11
  def subject_type(self) -> str:
12
+ """Return the analytics subject type for this source."""
13
+
10
14
  return "post"
11
15
 
12
16
  @property
13
17
  def activity_type(self) -> str:
18
+ """Return the analytics activity type for this source."""
19
+
14
20
  return "viewed"
15
21
 
16
22
  async def retrieve_activity_counts_for_day(
@@ -19,6 +25,7 @@ class PostViewedSource:
19
25
  *,
20
26
  final: bool = False,
21
27
  ) -> list[ActivityCount]:
28
+ """Return per-kind post viewed counts for one UTC day."""
22
29
  if final:
23
30
  rows = await post_deps.post_service.retrieve_post_viewed_activity_counts_for_day_strong(day=day)
24
31
  else:
@@ -5,12 +5,18 @@ from core_framework.domains.analytics import ActivityCount
5
5
 
6
6
 
7
7
  class UserRegisteredSource:
8
+ """Activity source for user registration counts."""
9
+
8
10
  @property
9
11
  def subject_type(self) -> str:
12
+ """Return the analytics subject type for this source."""
13
+
10
14
  return "user"
11
15
 
12
16
  @property
13
17
  def activity_type(self) -> str:
18
+ """Return the analytics activity type for this source."""
19
+
14
20
  return "registered"
15
21
 
16
22
  async def retrieve_activity_counts_for_day(
@@ -19,6 +25,7 @@ class UserRegisteredSource:
19
25
  *,
20
26
  final: bool = False,
21
27
  ) -> list[ActivityCount]:
28
+ """Return per-kind user registered counts for one UTC day."""
22
29
  if final:
23
30
  rows = await user_deps.user_service.retrieve_user_registered_activity_counts_for_day_strong(day=day)
24
31
  else:
@@ -6,5 +6,7 @@ from core_framework.domains.user import UserIdentity
6
6
 
7
7
  @dataclass(frozen=True, slots=True, kw_only=True)
8
8
  class UserDetail:
9
+ """Authenticated user identity plus moderation snapshot for access checks."""
10
+
9
11
  identity: UserIdentity
10
12
  moderation: UserModeration
@@ -5,11 +5,15 @@ from core_framework.core import CacheKey
5
5
 
6
6
  @dataclass(frozen=True, slots=True, kw_only=True)
7
7
  class CacheInvalidateTarget:
8
+ """One exact cache key invalidation target."""
9
+
8
10
  resource: CacheKey
9
11
  params: dict[str, str]
10
12
 
11
13
 
12
14
  @dataclass(frozen=True, slots=True, kw_only=True)
13
15
  class CacheInvalidatePatternTarget:
16
+ """One pattern-based cache invalidation target."""
17
+
14
18
  resource: CacheKey
15
19
  params: dict[str, str]
@@ -3,5 +3,7 @@ from dataclasses import dataclass
3
3
 
4
4
  @dataclass(frozen=True, slots=True, kw_only=True)
5
5
  class Event:
6
+ """Analytics event payload enqueued for asynchronous recording."""
7
+
6
8
  subject_type: str
7
9
  subject: str
@@ -52,6 +52,7 @@ def _serialize_attachment_variant(
52
52
 
53
53
 
54
54
  def serialize_image_attachments(*, attachment_links: Sequence[_ImageAttachmentLink]) -> dict[str, Any]:
55
+ """Serialize image attachment links into API-ready thumb and display variant payloads."""
55
56
  _, _, default_fallback_url = require_attachment_read_urls()
56
57
  sorted_attachment_links = sorted(attachment_links, key=lambda link: link.asset_id)
57
58
  return {
@@ -116,6 +116,8 @@ async def attachment_asset_has_link_row(*, asset_id: str) -> bool:
116
116
 
117
117
 
118
118
  class _InsertImageAttachmentLink(Protocol):
119
+ """Insert one image attachment link row for a content item."""
120
+
119
121
  def __call__(
120
122
  self,
121
123
  *,
@@ -123,15 +125,25 @@ class _InsertImageAttachmentLink(Protocol):
123
125
  asset_id: str,
124
126
  display_width: int | None,
125
127
  display_height: int | None,
126
- ) -> Awaitable[bool]: ...
128
+ ) -> Awaitable[bool]:
129
+ """Insert a link row and return whether a new row was created."""
130
+ ...
127
131
 
128
132
 
129
133
  class _DeleteImageAttachmentLink(Protocol):
130
- def __call__(self, *, content_id: str, asset_id: str) -> Awaitable[bool]: ...
134
+ """Delete one image attachment link row for a content item."""
135
+
136
+ def __call__(self, *, content_id: str, asset_id: str) -> Awaitable[bool]:
137
+ """Delete a link row and return whether a row was removed."""
138
+ ...
131
139
 
132
140
 
133
141
  class _SelectImageAttachmentAssetIds(Protocol):
134
- def __call__(self, *, content_id: str) -> Awaitable[list[str]]: ...
142
+ """List image attachment asset ids linked to a content item."""
143
+
144
+ def __call__(self, *, content_id: str) -> Awaitable[list[str]]:
145
+ """Return asset ids currently linked to the content item."""
146
+ ...
135
147
 
136
148
 
137
149
  @dataclass(frozen=True)
@@ -12,6 +12,7 @@ _attachment_default_fallback_url: str | None = None
12
12
 
13
13
 
14
14
  def configure_media_read_urls(*, settings: Settings) -> None:
15
+ """Load avatar, banner, and attachment public read URL settings from bootstrap config."""
15
16
  global _avatar_default_url, _avatar_public_base_url, _avatar_extension
16
17
  global _banner_default_url, _banner_public_base_url, _banner_extension
17
18
  global _attachment_public_base_url, _attachment_extension, _attachment_default_fallback_url
@@ -27,6 +28,7 @@ def configure_media_read_urls(*, settings: Settings) -> None:
27
28
 
28
29
 
29
30
  def require_avatar_read_urls() -> tuple[str, str, str]:
31
+ """Return configured avatar default URL, public base URL, and file extension."""
30
32
  if _avatar_default_url is None or _avatar_public_base_url is None or _avatar_extension is None:
31
33
  raise RuntimeError(
32
34
  "Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
@@ -35,6 +37,7 @@ def require_avatar_read_urls() -> tuple[str, str, str]:
35
37
 
36
38
 
37
39
  def require_banner_read_urls() -> tuple[str, str, str]:
40
+ """Return configured banner default URL, public base URL, and file extension."""
38
41
  if _banner_default_url is None or _banner_public_base_url is None or _banner_extension is None:
39
42
  raise RuntimeError(
40
43
  "Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
@@ -43,6 +46,7 @@ def require_banner_read_urls() -> tuple[str, str, str]:
43
46
 
44
47
 
45
48
  def require_attachment_read_urls() -> tuple[str, str, str]:
49
+ """Return configured attachment public base URL, file extension, and default fallback URL."""
46
50
  if _attachment_public_base_url is None or _attachment_extension is None or _attachment_default_fallback_url is None:
47
51
  raise RuntimeError(
48
52
  "Media read URLs are not configured. Call configure_media_read_urls() during application bootstrap."
@@ -2,6 +2,8 @@ from enum import StrEnum
2
2
 
3
3
 
4
4
  class NotificationInboxListItemType(StrEnum):
5
+ """Notification kinds surfaced in the authenticated inbox list."""
6
+
5
7
  COMMENT_ON_POST = "comment_on_post"
6
8
  REPLY_TO_COMMENT = "reply_to_comment"
7
9
  MENTION_IN_POST = "mention_in_post"
@@ -9,6 +9,8 @@ USER_BLOCK_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "user.block"
9
9
 
10
10
 
11
11
  class UserBlockRelationshipChangedPayload(TypedDict):
12
+ """Outbox payload for a user block relationship change."""
13
+
12
14
  blocker_id: str
13
15
  blocked_id: str
14
16
 
@@ -24,6 +26,7 @@ def build_user_block_relationship_changed_enqueue(
24
26
  blocked_id: str,
25
27
  commit_token: str,
26
28
  ) -> OutboxEnqueue:
29
+ """Build an outbox enqueue for a user block relationship change."""
27
30
  aggregate_id = aggregate_id_for_user_block(blocker_id=blocker_id, blocked_id=blocked_id)
28
31
  payload: UserBlockRelationshipChangedPayload = {
29
32
  "blocker_id": blocker_id,
@@ -46,6 +49,8 @@ USER_FOLLOW_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "user.follow"
46
49
 
47
50
 
48
51
  class UserFollowRelationshipChangedPayload(TypedDict):
52
+ """Outbox payload for a user follow relationship change."""
53
+
49
54
  follower_id: str
50
55
  followee_id: str
51
56
 
@@ -61,6 +66,7 @@ def build_user_follow_relationship_changed_enqueue(
61
66
  followee_id: str,
62
67
  commit_token: str,
63
68
  ) -> OutboxEnqueue:
69
+ """Build an outbox enqueue for a user follow relationship change."""
64
70
  aggregate_id = aggregate_id_for_user_follow(follower_id=follower_id, followee_id=followee_id)
65
71
  payload: UserFollowRelationshipChangedPayload = {
66
72
  "follower_id": follower_id,
@@ -83,6 +89,8 @@ MODERATION_RESTRICTION_MIRROR_ORDERING_LOCK_PREFIX: Final[str] = "moderation.res
83
89
 
84
90
 
85
91
  class ModerationRestrictionRelationshipChangedPayload(TypedDict):
92
+ """Outbox payload for a moderation restriction relationship change."""
93
+
86
94
  user_id: str
87
95
 
88
96
 
@@ -96,6 +104,7 @@ def build_moderation_restriction_relationship_changed_enqueue(
96
104
  user_id: str,
97
105
  commit_token: str,
98
106
  ) -> OutboxEnqueue:
107
+ """Build an outbox enqueue for a moderation restriction relationship change."""
99
108
  payload: ModerationRestrictionRelationshipChangedPayload = {
100
109
  "user_id": user_id,
101
110
  }
@@ -2,16 +2,22 @@ from enum import StrEnum
2
2
 
3
3
 
4
4
  class EventType(StrEnum):
5
+ """Analytics event kinds recorded for subject activity."""
6
+
5
7
  LOGIN = "login"
6
8
  VIEW = "view"
7
9
 
8
10
 
9
11
  class SubjectType(StrEnum):
12
+ """Analytics subject kinds aggregated in daily facts."""
13
+
10
14
  POST = "post"
11
15
  USER = "user"
12
16
 
13
17
 
14
18
  class WorkerJobName(StrEnum):
19
+ """Registered ARQ worker job names."""
20
+
15
21
  PROCESS_ACCOUNT_DELETION = "process_account_deletion"
16
22
  PROCESS_USER_CONTENT_DELETION = "process_user_content_deletion"
17
23
  PROCESS_ADMIN_USER_DELETION = "process_admin_user_deletion"
@@ -1,58 +1,78 @@
1
1
  class UnauthorizedException(Exception):
2
+ """Signal that the caller lacks valid authentication."""
3
+
2
4
  def __init__(self, message: str = "Unauthorized") -> None:
3
5
  self.message = message
4
6
  super().__init__(self.message)
5
7
 
6
8
 
7
9
  class ForbiddenException(Exception):
10
+ """Signal that the caller is authenticated but not permitted."""
11
+
8
12
  def __init__(self, message: str = "Forbidden") -> None:
9
13
  self.message = message
10
14
  super().__init__(self.message)
11
15
 
12
16
 
13
17
  class UserNotFoundException(Exception):
18
+ """Signal that the requested user does not exist or is not visible."""
19
+
14
20
  def __init__(self, message: str = "User not found") -> None:
15
21
  self.message = message
16
22
  super().__init__(self.message)
17
23
 
18
24
 
19
25
  class ContentNotFoundException(Exception):
26
+ """Signal that the requested content does not exist or is not visible."""
27
+
20
28
  def __init__(self, message: str = "Content not found") -> None:
21
29
  self.message = message
22
30
  super().__init__(self.message)
23
31
 
24
32
 
25
33
  class BadRequestException(Exception):
34
+ """Signal a caller mistake that should map to HTTP 400."""
35
+
26
36
  def __init__(self, message: str = "Bad request") -> None:
27
37
  self.message = message
28
38
  super().__init__(self.message)
29
39
 
30
40
 
31
41
  class ConflictException(Exception):
42
+ """Signal a state conflict that should map to HTTP 409."""
43
+
32
44
  def __init__(self, message: str = "Conflict") -> None:
33
45
  self.message = message
34
46
  super().__init__(self.message)
35
47
 
36
48
 
37
49
  class IngestBodyTooLargeException(Exception):
50
+ """Signal that an ingest payload exceeds the configured size limit."""
51
+
38
52
  def __init__(self, message: str = "Ingest body too large") -> None:
39
53
  self.message = message
40
54
  super().__init__(self.message)
41
55
 
42
56
 
43
57
  class IngestUnsupportedMediaTypeException(Exception):
58
+ """Signal that an ingest Content-Type is not allowed."""
59
+
44
60
  def __init__(self, message: str = "Ingest unsupported media type") -> None:
45
61
  self.message = message
46
62
  super().__init__(self.message)
47
63
 
48
64
 
49
65
  class AppealAlreadyDecidedException(Exception):
66
+ """Signal that a moderation appeal was already decided."""
67
+
50
68
  def __init__(self, message: str = "Appeal already decided") -> None:
51
69
  self.message = message
52
70
  super().__init__(self.message)
53
71
 
54
72
 
55
73
  class InvariantViolationException(Exception):
74
+ """Signal an internal invariant breach that should map to HTTP 500."""
75
+
56
76
  def __init__(self, message: str = "Invariant violation") -> None:
57
77
  self.message = message
58
78
  super().__init__(self.message)
@@ -3,6 +3,7 @@ from core_framework.domains.user import UserIdentity
3
3
 
4
4
 
5
5
  def username_for_audit_from_identity(*, identity: UserIdentity) -> str | None:
6
+ """Return a username for deletion audit logs, or ``None`` for the default identity."""
6
7
  return identity.username if identity != UserIdentity.DEFAULT else None
7
8
 
8
9
 
@@ -2,5 +2,9 @@ from enum import StrEnum
2
2
 
3
3
 
4
4
  class AdminUserDeletionType(StrEnum):
5
+ """Admin-initiated user deletion strategies."""
6
+
5
7
  REMOVE_ACCOUNT_TOMBSTONE_AUTHORED_CONTENT = "remove_account_tombstone_authored_content"
6
8
  REMOVE_ACCOUNT_DELETE_AUTHORED_CONTENT = "remove_account_delete_authored_content"
9
+ TOMBSTONE_AUTHORED_POSTS_ONLY = "tombstone_authored_posts_only"
10
+ TOMBSTONE_AUTHORED_COMMENTS_ONLY = "tombstone_authored_comments_only"
@@ -145,14 +145,25 @@ async def _run_remove_account_delete_authored_content(*, target_user_id: str) ->
145
145
  await _remove_user(target_user_id=target_user_id, preserve_authored_content=False)
146
146
 
147
147
 
148
- async def _tombstone_moderator_authored_content_for_user(*, user_id: str) -> None:
149
- """Tombstone active authored posts and comments as ``tombstoned_by_moderator`` without per-item audit."""
148
+ async def _run_tombstone_authored_posts_only(*, target_user_id: str) -> None:
149
+ await _tombstone_moderator_authored_posts_for_user(user_id=target_user_id)
150
+
151
+
152
+ async def _run_tombstone_authored_comments_only(*, target_user_id: str) -> None:
153
+ await _tombstone_moderator_authored_comments_for_user(user_id=target_user_id)
154
+
155
+
156
+ async def _tombstone_moderator_authored_posts_for_user(*, user_id: str) -> None:
157
+ """Tombstone active authored posts as ``tombstoned_by_moderator`` without per-item audit."""
150
158
  post_impact = await post_deps.post_service.tombstone_posts_by_author_id(
151
159
  author_id=user_id,
152
160
  tombstone_status=PostStatus.TOMBSTONED_BY_MODERATOR,
153
161
  )
154
162
  await finalize_author_posts_tombstone_cleanup(impact=post_impact)
155
163
 
164
+
165
+ async def _tombstone_moderator_authored_comments_for_user(*, user_id: str) -> None:
166
+ """Tombstone active authored comments as ``tombstoned_by_moderator`` without per-item audit."""
156
167
  comment_impact = await comment_deps.comment_service.tombstone_comments_by_author_id(
157
168
  author_id=user_id,
158
169
  tombstone_status=CommentStatus.TOMBSTONED_BY_MODERATOR,
@@ -164,6 +175,12 @@ async def _tombstone_moderator_authored_content_for_user(*, user_id: str) -> Non
164
175
  )
165
176
 
166
177
 
178
+ async def _tombstone_moderator_authored_content_for_user(*, user_id: str) -> None:
179
+ """Tombstone active authored posts and comments as ``tombstoned_by_moderator`` without per-item audit."""
180
+ await _tombstone_moderator_authored_posts_for_user(user_id=user_id)
181
+ await _tombstone_moderator_authored_comments_for_user(user_id=user_id)
182
+
183
+
167
184
  async def _destructive_authored_content_purge(*, author_id: str) -> None:
168
185
  """Destructively remove all posts and remaining comments authored by ``author_id``."""
169
186
  authored_post_ids = frozenset(
@@ -216,6 +233,8 @@ async def _mark_stats_dirty_for_author_comment_impacts(
216
233
  _ADMIN_USER_DELETION_STRATEGIES: dict[AdminUserDeletionType, AdminUserDeletionRunner] = {
217
234
  AdminUserDeletionType.REMOVE_ACCOUNT_TOMBSTONE_AUTHORED_CONTENT: _run_remove_account_tombstone_authored_content,
218
235
  AdminUserDeletionType.REMOVE_ACCOUNT_DELETE_AUTHORED_CONTENT: _run_remove_account_delete_authored_content,
236
+ AdminUserDeletionType.TOMBSTONE_AUTHORED_POSTS_ONLY: _run_tombstone_authored_posts_only,
237
+ AdminUserDeletionType.TOMBSTONE_AUTHORED_COMMENTS_ONLY: _run_tombstone_authored_comments_only,
219
238
  }
220
239
 
221
240
 
@@ -14,6 +14,11 @@ DB_NOT_CONNECTED_MSG: Final[str] = "Database is not connected"
14
14
  DB_ALREADY_CONNECTED_MSG: Final[str] = "Database is already connected"
15
15
 
16
16
 
17
+ def quote_postgres_identifier(identifier: str) -> str:
18
+ """Return a double-quoted Postgres identifier (schema, table, or column name)."""
19
+ return f'"{identifier.replace('"', '""')}"'
20
+
21
+
17
22
  class Postgres:
18
23
  __slots__ = ("_pool", "_database_url", "_min_connections", "_max_connections")
19
24
 
@@ -1,6 +1,6 @@
1
1
  from core_framework.domains.analytics.constants import DAILY_FACT_RETENTION_DAYS
2
2
  from core_framework.domains.analytics.exceptions import BaseAnalyticsException
3
- from core_framework.domains.analytics.models import DailyFactBucket, DailyFactDayTotal
3
+ from core_framework.domains.analytics.models import DailyFactBucket, DailyFactDayTotal, DailyFactKindTotal
4
4
  from core_framework.domains.analytics.ports.activity_source import ActivityCount, ActivitySourcePort
5
5
 
6
6
  __all__ = [
@@ -10,4 +10,5 @@ __all__ = [
10
10
  "DAILY_FACT_RETENTION_DAYS",
11
11
  "DailyFactBucket",
12
12
  "DailyFactDayTotal",
13
+ "DailyFactKindTotal",
13
14
  ]