core-framework 1.6.0__tar.gz → 1.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/api-layer.mdc +1 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/api-reference-docs.mdc +5 -5
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/application-layer.mdc +4 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/database-triggers.md +4 -4
- core_framework-1.8.0/.cursor/rules/docstrings.mdc +81 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-services-and-adapters.mdc +5 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/flow-documentation.mdc +4 -4
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/henry-cursor-rules-sync.mdc +5 -6
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/implementation-workflow.mdc +1 -1
- core_framework-1.8.0/.cursor/rules/karpathy-guidelines.mdc +70 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/skills/add-domain/SKILL.md +2 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/skills/code-review/SKILL.md +7 -6
- {core_framework-1.6.0 → core_framework-1.8.0}/.github/workflows/_deploy.yml +7 -7
- {core_framework-1.6.0 → core_framework-1.8.0}/.gitignore +1 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/CHANGELOG.md +66 -25
- {core_framework-1.6.0 → core_framework-1.8.0}/PKG-INFO +4 -3
- {core_framework-1.6.0 → core_framework-1.8.0}/README.md +2 -2
- core_framework-1.8.0/alembic/comment/alembic/versions/comment_add_comment_mentions.py +36 -0
- core_framework-1.8.0/alembic/media/alembic/versions/media_add_banner_staging_and_lease.py +43 -0
- core_framework-1.8.0/alembic/post/alembic/versions/post_add_post_mentions.py +36 -0
- core_framework-1.8.0/alembic/user/alembic/versions/user_add_banner_ingest_sequences.py +34 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/config.toml +11 -4
- {core_framework-1.6.0 → core_framework-1.8.0}/config.toml.template +5 -1
- core_framework-1.8.0/core_framework/api/admin/cache/router.py +32 -0
- core_framework-1.8.0/core_framework/api/admin/cache/schemas.py +95 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/router.py +2 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/users/schemas.py +2 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/authenticated/mappers.py +11 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/authenticated/schemas.py +8 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/public/schemas.py +1 -0
- core_framework-1.8.0/core_framework/api/posts/authenticated/mappers.py +28 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/authenticated/schemas.py +8 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/public/schemas.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/authenticated/router.py +62 -5
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/authenticated/schemas.py +7 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/mappers.py +0 -20
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/public/router.py +13 -3
- core_framework-1.8.0/core_framework/api/users/public/schemas.py +33 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/shared/schemas.py +15 -6
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/auth/access_service.py +6 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/auth/auth_service.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/bootstrap.py +1 -0
- core_framework-1.8.0/core_framework/application/cache/invalidate_service.py +59 -0
- core_framework-1.8.0/core_framework/application/cache/models.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/comments/admin_service.py +20 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/comments/aggregation_service.py +7 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/comments/authenticated_service.py +30 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/comments/public_service.py +90 -37
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/events/event_service.py +13 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/events/event_token.py +3 -0
- core_framework-1.8.0/core_framework/application/media/README.md +17 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/media/avatar_service.py +33 -0
- core_framework-1.8.0/core_framework/application/media/banner_service.py +150 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/appeal_service.py +8 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/moderator_service.py +6 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/report_service.py +7 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/scheduled_service.py +5 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/user_service.py +35 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/notifications/README.md +2 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/notifications/inbox_service.py +9 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/notifications/mute_service.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/notifications/notification_service.py +9 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/posts/admin_service.py +19 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/posts/aggregation_service.py +7 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/posts/authenticated_service.py +16 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/posts/public_service.py +108 -9
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/shared/enums.py +3 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/shared/user_agent.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/shared/worker_jobs.py +2 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/users/admin_service.py +53 -3
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/users/aggregation_service.py +3 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/users/authenticated_service.py +57 -5
- core_framework-1.8.0/core_framework/application/users/public_service.py +155 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/users/scheduled_service.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/cache.py +22 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/media.py +40 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/settings.py +25 -9
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/README.md +23 -6
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/constants.py +2 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/dependencies.py +27 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/models.py +32 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/repository.py +461 -7
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/service.py +293 -3
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/README.md +7 -4
- core_framework-1.8.0/core_framework/domains/media/__init__.py +59 -0
- core_framework-1.8.0/core_framework/domains/media/avatar/components/finals_publisher.py +39 -0
- core_framework-1.8.0/core_framework/domains/media/avatar/components/staging.py +121 -0
- core_framework-1.8.0/core_framework/domains/media/avatar/components/variant_encoder.py +39 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/constants.py +2 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/exceptions.py +5 -1
- core_framework-1.8.0/core_framework/domains/media/avatar/ports/finals_publisher.py +30 -0
- core_framework-1.8.0/core_framework/domains/media/avatar/ports/staging.py +41 -0
- core_framework-1.8.0/core_framework/domains/media/avatar/ports/variant_encoder.py +19 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/service.py +136 -0
- core_framework-1.8.0/core_framework/domains/media/banner/components/finals_publisher.py +25 -0
- core_framework-1.8.0/core_framework/domains/media/banner/components/staging.py +91 -0
- core_framework-1.8.0/core_framework/domains/media/banner/components/variant_encoder.py +32 -0
- core_framework-1.8.0/core_framework/domains/media/banner/constants.py +28 -0
- core_framework-1.8.0/core_framework/domains/media/banner/exceptions.py +30 -0
- core_framework-1.8.0/core_framework/domains/media/banner/models.py +23 -0
- core_framework-1.8.0/core_framework/domains/media/banner/ports/finals_publisher.py +29 -0
- core_framework-1.8.0/core_framework/domains/media/banner/ports/staging.py +41 -0
- core_framework-1.8.0/core_framework/domains/media/banner/ports/variant_encoder.py +19 -0
- core_framework-1.8.0/core_framework/domains/media/banner/service.py +293 -0
- core_framework-1.8.0/core_framework/domains/media/dependencies.py +236 -0
- core_framework-1.8.0/core_framework/domains/media/shared/constants.py +4 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/shared/exceptions.py +4 -0
- core_framework-1.8.0/core_framework/domains/media/shared/repository.py +521 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/shared/utils.py +23 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/README.md +1 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/dependencies.py +27 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/repository.py +469 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/service.py +318 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/README.md +3 -3
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/dependencies.py +27 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/repository.py +163 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/service.py +93 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/README.md +15 -11
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/constants.py +1 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/dependencies.py +27 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/models.py +37 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/repository.py +443 -11
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/service.py +266 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/README.md +1 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/__init__.py +2 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/dependencies.py +27 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/models.py +75 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/repository.py +576 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/service.py +408 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/utils.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/utils.py +81 -0
- core_framework-1.8.0/core_framework/infrastructure/media/local_banner_staging_adapter.py +89 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/infrastructure/media/local_staging_adapter.py +36 -0
- core_framework-1.8.0/core_framework/infrastructure/media/pillow_avatar_variant_encoder_adapter.py +50 -0
- core_framework-1.8.0/core_framework/infrastructure/media/pillow_banner_variant_encoder_adapter.py +33 -0
- core_framework-1.8.0/core_framework/infrastructure/media/pillow_staging_image.py +72 -0
- core_framework-1.8.0/core_framework/infrastructure/media/ssh_banner_finals_publisher_adapter.py +101 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/infrastructure/media/ssh_finals_publisher_adapter.py +26 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/arq.py +13 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/auth.py +73 -0
- core_framework-1.8.0/core_framework/testing/config.py +44 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/containers.py +18 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/firebase.py +19 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/httpx_test_client.py +11 -0
- core_framework-1.8.0/core_framework/testing/media.py +197 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/plugin.py +39 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/__init__.py +10 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_aggregate_comment_stats.py +16 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_aggregate_post_stats.py +16 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_aggregate_user_stats.py +16 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_expired_account_deletions.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_expired_mute_lifts.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/schedules/schedule_sweep_stale_avatar_staging.py +12 -0
- core_framework-1.8.0/core_framework/worker/schedules/schedule_sweep_stale_banner_staging.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/__init__.py +6 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/delete_superseded_avatar_finals.py +12 -0
- core_framework-1.8.0/core_framework/worker/tasks/delete_superseded_banner_finals.py +17 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/process_account_deletion.py +14 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/process_aggregate_comment_stats.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/process_aggregate_post_stats.py +15 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/process_aggregate_user_stats.py +15 -0
- core_framework-1.6.0/core_framework/worker/tasks/process_media_asset_variants.py → core_framework-1.8.0/core_framework/worker/tasks/process_banner_asset_variants.py +6 -5
- core_framework-1.8.0/core_framework/worker/tasks/process_cache_pattern_invalidation.py +26 -0
- core_framework-1.8.0/core_framework/worker/tasks/process_media_asset_variants.py +46 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/tasks/process_mute_lift.py +13 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/docker-compose.yml +2 -2
- core_framework-1.8.0/docs/README.md +28 -0
- core_framework-1.8.0/docs/deployments/README.md +32 -0
- core_framework-1.8.0/docs/deployments/deploy-playbook.md +139 -0
- {core_framework-1.6.0/docs/deployment → core_framework-1.8.0/docs/deployments}/edge-upload-limits.md +14 -12
- {core_framework-1.6.0/docs/deployment → core_framework-1.8.0/docs/deployments/examples}/Caddyfile.example +14 -2
- core_framework-1.8.0/docs/deployments/guides/app-server-deploy-ssh.md +50 -0
- core_framework-1.8.0/docs/deployments/guides/image-server-ssh.md +57 -0
- core_framework-1.8.0/docs/deployments/guides/postgres-setup.md +153 -0
- core_framework-1.8.0/docs/deployments/guides/redis-setup.md +109 -0
- core_framework-1.8.0/docs/deployments/guides/ubuntu-server-setup.md +173 -0
- core_framework-1.8.0/docs/deployments/release-playbook.md +84 -0
- core_framework-1.8.0/docs/domains/README.md +16 -0
- core_framework-1.8.0/docs/domains/cache/admin_cache_invalidation.md +221 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/admin_comments.md +2 -1
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/comment_report.md +1 -1
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/create_comment.md +21 -6
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/edit_comment.md +12 -8
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/retrieve_comments.md +6 -6
- core_framework-1.8.0/docs/domains/media/avatar-upload-design.md +110 -0
- core_framework-1.8.0/docs/domains/media/banner-upload-design.md +150 -0
- core_framework-1.6.0/docs/media-upload-pipeline-design.md → core_framework-1.8.0/docs/domains/media/upload-pipeline-design.md +41 -36
- core_framework-1.8.0/docs/domains/media/upload_pipeline.md +60 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/mentions/mentions_in_content.md +79 -19
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/moderation/reports.md +1 -1
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/notifications/notification_inbox.md +8 -8
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/admin_posts.md +1 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/author_context.md +8 -6
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/hashtag_discovery.md +2 -2
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/post_visibility.md +1 -1
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/avatar.md +7 -7
- core_framework-1.8.0/docs/domains/users/banner.md +79 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/domains/users}/follow-system-design.md +28 -27
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/follow.md +3 -3
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/my_posts_and_comments.md +7 -7
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/profile.md +72 -11
- core_framework-1.8.0/docs/domains/users/public_profile.md +97 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/user_removal.md +2 -2
- core_framework-1.8.0/docs/library/README.md +11 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/library}/api.md +9 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/library}/core-framework-migration.md +11 -11
- core_framework-1.8.0/docs/library/overview.md +49 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/library}/package-api.md +8 -8
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/library}/testing-plugin-design.md +2 -2
- core_framework-1.8.0/docs/platform/README.md +13 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/platform}/architecture-decisions.md +9 -9
- core_framework-1.8.0/docs/platform/conventions.md +75 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/platform}/database-triggers.md +1 -1
- core_framework-1.8.0/docs/platform/domain-services-and-adapters.md +93 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/platform}/event-outbox-design.md +45 -45
- core_framework-1.8.0/docs/platform/layers-and-boundaries.md +46 -0
- {core_framework-1.6.0/docs → core_framework-1.8.0/docs/platform}/patch-update-typed-payload.md +6 -4
- {core_framework-1.6.0 → core_framework-1.8.0}/docs/todo.md +1 -2
- {core_framework-1.6.0 → core_framework-1.8.0}/pyproject.toml +2 -1
- core_framework-1.8.0/tests/integration/api/admin/cache/router_test.py +357 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/admin/users/router_test.py +4 -1
- core_framework-1.8.0/tests/integration/api/mentions/mentions_integration_test.py +348 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/users/authenticated/avatar_upload_test.py +35 -0
- core_framework-1.8.0/tests/integration/api/users/authenticated/banner_upload_test.py +200 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/users/authenticated/router_test.py +115 -6
- core_framework-1.8.0/tests/integration/api/users/public/router_test.py +331 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/avatar_upload_test.py +67 -2
- core_framework-1.8.0/tests/integration/worker/banner_upload_test.py +229 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/utils_test.py +14 -1
- core_framework-1.8.0/tests/unit/infrastructure/media/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/uv.lock +28 -1
- core_framework-1.6.0/.cursor/rules/no-docstrings.mdc +0 -13
- core_framework-1.6.0/core_framework/api/posts/authenticated/mappers.py +0 -14
- core_framework-1.6.0/core_framework/api/users/public/schemas.py +0 -7
- core_framework-1.6.0/core_framework/application/media/README.md +0 -11
- core_framework-1.6.0/core_framework/application/users/public_service.py +0 -8
- core_framework-1.6.0/core_framework/domains/media/__init__.py +0 -30
- core_framework-1.6.0/core_framework/domains/media/avatar/components/finals_publisher.py +0 -16
- core_framework-1.6.0/core_framework/domains/media/avatar/components/staging.py +0 -51
- core_framework-1.6.0/core_framework/domains/media/avatar/components/variant_encoder.py +0 -15
- core_framework-1.6.0/core_framework/domains/media/avatar/ports/finals_publisher.py +0 -7
- core_framework-1.6.0/core_framework/domains/media/avatar/ports/staging.py +0 -10
- core_framework-1.6.0/core_framework/domains/media/avatar/ports/variant_encoder.py +0 -7
- core_framework-1.6.0/core_framework/domains/media/dependencies.py +0 -82
- core_framework-1.6.0/core_framework/domains/media/shared/repository.py +0 -179
- core_framework-1.6.0/core_framework/infrastructure/media/pillow_variant_encoder_adapter.py +0 -45
- core_framework-1.6.0/core_framework/testing/config.py +0 -28
- core_framework-1.6.0/core_framework/testing/media.py +0 -81
- core_framework-1.6.0/docs/README.md +0 -22
- core_framework-1.6.0/docs/architecture.md +0 -137
- core_framework-1.6.0/docs/conventions.md +0 -173
- core_framework-1.6.0/docs/deployment/image-server-ssh.md +0 -84
- core_framework-1.6.0/docs/domain-services-and-adapters.md +0 -179
- core_framework-1.6.0/docs/flows/media/upload_pipeline.md +0 -37
- core_framework-1.6.0/tests/integration/api/users/public/router_test.py +0 -49
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/api-security.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/api-validation.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/code-review-output.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/constants-final.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-caller-context.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-imports.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-input-guards.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-repository-exceptions.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/exception-handlers.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/integration-test-strategy.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/layer-boundaries.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/no-code-in-docs.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/postgres-config-conventions.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/repository-read-consistency.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/strong-read-opt-in.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/structured-logging.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/tech-stack.mdc +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/skills/add-config/SKILL.md +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.cursor/skills/recommend-features/SKILL.md +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.dockerignore +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.github/workflows/dev-ci-cd.yaml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.github/workflows/manual-deployment.yaml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.github/workflows/publish-pypi.yml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.github/workflows/test.yaml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.pre-commit-config.yaml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/.python-version +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/LICENSE +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/comment/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/comment/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/comment/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/comment/alembic/versions/v1_comment_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/comment/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/extension/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/extension/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/extension/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/extension/alembic/versions/v1_ext_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/extension/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/media/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/media/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/media/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/media/alembic/versions/v1_media_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/media/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/moderation/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/moderation/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/moderation/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/moderation/alembic/versions/v1_mod_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/moderation/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/notification/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/notification/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/notification/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/notification/alembic/versions/v1_notif_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/notification/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/post/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/post/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/post/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/post/alembic/versions/v1_post_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/post/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/README +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/env.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/script.py.mako +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/versions/user_add_avatar_ingest_sequences.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/versions/user_add_date_of_birth_to_profiles.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic/versions/v1_user_init_baseline.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/alembic/user/alembic.ini +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/comments/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/comments/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/moderation/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/moderation/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/moderation/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/posts/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/posts/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/users/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/admin/users/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/auth/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/auth/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/auth/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/authenticated/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/public/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/comments/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/constants.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/dependencies.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/events/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/events/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/notifications/authenticated/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/notifications/authenticated/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/notifications/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/authenticated/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/public/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/posts/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/schemas.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/system/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/system/router.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/authenticated/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/authenticated/mappers.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/public/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/api/users/router.py +1 -1
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/auth/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/auth/models.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/events/README.md +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/events/models.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/moderation/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/notifications/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/shared/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/shared/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/application/users/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/asgi.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/bundled_alembic.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/constants.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/context.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/database.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/comment.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/common.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/moderation.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/notification.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/post.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/setup.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/exception_handlers/user.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/firebase.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/http_client.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/logging.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/middleware.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/observability.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/pagination.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/redis.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/core/runtime.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/comment/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/components/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/models.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/avatar/ports/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/shared/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/media/shared/service.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/moderation/models.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/notification/models.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/post/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/constants.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/enums.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/domains/user/exceptions.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/infrastructure/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/infrastructure/media/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/main.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/migrate_cli.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/hookspecs.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/testing/migrations.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/main.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/core_framework/worker/worker_context.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/docker-compose.dev.yaml +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/dockerfile +0 -0
- {core_framework-1.6.0/docs/deployment → core_framework-1.8.0/docs/deployments/examples}/image-server-known-hosts.example +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/auth/access_control.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/auth/registration.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/comment_stats_aggregation.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/comments/delete_comment.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/events/events.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/moderation/appeals.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/moderation/internal_notes.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/moderation/moderator_actions.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/moderation/restrictions.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/post_like.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/posts/post_stats_aggregation.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/account.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/account_deletion.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/blocks.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/change_history.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/check_username_exists.md +0 -0
- {core_framework-1.6.0/docs/flows → core_framework-1.8.0/docs/domains}/users/preferences.md +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/firebase_config.example.json +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/makefile +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/conftest.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/_http_helpers.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/admin/__init__.py +0 -0
- {core_framework-1.6.0/tests/integration/api/admin/comments → core_framework-1.8.0/tests/integration/api/admin/cache}/__init__.py +0 -0
- {core_framework-1.6.0/tests/integration/api/admin/moderation → core_framework-1.8.0/tests/integration/api/admin/comments}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/admin/comments/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/admin/posts → core_framework-1.8.0/tests/integration/api/admin/moderation}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/admin/moderation/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/admin/users → core_framework-1.8.0/tests/integration/api/admin/posts}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/admin/posts/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/auth → core_framework-1.8.0/tests/integration/api/admin/users}/__init__.py +0 -0
- {core_framework-1.6.0/tests/integration/api/comments → core_framework-1.8.0/tests/integration/api/auth}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/auth/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/comments/public → core_framework-1.8.0/tests/integration/api/comments}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/comments/authenticated/comment_writes_integration_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/notifications → core_framework-1.8.0/tests/integration/api/comments/public}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/comments/public/router_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/events/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/posts → core_framework-1.8.0/tests/integration/api/notifications}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/notifications/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/posts/public → core_framework-1.8.0/tests/integration/api/posts}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/posts/authenticated/post_writes_integration_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/posts/comment_count_aggregation_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/posts/followers_visibility_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/posts/post_stats_dirty_marking_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/system → core_framework-1.8.0/tests/integration/api/posts/public}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/posts/public/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/users → core_framework-1.8.0/tests/integration/api/system}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/api/system/router_test.py +0 -0
- {core_framework-1.6.0/tests/integration/api/users/authenticated → core_framework-1.8.0/tests/integration/api/users}/__init__.py +0 -0
- {core_framework-1.6.0/tests/integration/api/users/public → core_framework-1.8.0/tests/integration/api/users/authenticated}/__init__.py +0 -0
- {core_framework-1.6.0/tests/integration/worker → core_framework-1.8.0/tests/integration/api/users/public}/__init__.py +0 -0
- {core_framework-1.6.0/tests/unit → core_framework-1.8.0/tests/integration/worker}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/account_deletion_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/aggregate_comment_stats_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/aggregate_post_stats_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/aggregate_user_stats_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/conftest.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/integration/worker/mute_lift_test.py +0 -0
- {core_framework-1.6.0/tests/unit/application/comments → core_framework-1.8.0/tests/unit}/__init__.py +0 -0
- {core_framework-1.6.0/tests/unit/domains → core_framework-1.8.0/tests/unit/application/comments}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/application/events/event_service_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/application/notifications/inbox_service_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/core/bundled_alembic_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/core/migrate_cli_test.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/core/pagination_test.py +0 -0
- {core_framework-1.6.0/tests/unit/domains/comment → core_framework-1.8.0/tests/unit/domains}/__init__.py +0 -0
- {core_framework-1.6.0/tests/unit/infrastructure → core_framework-1.8.0/tests/unit/domains/comment}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/domains/user/service_test.py +0 -0
- {core_framework-1.6.0/tests/unit/infrastructure/media → core_framework-1.8.0/tests/unit/infrastructure}/__init__.py +0 -0
- {core_framework-1.6.0 → core_framework-1.8.0}/tests/unit/infrastructure/media/ssh_finals_publisher_adapter_test.py +0 -0
|
@@ -23,7 +23,7 @@ The API layer is an HTTP adapter, not a business-logic layer.
|
|
|
23
23
|
|
|
24
24
|
## Route decorators (OpenAPI)
|
|
25
25
|
|
|
26
|
-
- Do **not** set **`summary=`** or **`description=`** on **`@router.get`**, **`post`**, **`patch`**, **`put`**, **`delete`**, or **`APIRoute`-style** registrations. Rely on paths, handler names, **`response_model`**, and Pydantic schemas. Do **not** add route **docstrings** for the same purpose either
|
|
26
|
+
- Do **not** set **`summary=`** or **`description=`** on **`@router.get`**, **`post`**, **`patch`**, **`put`**, **`delete`**, or **`APIRoute`-style** registrations. Rely on paths, handler names, **`response_model`**, and Pydantic schemas. Do **not** add route **docstrings** for the same purpose either.
|
|
27
27
|
|
|
28
28
|
## Response Models
|
|
29
29
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: docs/api.md is a minimal API index only
|
|
2
|
+
description: docs/library/api.md is a minimal API index only
|
|
3
3
|
globs:
|
|
4
|
-
- docs/api.md
|
|
4
|
+
- docs/library/api.md
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# API Reference (docs/api.md)
|
|
7
|
+
# API Reference (docs/library/api.md)
|
|
8
8
|
|
|
9
|
-
`docs/api.md` is strictly for **quick viewing** of available APIs. It is an index, not detailed documentation.
|
|
9
|
+
`docs/library/api.md` is strictly for **quick viewing** of available APIs. It is an index, not detailed documentation.
|
|
10
10
|
|
|
11
11
|
## Format
|
|
12
12
|
|
|
@@ -28,4 +28,4 @@ globs:
|
|
|
28
28
|
- Any prose or bullet lists
|
|
29
29
|
- Detailed behavior notes
|
|
30
30
|
|
|
31
|
-
For detailed API behavior, create or update flow documentation in `docs/
|
|
31
|
+
For detailed API behavior, create or update flow documentation in `docs/domains/` instead.
|
|
@@ -77,3 +77,7 @@ async def retrieve_my_username_suggestions(...) -> list[UsernameSuggestion]: ...
|
|
|
77
77
|
- Input validation (`validate_user_id`, `validate_report_id`, etc.) belongs in schemas
|
|
78
78
|
- Services do NOT raise `RequestValidationError` or import from `fastapi.exceptions`
|
|
79
79
|
- Routers call `validate_*` from schemas before invoking services
|
|
80
|
+
|
|
81
|
+
## Docstrings
|
|
82
|
+
|
|
83
|
+
Application functions get a **one-line** docstring (what it does). No `Args` / `Returns` / `Raises` — see **`docstrings.mdc`**.
|
|
@@ -178,7 +178,7 @@ If you ask for a trigger for business logic, I should:
|
|
|
178
178
|
|
|
179
179
|
## Related Documentation
|
|
180
180
|
|
|
181
|
-
- `docs/database-triggers.md` - **Catalog of all triggers** (update when adding new triggers)
|
|
182
|
-
- `docs/conventions.md` - Database Triggers section
|
|
183
|
-
- `docs/architecture-decisions.md` - Triggers Only for Audit/History
|
|
184
|
-
- `docs/
|
|
181
|
+
- `docs/platform/database-triggers.md` - **Catalog of all triggers** (update when adding new triggers)
|
|
182
|
+
- `docs/platform/conventions.md` - Database Triggers section
|
|
183
|
+
- `docs/platform/architecture-decisions.md` - Triggers Only for Audit/History
|
|
184
|
+
- `docs/domains/users/change_history.md` - Example of proper trigger usage
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Docstring depth by layer — one-line in application, full Args/Returns/Raises in domain and infrastructure
|
|
3
|
+
globs:
|
|
4
|
+
- core_framework/application/**/*.py
|
|
5
|
+
- core_framework/domains/**/*.py
|
|
6
|
+
- core_framework/infrastructure/**/*.py
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Docstrings by layer
|
|
10
|
+
|
|
11
|
+
Docstring **depth** depends on which layer owns the symbol. Type hints and keyword-only signatures carry parameter detail in application code; domain and infrastructure document the contract at the boundary.
|
|
12
|
+
|
|
13
|
+
## Application layer (`core_framework/application/`)
|
|
14
|
+
|
|
15
|
+
**One short sentence** — what the function does. No `Args`, `Returns`, or `Raises` sections.
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
# ✅ Preferred
|
|
19
|
+
async def enqueue_delete_superseded_banner_finals(*, asset_id: str) -> None:
|
|
20
|
+
"""Enqueue cleanup of published finals for a replaced banner asset."""
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
# ❌ Avoid — too heavy for application orchestration
|
|
24
|
+
async def enqueue_delete_superseded_banner_finals(...):
|
|
25
|
+
"""Enqueue cleanup of published finals for a replaced banner asset.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
asset_id: ...
|
|
29
|
+
Returns:
|
|
30
|
+
...
|
|
31
|
+
"""
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Applies to **public and private** helpers in application modules. When you touch a function in an application file, use the simple style.
|
|
35
|
+
|
|
36
|
+
## Domain layer (`core_framework/domains/`)
|
|
37
|
+
|
|
38
|
+
**Full docstring** on public service, repository, component, and port methods that implement or define behavior:
|
|
39
|
+
|
|
40
|
+
- Opening summary (one or two sentences)
|
|
41
|
+
- **`Args:`** — keyword-only parameters and meaning
|
|
42
|
+
- **`Returns:`** — when the return value is not obvious from the type alone
|
|
43
|
+
- **`Raises:`** — domain exceptions and validation errors callers should handle
|
|
44
|
+
|
|
45
|
+
Skip `Raises` only when the method truly cannot raise beyond programming errors. Trivial private helpers may stay undocumented; **exported and orchestration paths** get the full treatment.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# ✅ Preferred (domain service)
|
|
49
|
+
async def insert_avatar_staging_registry(...) -> AvatarStagingRegistryEntry:
|
|
50
|
+
"""Record a new avatar staging registry row before blob upload completes.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
asset_id: Unique avatar asset identifier.
|
|
54
|
+
owner_user_id: User who owns the avatar.
|
|
55
|
+
staging_filename: Basename of the staging blob on disk.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Persisted registry entry including staging metadata.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
DomainValidationError: If required string fields are blank or ``staging_filename``
|
|
62
|
+
is unsafe.
|
|
63
|
+
"""
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Repositories: document query semantics (filtering, empty results, strong vs normal read) in the summary or **`Returns:`** when non-obvious.
|
|
67
|
+
|
|
68
|
+
## Infrastructure layer (`core_framework/infrastructure/`)
|
|
69
|
+
|
|
70
|
+
Same as **domain** — adapters implement ports and perform I/O. Document inputs, outputs, failure modes (`Raises:` or raised infrastructure exceptions), and non-obvious side effects (network, disk, SSH).
|
|
71
|
+
|
|
72
|
+
## When editing
|
|
73
|
+
|
|
74
|
+
- **New** application functions → simple docstring.
|
|
75
|
+
- **New** domain/infrastructure public methods → full docstring.
|
|
76
|
+
- When you **change** a function in a file, bring **that function's** docstring in line with its layer; do not repo-wide migrate unrelated symbols unless the task asks for it.
|
|
77
|
+
|
|
78
|
+
## Out of scope
|
|
79
|
+
|
|
80
|
+
- **API routers and schemas** — no docstring requirement from this rule (OpenAPI and Pydantic carry the contract).
|
|
81
|
+
- **Workers** (`core_framework/worker/`) — thin task/schedule wrappers follow **application** style; logic belongs in application services.
|
{core_framework-1.6.0 → core_framework-1.8.0}/.cursor/rules/domain-services-and-adapters.mdc
RENAMED
|
@@ -7,7 +7,7 @@ globs:
|
|
|
7
7
|
|
|
8
8
|
# Domain Services and Adapters
|
|
9
9
|
|
|
10
|
-
See **`docs/domain-services-and-adapters.md`** for the full model. Apply when adding or changing domain packages and application orchestration.
|
|
10
|
+
See **`docs/platform/domain-services-and-adapters.md`** for the full model. Apply when adding or changing domain packages and application orchestration.
|
|
11
11
|
|
|
12
12
|
## Application = orchestration
|
|
13
13
|
|
|
@@ -45,3 +45,7 @@ See **`docs/domain-services-and-adapters.md`** for the full model. Apply when ad
|
|
|
45
45
|
- **Layout:** `domains/media/shared/`, `avatar/ports/`, `avatar/components/`, `AvatarService`.
|
|
46
46
|
- **Avatar:** `media_deps.avatar_service` only (not individual components).
|
|
47
47
|
- **Cross-domain:** `avatar_ingest_sequence` / profile `avatar_id` via **user** domain; orchestration in `application/media/avatar_service`.
|
|
48
|
+
|
|
49
|
+
## Docstrings
|
|
50
|
+
|
|
51
|
+
Domain services, repositories, ports, and components use **full** docstrings (`Args`, `Returns`, `Raises` where applicable). Application orchestration uses **one-line** summaries — see **`docstrings.mdc`**.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Flow docs describe user-facing API behavior. No JSON examples, no implementation details.
|
|
3
3
|
globs:
|
|
4
|
-
- docs/
|
|
4
|
+
- docs/domains/**/*.md
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Flow Documentation Rule
|
|
@@ -21,7 +21,7 @@ Create a new flow document when:
|
|
|
21
21
|
|
|
22
22
|
## File Location and Naming
|
|
23
23
|
|
|
24
|
-
- **Location**: `docs/
|
|
24
|
+
- **Location**: `docs/domains/{domain}/{feature}.md`
|
|
25
25
|
- **Naming**: Use lowercase with underscores (e.g., `account_deletion.md`, `change_history.md`)
|
|
26
26
|
- **Domain folders**: `auth`, `users`, `moderation`, `comments`, etc.
|
|
27
27
|
|
|
@@ -310,8 +310,8 @@ All endpoints require authentication via Firebase ID token with admin role.
|
|
|
310
310
|
|
|
311
311
|
When flow docs reference implementation details:
|
|
312
312
|
|
|
313
|
-
- **Architecture decisions**: Link to `docs/architecture-decisions.md`
|
|
314
|
-
- **API reference**: Already covered in `docs/api.md`
|
|
313
|
+
- **Architecture decisions**: Link to `docs/platform/architecture-decisions.md`
|
|
314
|
+
- **API reference**: Already covered in `docs/library/api.md`
|
|
315
315
|
- **Database schema**: Should be in migration files, not flow docs
|
|
316
316
|
- **Code structure**: Should be in code comments or architecture docs
|
|
317
317
|
|
|
@@ -38,14 +38,13 @@ When a rule encodes a new convention, check whether **`docs/`** in both repos ne
|
|
|
38
38
|
|
|
39
39
|
Sync to henry when core changes:
|
|
40
40
|
|
|
41
|
-
- **`docs/
|
|
42
|
-
- **`docs/
|
|
43
|
-
- **`docs/
|
|
44
|
-
- **`docs/deployment/`**, **`docs/media-upload-pipeline-design.md`** → sync when shared deploy/media docs change (adapt flow links in henry)
|
|
41
|
+
- **`docs/platform/`** — synced platform docs (layers, conventions, ADRs, adapters, etc.); adapt `docs/domains/…` links in henry to **`docs/core-product-docs.md`**
|
|
42
|
+
- **`docs/library/`** — canonical in core-framework only; henry points to it from **`docs/core-product-docs.md`** (do not add **`docs/library/`** under henry-backend)
|
|
43
|
+
- **`docs/deployments/`**, **`docs/domains/media/upload-pipeline-design.md`** → sync when shared deploy/media docs change (adapt flow links in henry)
|
|
45
44
|
|
|
46
|
-
**Do not** mirror **`docs/
|
|
45
|
+
**Do not** mirror **`docs/domains/`** into henry-backend. Henry maintains **`docs/core-product-docs.md`** as a pointer/index to core product documentation.
|
|
47
46
|
|
|
48
|
-
Do not overwrite henry-only docs (e.g. **`docs/henry
|
|
47
|
+
Do not overwrite henry-only docs (e.g. **`docs/domains/henry/`**, **`docs/core-product-docs.md`**).
|
|
49
48
|
|
|
50
49
|
## User-triggered sync
|
|
51
50
|
|
|
@@ -38,7 +38,7 @@ After the user accepts the API layer (or if there was no API layer):
|
|
|
38
38
|
|
|
39
39
|
- Implement the **Repository** for the domain layer (Postgres only).
|
|
40
40
|
- Include the **domain model** if data is retrieved from the database.
|
|
41
|
-
- If the feature needs non-SQL I/O (filesystem, HTTP, SSH), add **ports** in the domain and **adapter implementations** under `core_framework/infrastructure/<domain>/` per `docs/domain-services-and-adapters.md`—not in the repository.
|
|
41
|
+
- If the feature needs non-SQL I/O (filesystem, HTTP, SSH), add **ports** in the domain and **adapter implementations** under `core_framework/infrastructure/<domain>/` per `docs/platform/domain-services-and-adapters.md`—not in the repository.
|
|
42
42
|
- Wait for the user to review and accept before proceeding.
|
|
43
43
|
|
|
44
44
|
## 4. Service and Application Layer
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Karpathy behavioral guidelines
|
|
7
|
+
|
|
8
|
+
Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
|
|
9
|
+
|
|
10
|
+
**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
|
|
11
|
+
|
|
12
|
+
## 1. Think Before Coding
|
|
13
|
+
|
|
14
|
+
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
|
15
|
+
|
|
16
|
+
Before implementing:
|
|
17
|
+
- State your assumptions explicitly. If uncertain, ask.
|
|
18
|
+
- If multiple interpretations exist, present them - don't pick silently.
|
|
19
|
+
- If a simpler approach exists, say so. Push back when warranted.
|
|
20
|
+
- If something is unclear, stop. Name what's confusing. Ask.
|
|
21
|
+
|
|
22
|
+
## 2. Simplicity First
|
|
23
|
+
|
|
24
|
+
**Minimum code that solves the problem. Nothing speculative.**
|
|
25
|
+
|
|
26
|
+
- No features beyond what was asked.
|
|
27
|
+
- No abstractions for single-use code.
|
|
28
|
+
- No "flexibility" or "configurability" that wasn't requested.
|
|
29
|
+
- No error handling for impossible scenarios.
|
|
30
|
+
- If you write 200 lines and it could be 50, rewrite it.
|
|
31
|
+
|
|
32
|
+
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
|
|
33
|
+
|
|
34
|
+
## 3. Surgical Changes
|
|
35
|
+
|
|
36
|
+
**Touch only what you must. Clean up only your own mess.**
|
|
37
|
+
|
|
38
|
+
When editing existing code:
|
|
39
|
+
- Don't "improve" adjacent code, comments, or formatting.
|
|
40
|
+
- Don't refactor things that aren't broken.
|
|
41
|
+
- Match existing style, even if you'd do it differently.
|
|
42
|
+
- If you notice unrelated dead code, mention it - don't delete it.
|
|
43
|
+
|
|
44
|
+
When your changes create orphans:
|
|
45
|
+
- Remove imports/variables/functions that YOUR changes made unused.
|
|
46
|
+
- Don't remove pre-existing dead code unless asked.
|
|
47
|
+
|
|
48
|
+
The test: Every changed line should trace directly to the user's request.
|
|
49
|
+
|
|
50
|
+
## 4. Goal-Driven Execution
|
|
51
|
+
|
|
52
|
+
**Define success criteria. Loop until verified.**
|
|
53
|
+
|
|
54
|
+
Transform tasks into verifiable goals:
|
|
55
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
56
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
57
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
58
|
+
|
|
59
|
+
For multi-step tasks, state a brief plan:
|
|
60
|
+
```
|
|
61
|
+
1. [Step] → verify: [check]
|
|
62
|
+
2. [Step] → verify: [check]
|
|
63
|
+
3. [Step] → verify: [check]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
|
|
@@ -111,7 +111,7 @@ A single `class <Domain>Service:` whose **`__init__`** takes `<Domain>Repository
|
|
|
111
111
|
|
|
112
112
|
When real behavior is added later, apply `repository-read-consistency` (`/.cursor/rules/repository-read-consistency.mdc`) for reads and `_strong` naming.
|
|
113
113
|
|
|
114
|
-
If the bounded context needs filesystem, HTTP, or SSH, add **ports/adapters** or extra domain collaborators per `docs/domain-services-and-adapters.md` — do not put that I/O in `repository.py`.
|
|
114
|
+
If the bounded context needs filesystem, HTTP, or SSH, add **ports/adapters** or extra domain collaborators per `docs/platform/domain-services-and-adapters.md` — do not put that I/O in `repository.py`.
|
|
115
115
|
|
|
116
116
|
### `__init__.py`
|
|
117
117
|
|
|
@@ -175,7 +175,7 @@ Worker `startup` and API `init_app` already call `configure_application_dependen
|
|
|
175
175
|
|
|
176
176
|
- `core_framework/domains/<domain>/README.md` — domain exists in code; `alembic/<domain>/` exists with **empty** `versions/`; **not** in `ALEMBIC_DOMAINS` until first revision; **no** DB schema object until a migration creates it.
|
|
177
177
|
- `CHANGELOG.md` — `### Added` under `[Unreleased]` for domain package, `schema_<domain>`, and Alembic skeleton path (optional). **Do not** list `ALEMBIC_DOMAINS` or revision ids until the first migration lands.
|
|
178
|
-
- Update `docs/
|
|
178
|
+
- Update `docs/library/overview.md` and `docs/library/package-api.md` only when the domain exposes anything to the public surface.
|
|
179
179
|
|
|
180
180
|
## Follow-up: first revision + enroll in `cf-alembic`
|
|
181
181
|
|
|
@@ -35,17 +35,17 @@ Apply **`.cursor/rules/code-review-output.mdc`**. The user wants **actionable fi
|
|
|
35
35
|
|
|
36
36
|
Read these files **before** proceeding with the review:
|
|
37
37
|
|
|
38
|
-
1. **`docs/
|
|
39
|
-
1. **`docs/domain-services-and-adapters.md`** – Application orchestration vs domain services, ports/adapters, multiple collaborators per bounded context
|
|
40
|
-
1. **`docs/conventions.md`** – Coding conventions, domain rules, caching, Redis, exception handling, API layer rules
|
|
41
|
-
1. **`docs/architecture-decisions.md`** – Intentional design choices; do not flag these as issues
|
|
42
|
-
1. **`.cursor/rules/api-layer.mdc`**, **`.cursor/rules/application-layer.mdc`**, **`.cursor/rules/domain-services-and-adapters.mdc`**, **`.cursor/rules/domain-imports.mdc`**, **`.cursor/rules/domain-caller-context.mdc`** – Apply when reviewing API/application/domain code
|
|
38
|
+
1. **`docs/platform/layers-and-boundaries.md`** – Domain boundaries, prohibited practices, and dependency rules
|
|
39
|
+
1. **`docs/platform/domain-services-and-adapters.md`** – Application orchestration vs domain services, ports/adapters, multiple collaborators per bounded context
|
|
40
|
+
1. **`docs/platform/conventions.md`** – Coding conventions, domain rules, caching, Redis, exception handling, API layer rules
|
|
41
|
+
1. **`docs/platform/architecture-decisions.md`** – Intentional design choices; do not flag these as issues
|
|
42
|
+
1. **`.cursor/rules/api-layer.mdc`**, **`.cursor/rules/application-layer.mdc`**, **`.cursor/rules/docstrings.mdc`**, **`.cursor/rules/domain-services-and-adapters.mdc`**, **`.cursor/rules/domain-imports.mdc`**, **`.cursor/rules/domain-caller-context.mdc`** – Apply when reviewing API/application/domain code
|
|
43
43
|
|
|
44
44
|
## Step 2: Key Context
|
|
45
45
|
|
|
46
46
|
### Architecture Decisions (do not flag as issues)
|
|
47
47
|
|
|
48
|
-
- TOML as primary deploy artifact; environment variables can override (see `docs/architecture-decisions.md`)
|
|
48
|
+
- TOML as primary deploy artifact; environment variables can override (see `docs/platform/architecture-decisions.md`)
|
|
49
49
|
- `trusted_hosts=["*"]` in ProxyHeadersMiddleware (runs behind reverse proxy)
|
|
50
50
|
- `-> Any` return types when `response_model` is specified
|
|
51
51
|
- Silent `ForeignKeyViolationError` in `insert_user_block`
|
|
@@ -76,6 +76,7 @@ Verify the following. Also apply api-layer, application-layer, and domain-import
|
|
|
76
76
|
|
|
77
77
|
### Application Layer Services (`core_framework/application/**/*_service.py`)
|
|
78
78
|
|
|
79
|
+
- [ ] **Docstrings** – One-line summary only; no `Args`/`Returns`/`Raises` (see `docstrings.mdc`)
|
|
79
80
|
- [ ] **No HTTP handling** – No `HTTPException`, `RequestValidationError`, `BackgroundTasks`, or other FastAPI HTTP imports
|
|
80
81
|
- [ ] **No Pydantic return types** – Services return `dict`, `list[dict]`, dataclasses, or plain types; routers use `response_model`
|
|
81
82
|
- [ ] **Not found** – Return `None` or `Optional`; routers raise `HTTPException(404)` when appropriate
|
|
@@ -140,7 +140,7 @@ jobs:
|
|
|
140
140
|
DOCKERHUB_USERNAME="${{ inputs.dockerhub_username }}"
|
|
141
141
|
CONFIG_PATH="/home/${{ secrets.SERVER_USER }}/app_configs/core-framework/config.toml"
|
|
142
142
|
FIREBASE_CONFIG_PATH="/home/${{ secrets.SERVER_USER }}/app_configs/core-framework/firebase_config.json"
|
|
143
|
-
|
|
143
|
+
MEDIA_STAGING_PATH="/home/${{ secrets.SERVER_USER }}/app_configs/core-framework/media-staging"
|
|
144
144
|
IMAGE_SERVER_SSH_KEY_PATH="/home/${{ secrets.SERVER_USER }}/app_configs/core-framework/image_server_ssh_key"
|
|
145
145
|
IMAGE_SERVER_KNOWN_HOSTS_PATH="/home/${{ secrets.SERVER_USER }}/app_configs/core-framework/image_server_known_hosts"
|
|
146
146
|
|
|
@@ -148,21 +148,21 @@ jobs:
|
|
|
148
148
|
DOCKERHUB_USERNAME="$DOCKERHUB_USERNAME" \
|
|
149
149
|
CONFIG_PATH="$CONFIG_PATH" \
|
|
150
150
|
FIREBASE_CONFIG_PATH="$FIREBASE_CONFIG_PATH" \
|
|
151
|
-
|
|
151
|
+
MEDIA_STAGING_PATH="$MEDIA_STAGING_PATH" \
|
|
152
152
|
IMAGE_SERVER_SSH_KEY_PATH="$IMAGE_SERVER_SSH_KEY_PATH" \
|
|
153
153
|
IMAGE_SERVER_KNOWN_HOSTS_PATH="$IMAGE_SERVER_KNOWN_HOSTS_PATH" \
|
|
154
154
|
docker compose -f "$COMPOSE_FILE" pull
|
|
155
155
|
|
|
156
|
-
echo "Preparing
|
|
157
|
-
mkdir -p "$
|
|
156
|
+
echo "Preparing media staging directory and image server SSH key permissions"
|
|
157
|
+
mkdir -p "$MEDIA_STAGING_PATH"
|
|
158
158
|
docker run --rm \
|
|
159
159
|
--user root \
|
|
160
|
-
-v "$
|
|
160
|
+
-v "$MEDIA_STAGING_PATH:/app/media-staging" \
|
|
161
161
|
-v "$IMAGE_SERVER_SSH_KEY_PATH:/app/image-server-ssh-key" \
|
|
162
162
|
-v "$IMAGE_SERVER_KNOWN_HOSTS_PATH:/app/image-server-known-hosts" \
|
|
163
163
|
--entrypoint "" \
|
|
164
164
|
"$DOCKERHUB_USERNAME/core-framework:latest" \
|
|
165
|
-
sh -c 'mkdir -p /app/
|
|
165
|
+
sh -c 'mkdir -p /app/media-staging && chown -R appuser:appgroup /app/media-staging && chown appuser:appgroup /app/image-server-ssh-key && chmod 600 /app/image-server-ssh-key && chown appuser:appgroup /app/image-server-known-hosts && chmod 644 /app/image-server-known-hosts'
|
|
166
166
|
|
|
167
167
|
echo "Running database migrations (cf-alembic iterates core_framework.bundled_alembic.ALEMBIC_DOMAINS in order)"
|
|
168
168
|
docker run --rm \
|
|
@@ -175,7 +175,7 @@ jobs:
|
|
|
175
175
|
DOCKERHUB_USERNAME="$DOCKERHUB_USERNAME" \
|
|
176
176
|
CONFIG_PATH="$CONFIG_PATH" \
|
|
177
177
|
FIREBASE_CONFIG_PATH="$FIREBASE_CONFIG_PATH" \
|
|
178
|
-
|
|
178
|
+
MEDIA_STAGING_PATH="$MEDIA_STAGING_PATH" \
|
|
179
179
|
IMAGE_SERVER_SSH_KEY_PATH="$IMAGE_SERVER_SSH_KEY_PATH" \
|
|
180
180
|
IMAGE_SERVER_KNOWN_HOSTS_PATH="$IMAGE_SERVER_KNOWN_HOSTS_PATH" \
|
|
181
181
|
docker compose -f "$COMPOSE_FILE" up -d \
|
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Notable changes to **core-framework** (import **`core_framework`**). Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is [SemVer](https://semver.org/spec/v2.0.0.html). Stable surface: **`docs/package-api.md`**.
|
|
3
|
+
Notable changes to **core-framework** (import **`core_framework`**). Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is [SemVer](https://semver.org/spec/v2.0.0.html). Stable surface: **`docs/library/package-api.md`**.
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.8.0] - 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`[avatar].public_path_prefix`** and **`[banner].public_path_prefix`** — optional URL path segment in **`config.toml`** when avatar/banner finals are served under a subdirectory on a shared media host. Empty by default (dedicated product vhost docroot).
|
|
12
|
+
|
|
13
|
+
- **Follow counts on profile surfaces:** **`GET /users/me/profile`**, **`PATCH /users/me/profile`**, and admin **`GET /admin/users/{user_id}`** profile payload include **`follower_count`** and **`following_count`** (same **user_stats** source as public profile). Follow/unfollow invalidates **`user_stats`** cache for both parties when the edge changes.
|
|
14
|
+
|
|
15
|
+
- **HEIC/HEIF ingest (avatar and banner):** Allow **`image/heic`** and **`image/heif`** on profile image uploads; decode via **`pillow-heif`** before WebP variant encoding.
|
|
16
|
+
|
|
17
|
+
- **Image ingest hardening:** Staging decode uses a **30s** timeout, **4096×4096** pixel cap, and Pillow decompression-bomb limits; published WebP finals omit embedded metadata.
|
|
18
|
+
|
|
19
|
+
- **Structured mentions (posts and comments):** **`post_mentions`** / **`comment_mentions`** persistence; **`mentions`** on **POST** create, **PATCH** replace (omit unchanged, **`[]`** clears), and **GET** responses as **`UserReference`** list. **`mention` inbox notifications** remain **create-only**. Migrations **`post_add_post_mentions`**, **`comment_add_comment_mentions`**. See **`docs/domains/mentions/mentions_in_content.md`**.
|
|
20
|
+
|
|
21
|
+
### Database
|
|
22
|
+
|
|
23
|
+
- **Post** migration **`post_add_post_mentions`**; **comment** migration **`comment_add_comment_mentions`**. Run **`uv run cf-alembic`** before deploying.
|
|
24
|
+
|
|
25
|
+
## [1.7.0] - 2026-06-01
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Banner upload (v1):** **`POST /users/me/profile/banner`**, **`media.banner_staging_registry`** / **`banner_ingest_lease`**, worker jobs **`process_banner_asset_variants`** and **`delete_superseded_banner_finals`**, stale banner staging cron, shared **`[media].staging_root`**. **`PATCH /users/me/profile`** no longer accepts **`banner_id`**. See **`docs/domains/media/upload_pipeline.md`**, **`docs/domains/users/banner.md`**, and **`docs/domains/users/profile.md`**.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **Breaking (API):** Profile **`banner`** is now an object **`{ "url": "…", "fallback": "…" }`** instead of a single URL string. **`fallback`** is always the default banner URL for load-error UX.
|
|
34
|
+
- **Breaking (hosts):** **`[avatar].staging_root`** removed; use **`[media].staging_root`** (**`MEDIA_STAGING_PATH`** / **`media-staging`**). Migrate existing host **`avatar-staging`** directories to **`media-staging`** on deploy.
|
|
35
|
+
|
|
36
|
+
### Database
|
|
37
|
+
|
|
38
|
+
- **Media** migration **`media_banner_staging_lease`**: **`banner_staging_registry`**, **`banner_ingest_lease`**.
|
|
39
|
+
- **User** migration **`user_add_banner_ingest_sequences`**: **`banner_ingest_sequence`**, **`banner_applied_sequence`** on **`user_profiles`**.
|
|
40
|
+
- Run **`uv run cf-alembic`** (or the host **`cf-alembic`** step) before deploying code that uses banner upload.
|
|
41
|
+
|
|
42
|
+
### Documentation
|
|
43
|
+
|
|
44
|
+
- **`docs/domains/users/banner.md`**, profile and upload-pipeline updates, **`docs/deployments/edge-upload-limits.md`** and **`Caddyfile.example`** — banner route body limit.
|
|
45
|
+
|
|
7
46
|
## [1.6.0] - 2026-05-27
|
|
8
47
|
|
|
9
48
|
### Changed
|
|
@@ -14,7 +53,7 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
14
53
|
|
|
15
54
|
### Added
|
|
16
55
|
|
|
17
|
-
- **Avatar upload (v1):** **`POST /users/me/profile/avatar`**, **`media`** schema, worker variant processing, staging sweep cron, **`[avatar].staging_root`** config. See **`docs/
|
|
56
|
+
- **Avatar upload (v1):** **`POST /users/me/profile/avatar`**, **`media`** schema, worker variant processing, staging sweep cron, **`[avatar].staging_root`** config. See **`docs/domains/media/upload_pipeline.md`** and **`docs/domains/users/profile.md`**.
|
|
18
57
|
|
|
19
58
|
### Fixed
|
|
20
59
|
|
|
@@ -23,7 +62,7 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
23
62
|
|
|
24
63
|
### Changed
|
|
25
64
|
|
|
26
|
-
- **Breaking:** **`[image_server].known_hosts_path`** is required; **`SshAvatarFinalsPublisherAdapter`** verifies the image server SSH host key (no longer **`known_hosts=None`**). Deploy must provide **`IMAGE_SERVER_KNOWN_HOSTS`** and mount **`/app/image-server-known-hosts`** on the worker. See **`docs/
|
|
65
|
+
- **Breaking:** **`[image_server].known_hosts_path`** is required; **`SshAvatarFinalsPublisherAdapter`** verifies the image server SSH host key (no longer **`known_hosts=None`**). Deploy must provide **`IMAGE_SERVER_KNOWN_HOSTS`** and mount **`/app/image-server-known-hosts`** on the worker. See **`docs/deployments/guides/image-server-ssh.md`**.
|
|
27
66
|
- **Breaking:** **`[avatar].avatar_host_domain`** is **host-only** in **`config.toml`** and deploy secret **`AVATAR_HOST_DOMAIN`** (for example **`avatar.example.com`**, no **`https://`**). The application prepends **`https://`** when assembling public avatar URLs. Values that still include a scheme are normalized at load time.
|
|
28
67
|
- **Breaking:** **`[banner]`** config aligns with **`[avatar]`**: **`banner_host_domain`** + **`default_banner_image`** (deploy secrets **`BANNER_HOST_DOMAIN`**, **`BANNER_DEFAULT_IMAGE`**) replace **`base_url`** / **`default_url`**. Hostname is host-only; public banner URLs derive **`https://`** in application code.
|
|
29
68
|
|
|
@@ -35,21 +74,21 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
35
74
|
|
|
36
75
|
### Documentation
|
|
37
76
|
|
|
38
|
-
- **Avatar upload edge limits:** **`docs/
|
|
39
|
-
- **Image server SSH:** **`docs/
|
|
40
|
-
- **`docs/
|
|
41
|
-
- **`docs/
|
|
42
|
-
- **`docs/
|
|
43
|
-
- **`docs/
|
|
44
|
-
- **`docs/domain-services-and-adapters.md`**: **`banner_host_domain`** / **`default_banner_image`** config shape documented alongside avatar.
|
|
77
|
+
- **Avatar upload edge limits:** **`docs/deployments/edge-upload-limits.md`**, **`docs/deployments/examples/Caddyfile.example`** — route-scoped reverse-proxy **`max_size`** (**6 MiB** recommended) for **`POST /users/me/profile/avatar`**; updated **`docs/domains/media/upload_pipeline.md`** and **`docs/domains/users/profile.md`**.
|
|
78
|
+
- **Image server SSH:** **`docs/deployments/guides/image-server-ssh.md`**, **`docs/deployments/examples/image-server-known-hosts.example`** — production checklist for **`known_hosts_path`** and **`IMAGE_SERVER_KNOWN_HOSTS`**.
|
|
79
|
+
- **`docs/domains/media/upload_pipeline.md`**: status and HTTP surface aligned with shipped v1 implementation.
|
|
80
|
+
- **`docs/domains/users/profile.md`**: **`POST /users/me/profile/avatar`** flow; **`PATCH`** no longer documents **`avatar_id`** as planned.
|
|
81
|
+
- **`docs/domains/users/avatar.md`**, **`docs/domains/users/change_history.md`**: avatar change path and ingest MIME notes updated.
|
|
82
|
+
- **`docs/domains/users/avatar.md`**, **`docs/domains/users/profile.md`**: **`avatar_host_domain`** documented as host-only; public URLs derive **`https://`** in application code.
|
|
83
|
+
- **`docs/platform/domain-services-and-adapters.md`**: **`banner_host_domain`** / **`default_banner_image`** config shape documented alongside avatar.
|
|
45
84
|
|
|
46
85
|
## [1.4.0] - 2026-05-19
|
|
47
86
|
|
|
48
87
|
### Changed
|
|
49
88
|
|
|
50
|
-
- **Breaking:** **`avatar`** on profile and related user responses is an object (**`size_128`**, **`size_500`**, **`fallback`**) instead of a single URL string. See **`docs/
|
|
89
|
+
- **Breaking:** **`avatar`** on profile and related user responses is an object (**`size_128`**, **`size_500`**, **`fallback`**) instead of a single URL string. See **`docs/domains/users/avatar.md`**.
|
|
51
90
|
- **Breaking:** **`[avatar]`** config uses **`avatar_host_domain`** + **`default_avatar_image`** (deploy env **`AVATAR_HOST_DOMAIN`**, **`AVATAR_DEFAULT_IMAGE`**) instead of **`base_url`** / **`default_url`**.
|
|
52
|
-
- **Typed PATCH payloads** — user (preferences, account, profile + admin profile), post, and comment PATCH routes map Pydantic requests to domain `*Update` types at the API boundary; no `model_dump(mode="json")` or dict partial-update payloads through application/domain/repository. See `docs/patch-update-typed-payload.md` and `docs/conventions.md` (*PATCH partial updates*).
|
|
91
|
+
- **Typed PATCH payloads** — user (preferences, account, profile + admin profile), post, and comment PATCH routes map Pydantic requests to domain `*Update` types at the API boundary; no `model_dump(mode="json")` or dict partial-update payloads through application/domain/repository. See `docs/platform/patch-update-typed-payload.md` and `docs/platform/conventions.md` (*PATCH partial updates*).
|
|
53
92
|
- Self-service profile PATCH invalidates **`USER_DETAIL`** only when **`display_name`** or **`avatar_id`** change (fields present in cached identity). **`profile_visibility`** is coerced to **`ProfileVisibility`** on repository read.
|
|
54
93
|
|
|
55
94
|
### Added
|
|
@@ -62,11 +101,11 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
62
101
|
|
|
63
102
|
### Documentation
|
|
64
103
|
|
|
65
|
-
- **`docs/
|
|
66
|
-
- **`docs/
|
|
67
|
-
- **`docs/
|
|
68
|
-
- **`docs/
|
|
69
|
-
- **`docs/patch-update-typed-payload.md`**: typed PATCH decisions and patterns for partial-update endpoints.
|
|
104
|
+
- **`docs/domains/users/avatar.md`**: multi-size **`avatar`** response shape and CDN URL convention.
|
|
105
|
+
- **`docs/domains/media/upload_pipeline.md`**: upload pipeline design and v1 implementation reference.
|
|
106
|
+
- **`docs/domains/users/profile.md`**: DOB on get/update flows and validation errors.
|
|
107
|
+
- **`docs/domains/users/change_history.md`**: profile **`date_of_birth`** changes are not written to change history (audit trigger unchanged).
|
|
108
|
+
- **`docs/platform/patch-update-typed-payload.md`**: typed PATCH decisions and patterns for partial-update endpoints.
|
|
70
109
|
|
|
71
110
|
### Fixed
|
|
72
111
|
|
|
@@ -103,7 +142,7 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
103
142
|
|
|
104
143
|
### Documentation
|
|
105
144
|
|
|
106
|
-
- Follow feature (HTTP, notifications, stats worker, mirrors, **`docs/follow-system-design.md`**, architecture decisions, domain READMEs, **`docs/api.md`**).
|
|
145
|
+
- Follow feature (HTTP, notifications, stats worker, mirrors, **`docs/domains/users/follow-system-design.md`**, architecture decisions, domain READMEs, **`docs/library/api.md`**).
|
|
107
146
|
|
|
108
147
|
## [1.1.1] - 2026-04-24
|
|
109
148
|
|
|
@@ -119,7 +158,7 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
119
158
|
|
|
120
159
|
### Added
|
|
121
160
|
|
|
122
|
-
- **`core-framework[testing]`** extra: pytest plugin (**`pytest11`** → **`core_framework.testing.plugin`**), **`TestConfig`**, session fixtures (Postgres, Redis, **`AsyncClient`**, migrations, Firebase helpers, optional SAQ). Parallel (**`pytest -n`**) coordination — see **`docs/testing-plugin-design.md`**. **`create_firebase_user_token`** helper.
|
|
161
|
+
- **`core-framework[testing]`** extra: pytest plugin (**`pytest11`** → **`core_framework.testing.plugin`**), **`TestConfig`**, session fixtures (Postgres, Redis, **`AsyncClient`**, migrations, Firebase helpers, optional SAQ). Parallel (**`pytest -n`**) coordination — see **`docs/library/testing-plugin-design.md`**. **`create_firebase_user_token`** helper.
|
|
123
162
|
|
|
124
163
|
### Changed
|
|
125
164
|
|
|
@@ -127,11 +166,11 @@ Notable changes to **core-framework** (import **`core_framework`**). Format foll
|
|
|
127
166
|
|
|
128
167
|
### Documentation
|
|
129
168
|
|
|
130
|
-
- **`docs/package-api.md`**, **`docs/core-framework-migration.md`**, **`README.md`**, **`docs/testing-plugin-design.md`** updated for testing and entrypoints.
|
|
169
|
+
- **`docs/library/package-api.md`**, **`docs/library/core-framework-migration.md`**, **`README.md`**, **`docs/library/testing-plugin-design.md`** updated for testing and entrypoints.
|
|
131
170
|
|
|
132
171
|
## [1.0.0] - 2026-04-18
|
|
133
172
|
|
|
134
|
-
First **SemVer-stable** release per **`docs/package-api.md`**.
|
|
173
|
+
First **SemVer-stable** release per **`docs/library/package-api.md`**.
|
|
135
174
|
|
|
136
175
|
### Breaking
|
|
137
176
|
|
|
@@ -158,7 +197,7 @@ First **SemVer-stable** release per **`docs/package-api.md`**.
|
|
|
158
197
|
|
|
159
198
|
### Documentation
|
|
160
199
|
|
|
161
|
-
- Mentions flow, **`GET /users/usernames/suggest`**, **`docs/api.md`**.
|
|
200
|
+
- Mentions flow, **`GET /users/usernames/suggest`**, **`docs/library/api.md`**.
|
|
162
201
|
|
|
163
202
|
## [0.4.0] - 2026-03-26
|
|
164
203
|
|
|
@@ -180,7 +219,7 @@ First **SemVer-stable** release per **`docs/package-api.md`**.
|
|
|
180
219
|
|
|
181
220
|
### Documentation
|
|
182
221
|
|
|
183
|
-
- **`README`**, **`docs/core-framework-migration.md`**, **`docs/package-api.md`**, **`docs/
|
|
222
|
+
- **`README`**, **`docs/library/core-framework-migration.md`**, **`docs/library/package-api.md`**, **`docs/library/overview.md`** (runtime / bootstrap).
|
|
184
223
|
|
|
185
224
|
### Removed
|
|
186
225
|
|
|
@@ -190,7 +229,7 @@ First **SemVer-stable** release per **`docs/package-api.md`**.
|
|
|
190
229
|
|
|
191
230
|
### Added
|
|
192
231
|
|
|
193
|
-
- **`init_app(settings)`**, **`create_task_worker(settings)`**, **`CoreRuntime`**, **`build_core_runtime`**, **`configure_application_dependencies`**, **`load_default_settings()`**, **`configure_core_runtime`**. **`docs/package-api.md`**.
|
|
232
|
+
- **`init_app(settings)`**, **`create_task_worker(settings)`**, **`CoreRuntime`**, **`build_core_runtime`**, **`configure_application_dependencies`**, **`load_default_settings()`**, **`configure_core_runtime`**. **`docs/library/package-api.md`**.
|
|
194
233
|
|
|
195
234
|
### Changed
|
|
196
235
|
|
|
@@ -211,4 +250,6 @@ First **SemVer-stable** release per **`docs/package-api.md`**.
|
|
|
211
250
|
[1.4.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.3.0...v1.4.0
|
|
212
251
|
[1.5.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.4.0...v1.5.0
|
|
213
252
|
[1.6.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.5.0...v1.6.0
|
|
214
|
-
[
|
|
253
|
+
[1.7.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.6.0...v1.7.0
|
|
254
|
+
[1.8.0]: https://github.com/NepNepFFXIV/core-framework/compare/v1.7.0...v1.8.0
|
|
255
|
+
[unreleased]: https://github.com/NepNepFFXIV/core-framework/compare/v1.8.0...HEAD
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-framework
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Core framework package (import as core_framework)
|
|
5
5
|
Project-URL: Homepage, https://github.com/NepNepFFXIV/core-framework
|
|
6
6
|
Project-URL: Repository, https://github.com/NepNepFFXIV/core-framework
|
|
@@ -24,6 +24,7 @@ Requires-Dist: itsdangerous>=2.2.0
|
|
|
24
24
|
Requires-Dist: logfire[asyncpg,fastapi,httpx,redis]>=4.32.1
|
|
25
25
|
Requires-Dist: mashumaro[orjson]>=3.20
|
|
26
26
|
Requires-Dist: orjson>=3.11.7
|
|
27
|
+
Requires-Dist: pillow-heif>=1.3.0
|
|
27
28
|
Requires-Dist: pillow>=12.2.0
|
|
28
29
|
Requires-Dist: python-ulid>=3.1.0
|
|
29
30
|
Requires-Dist: structlog>=25.5.0
|
|
@@ -87,7 +88,7 @@ def build_app(settings: HostSettings | None = None) -> FastAPI:
|
|
|
87
88
|
return app
|
|
88
89
|
```
|
|
89
90
|
|
|
90
|
-
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/core-framework-migration.md).
|
|
91
|
+
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/library/core-framework-migration.md).
|
|
91
92
|
|
|
92
93
|
## Host pytest
|
|
93
94
|
|
|
@@ -115,4 +116,4 @@ def anyio_backend() -> str:
|
|
|
115
116
|
return "asyncio"
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
See [Package API — Testing](docs/package-api.md#testing-pytest-plugin) and [testing plugin design](docs/testing-plugin-design.md).
|
|
119
|
+
See [Package API — Testing](docs/library/package-api.md#testing-pytest-plugin) and [testing plugin design](docs/library/testing-plugin-design.md).
|
|
@@ -50,7 +50,7 @@ def build_app(settings: HostSettings | None = None) -> FastAPI:
|
|
|
50
50
|
return app
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/core-framework-migration.md).
|
|
53
|
+
From the host repository root, run **`uv run cf-alembic`**. See [core-framework-migration](docs/library/core-framework-migration.md).
|
|
54
54
|
|
|
55
55
|
## Host pytest
|
|
56
56
|
|
|
@@ -78,4 +78,4 @@ def anyio_backend() -> str:
|
|
|
78
78
|
return "asyncio"
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
See [Package API — Testing](docs/package-api.md#testing-pytest-plugin) and [testing plugin design](docs/testing-plugin-design.md).
|
|
81
|
+
See [Package API — Testing](docs/library/package-api.md#testing-pytest-plugin) and [testing plugin design](docs/library/testing-plugin-design.md).
|