[Schema] Make keypairs.user_id hold the user's uuid
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
## Objective
Leave keypairs with a single owner column named user_id holding users.uuid — the value the code already means when it says user_id.
## Background
keypairs carries two owner columns. user_id is a String(256) holding the user's email, indexed and with no foreign key; user is a GUID with a real foreign key to users.uuid. The v2 stack has already settled the ambiguity in favour of the uuid: KeyPairRow.to_data() fills KeyPairData.user_id from the user column, and both KeyPairNode.user_id and the v2 keypair DTO document the field as the owner's uuid. The column actually named user_id is the one the API does not mean.
Nothing keeps the email copy in step with users.email either, so the readers that match on it — keypair deactivation in the auth db_source, the vfolder repository join, the legacy GraphQL keypair and resource-policy queries, the stats reporter group-by — join on a mutable string instead of the primary key.
## Acceptance Criteria
- keypairs ends with one owner column, named user_id, GUID, NOT NULL, foreign key to users.uuid; the email column and the separate user column are both gone.
- A migration performs the consolidation and is verified against a populated database; the downgrade restores the email column and backfills it from users.email.
- Every reader that matched keypairs by the user's email queries by uuid instead: the auth db_source deactivation, the vfolder repository join, the legacy GraphQL keypair and resource-policy queries, and the stats reporter group-by.
- KeyPairRow.user, the relationship's foreign_keys reference and the user/keypair join helpers are renamed; KeyPairRow.to_data() reads the column directly.
- No API field changes — KeyPairNode.user_id and the v2 DTO already carry the uuid.
- Tests and fixtures that seed or delete keypairs by email are moved onto the uuid.
## Notes
- Overlaps with BA-7198, which lists user_id among the columns to tighten to NOT NULL. Land this first, or drop user_id from that issue's list.
- Roughly 350 lines: migration, model, ~16 reader sites, tests.
JIRA Issue: BA-7206
Contributor guide
Research direction
Start by locating the keypair model and migration, then trace KeyPairRow, the auth db_source deactivation, vfolder repository join, legacy GraphQL queries, stats reporter, and related tests and fixtures. Verify the migration on populated data, update every email-based reader and seed/delete path to use the user's UUID, and confirm downgrade restores the email column from users.email without changing API fields.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- databases
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100