BAYAN uses Supabase (PostgreSQL) with Row-Level Security (RLS). All tables enforce per-user data isolation via auth.uid().
Entity Relationship Diagram
erDiagram
AUTH_USERS {
uuid id PK
text email
boolean is_anonymous
jsonb raw_user_meta_data
jsonb raw_app_meta_data
timestamptz created_at
timestamptz updated_at
}
PROFILES {
uuid id PK "FK → auth.users(id)"
text display_name
text avatar_url
text auth_provider "anonymous | google"
timestamptz created_at
timestamptz updated_at
}
DOCUMENTS {
uuid id PK "gen_random_uuid()"
uuid user_id FK "→ auth.users(id)"
text title "Default: مستند جديد"
text content "HTML content"
timestamptz created_at
timestamptz updated_at
}
SUMMARIES {
uuid id PK "gen_random_uuid()"
uuid document_id FK "→ documents(id)"
uuid user_id FK "→ auth.users(id)"
text original_text
text summary_text
integer word_count
real compression_ratio
timestamptz created_at
}
SETTINGS {
uuid id PK "gen_random_uuid()"
uuid user_id FK "→ auth.users(id)"
jsonb preferences "theme, font, size, etc."
timestamptz created_at
timestamptz updated_at
}
AUTH_USERS ||--|| PROFILES : "auto-created on signup"
AUTH_USERS ||--o{ DOCUMENTS : "owns"
AUTH_USERS ||--o| SETTINGS : "has"
DOCUMENTS ||--o{ SUMMARIES : "has"
AUTH_USERS ||--o{ SUMMARIES : "owns"
Table Details
profiles
Column
Type
Constraints
Description
id
uuid
PK, FK → auth.users
User ID from Supabase Auth
display_name
text
nullable
Display name (from Google or "ضيف")
avatar_url
text
nullable
Google profile picture URL
auth_provider
text
NOT NULL, default 'anonymous'
anonymous or google
created_at
timestamptz
NOT NULL, default now()
Account creation time
updated_at
timestamptz
NOT NULL, default now()
Last profile update
documents
Column
Type
Constraints
Description
id
uuid
PK, default gen_random_uuid()
Document unique ID
user_id
uuid
FK → auth.users, NOT NULL
Owner
title
text
default 'مستند جديد'
Document title
content
text
nullable
HTML content from editor
created_at
timestamptz
NOT NULL, default now()
Creation time
updated_at
timestamptz
NOT NULL, default now()
Last save time
summaries
Column
Type
Constraints
Description
id
uuid
PK, default gen_random_uuid()
Summary unique ID
document_id
uuid
FK → documents(id)
Parent document
user_id
uuid
FK → auth.users, NOT NULL
Owner
original_text
text
NOT NULL
Source text that was summarized
summary_text
text
NOT NULL
Generated summary
word_count
integer
nullable
Summary word count
compression_ratio
real
nullable
Compression percentage
created_at
timestamptz
NOT NULL, default now()
Generation time
settings
Column
Type
Constraints
Description
id
uuid
PK, default gen_random_uuid()
Setting record ID
user_id
uuid
FK → auth.users, UNIQUE
Owner (one per user)
preferences
jsonb
NOT NULL, default '{}'
All user preferences
created_at
timestamptz
NOT NULL, default now()
Creation time
updated_at
timestamptz
NOT NULL, default now()
Last update time
Row Level Security (RLS) Policies
All tables have RLS enabled. Policies follow the pattern:
-- SELECT: Users can only read their own dataCREATE POLICY "select_own" ONtableFORSELECTUSING (auth.uid() = user_id);
-- INSERT: Users can only insert their own data CREATE POLICY "insert_own" ONtableFORINSERTWITHCHECK (auth.uid() = user_id);
-- UPDATE: Users can only update their own dataCREATE POLICY "update_own" ONtableFORUPDATEUSING (auth.uid() = user_id);
-- DELETE: Users can only delete their own dataCREATE POLICY "delete_own" ONtableFORDELETEUSING (auth.uid() = user_id);