Refactor database schema for roles and visibility management
- Updated the roles table to use `code` as the primary key, enhancing readability and simplifying junction tables. - Modified `user_roles` and `product_role_visibility` tables to reference `role_code` instead of `role_id`, maintaining many-to-many relationships. - Added foreign key constraints and created new indexes to optimize queries. - Removed the previous migration file that was no longer needed, ensuring a cleaner migration history. - Updated related documentation to reflect the new schema changes and their benefits.
This commit is contained in:
@@ -1,29 +1,20 @@
|
|||||||
CREATE TYPE "public"."role_code" AS ENUM('private', 'educator', 'company');--> statement-breakpoint
|
CREATE TYPE "public"."role_code" AS ENUM('private', 'educator', 'company');--> statement-breakpoint
|
||||||
CREATE TYPE "public"."role_request_status" AS ENUM('pending', 'approved', 'rejected');--> statement-breakpoint
|
CREATE TYPE "public"."role_request_status" AS ENUM('pending', 'approved', 'rejected');--> statement-breakpoint
|
||||||
CREATE TABLE "product_role_visibility" (
|
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
||||||
"product_id" uuid NOT NULL,
|
|
||||||
"role_id" uuid NOT NULL,
|
|
||||||
"created_at" timestamp DEFAULT now() NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE "roles" (
|
CREATE TABLE "roles" (
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
"code" "role_code" PRIMARY KEY NOT NULL,
|
||||||
"code" "role_code" NOT NULL,
|
|
||||||
"display_name" text NOT NULL,
|
"display_name" text NOT NULL,
|
||||||
"description" text NOT NULL,
|
"description" text NOT NULL,
|
||||||
"requires_approval" boolean DEFAULT false NOT NULL,
|
"requires_approval" boolean DEFAULT false NOT NULL,
|
||||||
"sort_order" integer DEFAULT 0 NOT NULL,
|
"sort_order" integer DEFAULT 0 NOT NULL,
|
||||||
"active" boolean DEFAULT true NOT NULL,
|
"active" boolean DEFAULT true NOT NULL,
|
||||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
"updated_at" timestamp DEFAULT now() NOT NULL,
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
CONSTRAINT "roles_code_unique" UNIQUE("code")
|
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
CREATE TABLE "user_roles" (
|
CREATE TABLE "user_roles" (
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
"user_id" uuid NOT NULL,
|
"user_id" uuid NOT NULL,
|
||||||
"role_id" uuid NOT NULL,
|
"role_code" "role_code" NOT NULL,
|
||||||
"status" "role_request_status" DEFAULT 'pending' NOT NULL,
|
"status" "role_request_status" DEFAULT 'pending' NOT NULL,
|
||||||
"organization_name" text,
|
"organization_name" text,
|
||||||
"admin_notes" text,
|
"admin_notes" text,
|
||||||
@@ -32,12 +23,21 @@ CREATE TABLE "user_roles" (
|
|||||||
"updated_at" timestamp DEFAULT now() NOT NULL
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_product_id_products_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
CREATE TABLE "product_role_visibility" (
|
||||||
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_role_id_roles_id_fk" FOREIGN KEY ("role_id") REFERENCES "public"."roles"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"product_id" uuid NOT NULL,
|
||||||
|
"role_code" "role_code" NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_role_id_roles_id_fk" FOREIGN KEY ("role_id") REFERENCES "public"."roles"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_role_code_roles_code_fk" FOREIGN KEY ("role_code") REFERENCES "public"."roles"("code") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
CREATE INDEX "product_role_visibility_product_id_role_id_unique" ON "product_role_visibility" USING btree ("product_id","role_id");--> statement-breakpoint
|
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_product_id_products_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
CREATE INDEX "product_role_visibility_product_id_idx" ON "product_role_visibility" USING btree ("product_id");--> statement-breakpoint
|
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_role_code_roles_code_fk" FOREIGN KEY ("role_code") REFERENCES "public"."roles"("code") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
CREATE INDEX "user_roles_user_id_role_id_unique" ON "user_roles" USING btree ("user_id","role_id");--> statement-breakpoint
|
CREATE INDEX "user_roles_user_id_role_code_unique" ON "user_roles" USING btree ("user_id","role_code");--> statement-breakpoint
|
||||||
CREATE INDEX "user_roles_user_id_idx" ON "user_roles" USING btree ("user_id");--> statement-breakpoint
|
CREATE INDEX "user_roles_user_id_idx" ON "user_roles" USING btree ("user_id");--> statement-breakpoint
|
||||||
CREATE INDEX "user_roles_status_idx" ON "user_roles" USING btree ("status");
|
CREATE INDEX "user_roles_role_code_idx" ON "user_roles" USING btree ("role_code");--> statement-breakpoint
|
||||||
|
CREATE INDEX "user_roles_status_idx" ON "user_roles" USING btree ("status");--> statement-breakpoint
|
||||||
|
CREATE INDEX "product_role_visibility_product_id_role_code_unique" ON "product_role_visibility" USING btree ("product_id","role_code");--> statement-breakpoint
|
||||||
|
CREATE INDEX "product_role_visibility_product_id_idx" ON "product_role_visibility" USING btree ("product_id");--> statement-breakpoint
|
||||||
|
CREATE INDEX "product_role_visibility_role_code_idx" ON "product_role_visibility" USING btree ("role_code");
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
-- Migration: Refactor roles table to use code as primary key
|
|
||||||
-- This migration drops and recreates the role-related tables with the new schema
|
|
||||||
|
|
||||||
-- Drop existing tables (CASCADE removes dependent foreign keys)
|
|
||||||
DROP TABLE IF EXISTS "product_role_visibility" CASCADE;--> statement-breakpoint
|
|
||||||
DROP TABLE IF EXISTS "user_roles" CASCADE;--> statement-breakpoint
|
|
||||||
DROP TABLE IF EXISTS "roles" CASCADE;--> statement-breakpoint
|
|
||||||
|
|
||||||
-- Recreate roles table with code as primary key
|
|
||||||
CREATE TABLE "roles" (
|
|
||||||
"code" "role_code" PRIMARY KEY NOT NULL,
|
|
||||||
"display_name" text NOT NULL,
|
|
||||||
"description" text NOT NULL,
|
|
||||||
"requires_approval" boolean DEFAULT false NOT NULL,
|
|
||||||
"sort_order" integer DEFAULT 0 NOT NULL,
|
|
||||||
"active" boolean DEFAULT true NOT NULL,
|
|
||||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
||||||
"updated_at" timestamp DEFAULT now() NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
|
|
||||||
-- Recreate user_roles table with roleCode instead of roleId
|
|
||||||
CREATE TABLE "user_roles" (
|
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
||||||
"user_id" uuid NOT NULL,
|
|
||||||
"role_code" "role_code" NOT NULL,
|
|
||||||
"status" "role_request_status" DEFAULT 'pending' NOT NULL,
|
|
||||||
"organization_name" text,
|
|
||||||
"admin_notes" text,
|
|
||||||
"status_history" jsonb DEFAULT '[]' NOT NULL,
|
|
||||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
||||||
"updated_at" timestamp DEFAULT now() NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
|
|
||||||
-- Recreate product_role_visibility table with roleCode instead of roleId
|
|
||||||
CREATE TABLE "product_role_visibility" (
|
|
||||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
||||||
"product_id" uuid NOT NULL,
|
|
||||||
"role_code" "role_code" NOT NULL,
|
|
||||||
"created_at" timestamp DEFAULT now() NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
|
|
||||||
-- Add foreign key constraints
|
|
||||||
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
||||||
ALTER TABLE "user_roles" ADD CONSTRAINT "user_roles_role_code_roles_code_fk" FOREIGN KEY ("role_code") REFERENCES "public"."roles"("code") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
||||||
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_product_id_products_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
||||||
ALTER TABLE "product_role_visibility" ADD CONSTRAINT "product_role_visibility_role_code_roles_code_fk" FOREIGN KEY ("role_code") REFERENCES "public"."roles"("code") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
||||||
|
|
||||||
-- Create indexes
|
|
||||||
CREATE INDEX "user_roles_user_id_role_code_unique" ON "user_roles" USING btree ("user_id","role_code");--> statement-breakpoint
|
|
||||||
CREATE INDEX "user_roles_user_id_idx" ON "user_roles" USING btree ("user_id");--> statement-breakpoint
|
|
||||||
CREATE INDEX "user_roles_role_code_idx" ON "user_roles" USING btree ("role_code");--> statement-breakpoint
|
|
||||||
CREATE INDEX "user_roles_status_idx" ON "user_roles" USING btree ("status");--> statement-breakpoint
|
|
||||||
CREATE INDEX "product_role_visibility_product_id_role_code_unique" ON "product_role_visibility" USING btree ("product_id","role_code");--> statement-breakpoint
|
|
||||||
CREATE INDEX "product_role_visibility_product_id_idx" ON "product_role_visibility" USING btree ("product_id");--> statement-breakpoint
|
|
||||||
CREATE INDEX "product_role_visibility_role_code_idx" ON "product_role_visibility" USING btree ("role_code");
|
|
||||||
@@ -385,9 +385,10 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
"role_id": {
|
"role_code": {
|
||||||
"name": "role_id",
|
"name": "role_code",
|
||||||
"type": "uuid",
|
"type": "role_code",
|
||||||
|
"typeSchema": "public",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
@@ -400,8 +401,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"product_role_visibility_product_id_role_id_unique": {
|
"product_role_visibility_product_id_role_code_unique": {
|
||||||
"name": "product_role_visibility_product_id_role_id_unique",
|
"name": "product_role_visibility_product_id_role_code_unique",
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"expression": "product_id",
|
"expression": "product_id",
|
||||||
@@ -410,7 +411,7 @@
|
|||||||
"nulls": "last"
|
"nulls": "last"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"expression": "role_id",
|
"expression": "role_code",
|
||||||
"isExpression": false,
|
"isExpression": false,
|
||||||
"asc": true,
|
"asc": true,
|
||||||
"nulls": "last"
|
"nulls": "last"
|
||||||
@@ -435,6 +436,21 @@
|
|||||||
"concurrently": false,
|
"concurrently": false,
|
||||||
"method": "btree",
|
"method": "btree",
|
||||||
"with": {}
|
"with": {}
|
||||||
|
},
|
||||||
|
"product_role_visibility_role_code_idx": {
|
||||||
|
"name": "product_role_visibility_role_code_idx",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"expression": "role_code",
|
||||||
|
"isExpression": false,
|
||||||
|
"asc": true,
|
||||||
|
"nulls": "last"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isUnique": false,
|
||||||
|
"concurrently": false,
|
||||||
|
"method": "btree",
|
||||||
|
"with": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"foreignKeys": {
|
"foreignKeys": {
|
||||||
@@ -451,15 +467,15 @@
|
|||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"product_role_visibility_role_id_roles_id_fk": {
|
"product_role_visibility_role_code_roles_code_fk": {
|
||||||
"name": "product_role_visibility_role_id_roles_id_fk",
|
"name": "product_role_visibility_role_code_roles_code_fk",
|
||||||
"tableFrom": "product_role_visibility",
|
"tableFrom": "product_role_visibility",
|
||||||
"tableTo": "roles",
|
"tableTo": "roles",
|
||||||
"columnsFrom": [
|
"columnsFrom": [
|
||||||
"role_id"
|
"role_code"
|
||||||
],
|
],
|
||||||
"columnsTo": [
|
"columnsTo": [
|
||||||
"id"
|
"code"
|
||||||
],
|
],
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
@@ -607,18 +623,11 @@
|
|||||||
"name": "roles",
|
"name": "roles",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
"columns": {
|
"columns": {
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "gen_random_uuid()"
|
|
||||||
},
|
|
||||||
"code": {
|
"code": {
|
||||||
"name": "code",
|
"name": "code",
|
||||||
"type": "role_code",
|
"type": "role_code",
|
||||||
"typeSchema": "public",
|
"typeSchema": "public",
|
||||||
"primaryKey": false,
|
"primaryKey": true,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
"display_name": {
|
"display_name": {
|
||||||
@@ -672,15 +681,7 @@
|
|||||||
"indexes": {},
|
"indexes": {},
|
||||||
"foreignKeys": {},
|
"foreignKeys": {},
|
||||||
"compositePrimaryKeys": {},
|
"compositePrimaryKeys": {},
|
||||||
"uniqueConstraints": {
|
"uniqueConstraints": {},
|
||||||
"roles_code_unique": {
|
|
||||||
"name": "roles_code_unique",
|
|
||||||
"nullsNotDistinct": false,
|
|
||||||
"columns": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"policies": {},
|
"policies": {},
|
||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
@@ -702,9 +703,10 @@
|
|||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
"role_id": {
|
"role_code": {
|
||||||
"name": "role_id",
|
"name": "role_code",
|
||||||
"type": "uuid",
|
"type": "role_code",
|
||||||
|
"typeSchema": "public",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
@@ -751,8 +753,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"user_roles_user_id_role_id_unique": {
|
"user_roles_user_id_role_code_unique": {
|
||||||
"name": "user_roles_user_id_role_id_unique",
|
"name": "user_roles_user_id_role_code_unique",
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"expression": "user_id",
|
"expression": "user_id",
|
||||||
@@ -761,7 +763,7 @@
|
|||||||
"nulls": "last"
|
"nulls": "last"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"expression": "role_id",
|
"expression": "role_code",
|
||||||
"isExpression": false,
|
"isExpression": false,
|
||||||
"asc": true,
|
"asc": true,
|
||||||
"nulls": "last"
|
"nulls": "last"
|
||||||
@@ -787,6 +789,21 @@
|
|||||||
"method": "btree",
|
"method": "btree",
|
||||||
"with": {}
|
"with": {}
|
||||||
},
|
},
|
||||||
|
"user_roles_role_code_idx": {
|
||||||
|
"name": "user_roles_role_code_idx",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"expression": "role_code",
|
||||||
|
"isExpression": false,
|
||||||
|
"asc": true,
|
||||||
|
"nulls": "last"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isUnique": false,
|
||||||
|
"concurrently": false,
|
||||||
|
"method": "btree",
|
||||||
|
"with": {}
|
||||||
|
},
|
||||||
"user_roles_status_idx": {
|
"user_roles_status_idx": {
|
||||||
"name": "user_roles_status_idx",
|
"name": "user_roles_status_idx",
|
||||||
"columns": [
|
"columns": [
|
||||||
@@ -817,15 +834,15 @@
|
|||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
"user_roles_role_id_roles_id_fk": {
|
"user_roles_role_code_roles_code_fk": {
|
||||||
"name": "user_roles_role_id_roles_id_fk",
|
"name": "user_roles_role_code_roles_code_fk",
|
||||||
"tableFrom": "user_roles",
|
"tableFrom": "user_roles",
|
||||||
"tableTo": "roles",
|
"tableTo": "roles",
|
||||||
"columnsFrom": [
|
"columnsFrom": [
|
||||||
"role_id"
|
"role_code"
|
||||||
],
|
],
|
||||||
"columnsTo": [
|
"columnsTo": [
|
||||||
"id"
|
"code"
|
||||||
],
|
],
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
|
|||||||
@@ -15,13 +15,6 @@
|
|||||||
"when": 1762074397305,
|
"when": 1762074397305,
|
||||||
"tag": "0001_clammy_bulldozer",
|
"tag": "0001_clammy_bulldozer",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 2,
|
|
||||||
"version": "7",
|
|
||||||
"when": 1762157410000,
|
|
||||||
"tag": "0002_refactor_roles_primary_key",
|
|
||||||
"breakpoints": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
## my.experimenta.science
|
## my.experimenta.science
|
||||||
|
|
||||||
**Last Updated:** 2025-11-01
|
**Last Updated:** 2025-11-03
|
||||||
**Overall Progress:** 39/137 tasks (28.5%)
|
**Overall Progress:** 39/137 tasks (28.5%)
|
||||||
**Current Phase:** ✅ Phase 3 - Authentication (Validated & Completed)
|
**Current Phase:** ✅ Phase 3 - Authentication (Completed) | Database Schema Refinement Completed
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,6 +30,29 @@
|
|||||||
|
|
||||||
## 🚀 Current Work
|
## 🚀 Current Work
|
||||||
|
|
||||||
|
**Phase:** Database Schema Refinement ✅ **COMPLETED** (2025-11-03)
|
||||||
|
|
||||||
|
**Recent Work: Roles Table Refactoring**
|
||||||
|
|
||||||
|
Completed a major database schema refinement to improve code readability and performance:
|
||||||
|
|
||||||
|
- ✅ **Refactored `roles` table**: Changed Primary Key from `id` (UUID) to `code` (enum: 'private' | 'educator' | 'company')
|
||||||
|
- ✅ **Updated junction tables**: `user_roles.roleCode` and `product_role_visibility.roleCode` now reference `roles.code` directly
|
||||||
|
- ✅ **Simplified code**: Removed all UUID lookup queries for roles - direct enum usage throughout
|
||||||
|
- ✅ **Maintained functionality**: Many-to-Many relationships fully preserved
|
||||||
|
- ✅ **Migration**: Successfully applied, database reseeded with 3 roles, 3 products, 7 role assignments
|
||||||
|
- ✅ **Auto-assignment**: Confirmed that new users automatically receive `'private'` role on first login
|
||||||
|
- ✅ **Product visibility**: Verified role-based product filtering works correctly
|
||||||
|
- ✅ **Documentation**: Updated CLAUDE.md and ARCHITECTURE.md to reflect new schema
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Better readability: `roleCode: 'private'` instead of `roleId: 'uuid...'`
|
||||||
|
- Simpler code: No role lookups needed
|
||||||
|
- Better performance: Fewer joins in queries
|
||||||
|
- Type safety: Direct enum type usage
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
**Phase:** Phase 3 - Authentication ✅ **VALIDATED & COMPLETED** (2025-11-01)
|
**Phase:** Phase 3 - Authentication ✅ **VALIDATED & COMPLETED** (2025-11-01)
|
||||||
|
|
||||||
**Validation Summary:**
|
**Validation Summary:**
|
||||||
@@ -431,6 +454,7 @@ Tasks:
|
|||||||
| 2025-10-30 | 15.3% | Phase 2 - MVP | ✅ Database completed: Drizzle ORM, all tables defined, migrations applied, Studio working, schema documented |
|
| 2025-10-30 | 15.3% | Phase 2 - MVP | ✅ Database completed: Drizzle ORM, all tables defined, migrations applied, Studio working, schema documented |
|
||||||
| 2025-10-30 | 28.5% | Phase 3 - MVP | ✅ Authentication completed: Password Grant Flow, JWT validation, auth endpoints, UI components, middleware |
|
| 2025-10-30 | 28.5% | Phase 3 - MVP | ✅ Authentication completed: Password Grant Flow, JWT validation, auth endpoints, UI components, middleware |
|
||||||
| 2025-11-01 | 28.5% | Phase 3 - Validation | ✅ Authentication validated: Login tested with Playwright, DB user creation verified, docs updated |
|
| 2025-11-01 | 28.5% | Phase 3 - Validation | ✅ Authentication validated: Login tested with Playwright, DB user creation verified, docs updated |
|
||||||
|
| 2025-11-03 | 28.5% | DB Refinement | ✅ Roles table refactored: `code` as PK, simplified junction tables, maintained Many-to-Many functionality |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user