Repository navigation
fix: port legacy invite integrity hardening to dev - #767
Merged
Merged
Conversation
TThanos3000
marked this pull request as ready for review
September 29, 2026 22:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что изменено
Replacement delivery for #764.
#764 был корректно реализован и протестирован, но был merged в stacked base
fix/dev-team-security-errorsвместоdev. Этот PR переносит только incremental changes #764 на актуальныйdevпосле merge #763.Legacy Invite transitions используют общий atomic service и единый lock protocol. Accept создаёт Collaborator и завершает Invite в одной транзакции; stale PATCH не возвращает обработанный Invite в pending. Partial unique index защищает один pending Invite на
(project, user), а проигравший конкурентный INSERT получает controlled 409.Зачем
Изменения original PR #764 не попали в
dev, потому что PR был merged в stacked feature base. Этот Draft PR доставляет тот же incremental B scope отдельной веткой непосредственно вdev, без повторного переноса PR A и без изменений PR C.Реализация
3a513846c81dd36e5f3393957ec3450c9fcfb2f7.64a97a87b789aa2ac1f3ebabba2ef43e1b785bca.11547cab5af868125c150e53c8f4061d94b1554b.cherry-pickoriginal incremental commit B; конфликтов не было.origin/dev...HEADсодержит ровно один commit и 9 файлов B.docs/invite-integrity-api.md;invites/migrations/0003_legacy_pending_invite_constraint.py;invites/models.py;invites/serializers.py;invites/tests/test_invite_api.py;invites/tests/test_invite_integrity.py;invites/tests/test_pending_invite_migration.py;invites/views.py;projects/team_service.py.team_policy, migrations 0004/0019, Angular и React отсутствуют.API
Успешные ответы сохранены: create 201, accept/decline 200, edit 200, revoke pending 204. State conflicts имеют
{code, detail}и 409:duplicate_pending_invite,invite_already_processed,not_program_member,already_project_member,already_project_leader,invalid_team_member. Permission conflicts остаются 403. Malformed input остаётся 400.Concurrent revoke-first/accept-second может вернуть accept 404: Invite уже удалён, Collaborator не создаётся. Lifecycle fields нельзя изменить PATCH/PUT; edit сохраняет только разрешённые mutable fields.
UI
Не менялся. Angular и React отсутствуют в diff.
Permissions
Исправления PR A сохранены: только текущий leader управляет командой; object authorization повторно проверяется внутри service после Project lock. Outsider не может switch leader или удалить collaborator публичного/приватного проекта. Разрешённые pre-submission remove/switch текущим leader продолжают работать. Direct member add остаётся controlled 405 после authorization.
Проверки
invites.tests,projects.tests.test_project_collaborators,projects.tests.test_team_security— 72 tests PASS.python manage.py checkиcheck --tag models— PASS.python manage.py makemigrations --check --dry-run—No changes detected.python manage.py showmigrations invitesпоказывает единственную цепочку0001,0002,0003на source; на чистой test DB migration 0003 и partial unique index применены ровно один раз.git diff --check— PASS.Acceptance criteria
dev/64a97a87b789aa2ac1f3ebabba2ef43e1b785bca.0003_legacy_pending_invite_constraintприсутствует и применена ровно один раз.Не проверено
Повторный live DEV SQL preflight не выполнен: у Codex нет read-only credentials/SSH к DEV DB, а публичный API не предоставляет безопасный SQL/count surface. Ранее предоставленный результат аудита — duplicate pending Invite
(project,user) = 0— не выдаётся за повторную проверку. Workflow/PR #766 не использовался. Production/DEV data не изменялись.Browser не применим к backend-only diff. Live DEV mutations, merge и deploy не выполнялись.
Риски / migration
Единственная migration
invites/0003_legacy_pending_invite_constraint.pyсначала выполняет read-only duplicate preflight, затем добавляет partial unique indexuniq_legacy_pending_invite(project,user) WHERE is_accepted IS NULL. Если на момент rollout появились duplicates, migration остановится без удаления данных и без выбора победителя; требуется отдельное решение владельца данных.Откат удаляет constraint и сохраняет Invite. PROD имеет другой migration graph/lifecycle; этот PR направлен только в
dev. PR C #765 намеренно не изменялся и должен обновляться относительно свежего dev отдельным этапом после merge этого PR.