feat(spaces): replace sequential space ID with UUID#2983
feat(spaces): replace sequential space ID with UUID#2983vseehausen wants to merge 4 commits intomainfrom
Conversation
4509421 to
2172096
Compare
|
@vseehausen what happens to existing Spaces, are we going to migrate them? |
|
@claude review |
|
Claude finished @katspaugh's task —— View job
ReviewOverall this is a well-structured migration. A few things to address: Migration (critical)
Code
Minor / nits
|
Sequential SERIAL int PKs leak total space count and enable enumeration. Uses add-backfill-swap pattern since PG can't ALTER int→uuid in-place. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2172096 to
cd152cb
Compare
Change DB entity PK from SERIAL int to uuid, override RowSchema's int id with UuidSchema in domain schema, and update repository signatures and DTO ApiProperty types from Number to String. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ParseIntPipe + RowSchema.shape.id with UuidSchema for all spaceId route params. userId params in MembersController stay as int. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace faker.number.int() with faker.string.uuid() for space IDs in builders, e2e specs, and integration specs. User/member IDs stay as integers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cd152cb to
cd721bf
Compare
WA-1583
Why
Sequential auto-incrementing space IDs leak the total number of spaces and allow enumeration attacks. We replace them with server-generated UUID v4.
We evaluated external ID libraries (nanoid, cuid2, ksuid) but chose native PG
gen_random_uuid()— zero dependencies, built-in validation via the existingUuidSchema, and 16-byte binary storage with native indexing. No app-side generation needed.What changes
SERIAL int→uuid DEFAULT gen_random_uuid()onspaces.idand all FK references (members,space_safes,space_address_book_items)SpaceSchemaoverridesRowSchema.idwithUuidSchema; DB entity uses@PrimaryGeneratedColumn('uuid')ParseIntPipe+RowSchema.shape.id→UuidSchemafor allspaceIdparams;userIdstays as intApiProperty({ type: Number })→Stringfor space ID fieldsfaker.string.uuid()Scope
Only
spaces.idand its FK references change. Child table own PKs,users, andwalletsstay asSERIAL int.RowSchemais untouched.Test plan
yarn lint-checkpassesyarn buildcompilesyarn test:unitpassesyarn test:integrationpasses (requires test DB)yarn test:e2epasses (requires Redis + RabbitMQ)yarn migration:revertrestores integer IDs🤖 Generated with Claude Code