Skip to content

Prune seeded no-lockout language memberships#87

Merged
joaocarvoli merged 1 commit into
mainfrom
chore/prune-seeded-language-members
Jun 9, 2026
Merged

Prune seeded no-lockout language memberships#87
joaocarvoli merged 1 commit into
mainfrom
chore/prune-seeded-language-members

Conversation

@joaocarvoli

Copy link
Copy Markdown
Member

Summary

Per-language access control is enforced correctly, but migration 20260608_0001 seeded an as_language_members row for every existing annotation-studio user across every active language (to avoid a deploy lockout). That made scoping ineffective in practice — everyone can currently edit every language. This migration removes those seeded grants so only explicitly-invited members keep access.

How it identifies seeded rows

The seed insert omitted granted_by (→ NULL); Members-panel invites always set granted_by to the admin's id (member_service.add_member). So DELETE … WHERE granted_by IS NULL removes exactly the seeded rows and preserves real invites. Admins and platform admins bypass membership entirely, so they're unaffected.

Changes

  • alembic/versions/20260609_0001_prune_seeded_language_members.py (new): upgrade() deletes as_language_members WHERE granted_by IS NULL; downgrade() is a no-op (the seed set can't be reconstructed). Auto-applies on deploy (alembic upgrade head).

Type of Change

  • Bug fix / data migration (makes per-language scoping effective)

Testing

uv run alembic heads → single head 20260609_0001; uv run pytest -q → 677 passed / 2 skipped (existing AS access + HTTP tests already prove non-members get 403). The DELETE semantics were validated on a fixture: only granted_by IS NULL rows are removed, invited rows remain.

Effect after deploy: facilitators who only had seeded access lose it until an admin re-invites them per language via the Members panel. Existing per-language invites and admin access are untouched.


🤖 Generated with Claude Code

Migration 20260608_0001 seeded an as_language_members row for every existing
annotation-studio user across every active language to avoid a deploy lockout,
which made per-language scoping ineffective (everyone could edit everything).
Delete those seeded grants (granted_by IS NULL) so only explicitly-invited
members keep access. Members-panel invites set granted_by, so they're preserved;
admins/platform admins bypass membership and are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joaocarvoli joaocarvoli merged commit 325d5b1 into main Jun 9, 2026
4 checks passed
@joaocarvoli joaocarvoli deleted the chore/prune-seeded-language-members branch June 9, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant