Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
18 KiB
Märchenzauber Database Documentation
Project Information
- Project Name: Maerchenzauber
- Project ID: dyywxrmonxoiojsjmymc
- Region: eu-central-1
- Status: ACTIVE_HEALTHY
- Database Host: db.dyywxrmonxoiojsjmymc.supabase.co
- Postgres Version: 15.8.1.079
- Created: 2025-04-29T21:43:53.3429Z
Database Schema Overview
The Märchenzauber database is designed to support a storytelling application with character creation and story generation capabilities. It uses a custom JWT authentication system alongside standard Supabase auth.
Tables
1. characters
Stores user-created characters for storytelling.
| Column | Type | Default | Nullable | Description |
|---|---|---|---|---|
id |
uuid | uuid_generate_v4() | NO | Primary key |
user_id |
text | - | NO | User identifier (custom JWT) |
name |
varchar | - | NO | Character name |
original_description |
text | - | NO | Original character description |
character_description_prompt |
text | - | NO | AI prompt for character |
image_url |
text | - | NO | Character image URL |
source_image_url |
text | - | YES | Original source image |
is_animal |
boolean | false | YES | Whether character is an animal |
animal_type |
varchar | 'unspecified animal' | YES | Type of animal if applicable |
images_data |
jsonb | '[]'::jsonb | YES | JSON array of image data |
created_at |
timestamptz | now() | NO | Creation timestamp |
updated_at |
timestamptz | now() | NO | Last update timestamp |
Indexes:
characters_pkey(PRIMARY KEY on id)characters_user_id_id_key(UNIQUE on user_id, id)idx_characters_user_id(on user_id)idx_characters_images_data(GIN index on images_data)
Relationships:
- Referenced by
stories.character_id - Referenced by
errors.character_id
2. stories
Stores generated stories with their associated characters and content.
| Column | Type | Default | Nullable | Description |
|---|---|---|---|---|
id |
uuid | uuid_generate_v4() | NO | Primary key |
user_id |
text | - | NO | User identifier (custom JWT) |
title |
varchar | - | YES | Story title |
story_prompt |
text | - | NO | Prompt used to generate story |
story_text |
text | - | YES | Generated story content |
is_animal_story |
boolean | false | YES | Whether it's an animal story |
animal_type |
varchar | 'unspecified animal' | YES | Type of animal if applicable |
character_id |
uuid | - | YES | Reference to character |
character_name |
varchar | - | YES | Character name (denormalized) |
used_settings |
jsonb | - | YES | Settings used for generation |
characters_data |
jsonb | '[]'::jsonb | YES | JSON array of character data |
pages_data |
jsonb | '[]'::jsonb | YES | JSON array of page data |
created_at |
timestamptz | now() | NO | Creation timestamp |
updated_at |
timestamptz | now() | NO | Last update timestamp |
Indexes:
stories_pkey(PRIMARY KEY on id)stories_user_id_id_key(UNIQUE on user_id, id)idx_stories_user_id(on user_id)idx_stories_character_id(on character_id)idx_stories_characters_data(GIN index on characters_data)idx_stories_pages_data(GIN index on pages_data)
Foreign Keys:
character_id→characters.id
3. creators
Stores information about story and illustration creators (admin-managed).
| Column | Type | Default | Nullable | Description |
|---|---|---|---|---|
id |
uuid | uuid_generate_v4() | NO | Primary key |
creator_id |
varchar | - | NO | Unique creator identifier |
name |
varchar | - | NO | Creator name |
type |
varchar | - | NO | 'illustrator' or 'author' |
system_prompt |
text | - | NO | AI system prompt |
description |
text | - | NO | Creator description |
profile_picture |
text | - | YES | Profile picture URL |
extra_prompt_beginning |
text | - | YES | Additional prompt prefix |
extra_prompt_end |
text | - | YES | Additional prompt suffix |
created_at |
timestamptz | now() | NO | Creation timestamp |
updated_at |
timestamptz | now() | NO | Last update timestamp |
Indexes:
creators_pkey(PRIMARY KEY on id)creators_creator_id_key(UNIQUE on creator_id)
Constraints:
- CHECK:
typemust be either 'illustrator' or 'author'
4. errors
Logs errors that occur during character creation or story generation.
| Column | Type | Default | Nullable | Description |
|---|---|---|---|---|
id |
uuid | uuid_generate_v4() | NO | Primary key |
user_id |
text | - | NO | User identifier |
story_id |
uuid | - | YES | Related story ID |
character_id |
uuid | - | YES | Related character ID |
error_type |
varchar | - | NO | Type of error |
error_details |
jsonb | - | NO | Detailed error information |
created_at |
timestamptz | now() | NO | Error timestamp |
Indexes:
errors_pkey(PRIMARY KEY on id)idx_errors_user_id(on user_id)idx_errors_story_id(on story_id)idx_errors_character_id(on character_id)
Foreign Keys:
story_id→stories.idcharacter_id→characters.id
5. story_logbooks
Comprehensive logs of the story creation process including all AI prompts, responses, and timing data.
| Column | Type | Default | Nullable | Description |
|---|---|---|---|---|
id |
uuid | gen_random_uuid() | NO | Primary key |
story_id |
uuid | - | NO | Related story ID |
user_id |
uuid | - | NO | User identifier |
character_ids |
uuid[] | '{}' | YES | Array of character IDs used in story |
start_time |
timestamptz | - | NO | Story creation start time |
end_time |
timestamptz | - | YES | Story creation end time |
total_duration_ms |
integer | - | YES | Total duration in milliseconds |
success |
boolean | false | YES | Whether creation was successful |
environment |
text | 'production' | YES | Environment (development/production) |
entries |
jsonb | '[]'::jsonb | NO | Array of log entries with prompts/responses |
metadata |
jsonb | '{}'::jsonb | NO | Additional metadata (characters, settings, etc.) |
summary |
text | - | YES | Human-readable summary of the creation process |
created_at |
timestamptz | now() | YES | Log creation timestamp |
updated_at |
timestamptz | now() | YES | Last update timestamp |
Indexes:
story_logbooks_pkey(PRIMARY KEY on id)idx_story_logbooks_story_id(on story_id)idx_story_logbooks_user_id(on user_id)idx_story_logbooks_character_ids(GIN index on character_ids)idx_story_logbooks_created_at(on created_at DESC)idx_story_logbooks_success(on success)
JSONB Structure:
entries array contains objects with:
{
"timestamp": "ISO 8601 timestamp",
"step": "step_name",
"type": "prompt|response|error|info|character|illustration",
"data": {}, // Context-specific data
"duration": 1234 // Optional, in milliseconds
}
metadata object contains:
{
"storyTitle": "string",
"characters": [{
"id": "uuid",
"name": "string",
"description": "string",
"isAnimal": boolean,
"animalType": "string"
}],
"storyDescription": "string",
"language": "string",
"authorId": "uuid",
"illustratorId": "uuid",
"pageCount": number,
"imageCount": number,
"success": boolean,
"errors": []
}
Database Functions
Authentication & Authorization Functions
-
auth_is_admin()- Returns:
boolean - Checks if current user has admin privileges
- Returns:
-
authenticate_custom_jwt(jwt_token text)- Returns:
json - Validates and authenticates custom JWT tokens
- Returns:
-
current_user_id()- Returns:
text - Gets current user ID from auth context or JWT claims
- Returns:
-
current_user_uuid()- Returns:
uuid - Gets current user UUID from auth context
- Returns:
-
user_owns_resource(resource_user_id text)- Returns:
boolean - Checks if current user owns a specific resource
- Returns:
Utility Functions
-
debug_jwt_context()- Returns:
json - Debugging function to inspect JWT context
- Returns:
-
get_current_user_context()- Returns:
json - Gets complete current user context information
- Returns:
-
set_request_user_id(user_id uuid/text)- Returns:
void - Sets the request user ID (overloaded for uuid and text)
- Returns:
Data Operation Functions
-
execute_as_user(p_token text, p_operation text, p_params jsonb)- Returns:
jsonb - Executes operations on behalf of a user with proper authentication
- Returns:
-
create_test_character(p_user_id text, p_name text, p_description text, p_prompt text, p_image_url text)- Returns:
jsonb - Creates a test character (likely for testing purposes)
- Returns:
Row Level Security (RLS) Policies
Characters Table
- Users can view own characters: SELECT where
user_idmatches current user - Users can insert own characters: INSERT where
user_idmatches current user - Users can update own characters: UPDATE where
user_idmatches current user - Users can delete own characters: DELETE where
user_idmatches current user - Service role full access: Full access for service_role
Stories Table
- Users can view own stories: SELECT where
user_idmatches current user - Users can insert own stories: INSERT where
user_idmatches current user - Users can update own stories: UPDATE where
user_idmatches current user - Users can delete own stories: DELETE where
user_idmatches current user - Service role full access: Full access for service_role
Creators Table
- All users can view creators: SELECT for all authenticated users
- Admins can insert creators: INSERT only for admins
- Admins can update creators: UPDATE only for admins
- Admins can delete creators: DELETE only for admins
- Service role full access: Full access for service_role
Errors Table
- Users can insert errors: Any authenticated user can log errors
- Admins can view errors: SELECT only for admins
- Admins can update errors: UPDATE only for admins
- Admins can delete errors: DELETE only for admins
- Service role full access: Full access for service_role
Story Logbooks Table
- Service role full access: Full access for service_role (backend handles auth via Mana Core)
Enabled Extensions
Core Extensions
uuid-ossp(v1.1): UUID generationpgcrypto(v1.3): Cryptographic functionspg_stat_statements(v1.10): Query performance trackingpgjwt(v0.2.0): JWT handling for PostgreSQL
GraphQL & Vault
pg_graphql(v1.5.11): GraphQL supportsupabase_vault(v0.3.1): Supabase Vault for secrets management
Migration History
The database has undergone 43 migrations, primarily focused on:
- Custom JWT authentication implementation
- RLS policy refinements for security
- Storage integration with custom auth
- Performance optimizations
- Security enhancements
Key migration themes:
- Initial custom JWT verification setup (20250501)
- RLS policies for JWT authentication (20250501)
- Auth helper functions implementation (20250705)
- Storage RLS policies with custom JWT support (20250705)
- Performance and security optimizations (20250706-20250712)
- Story logbooks table for comprehensive creation tracking (20250910)
Security Advisories
Warnings
-
Function Search Path Mutable (SECURITY)
- Function
public.execute_as_userhas a mutable search_path - Remediation Guide
- Function
-
Auth OTP Long Expiry (SECURITY)
- OTP expiry is set to more than an hour
- Recommendation: Set to less than an hour
- Security Best Practices
Performance Issues
-
RLS Performance (PERFORMANCE)
- Multiple RLS policies re-evaluate
current_setting()orauth.<function>()for each row - Affected tables:
stories,characters,errors - Solution: Replace
auth.<function>()with(select auth.<function>()) - Performance Guide
- Multiple RLS policies re-evaluate
-
Unused Indexes (INFO)
- Several indexes have never been used and could be removed:
idx_errors_user_ididx_errors_story_ididx_characters_images_dataidx_stories_pages_dataidx_stories_characters_data
- Several indexes have never been used and could be removed:
TypeScript Types
The database includes generated TypeScript types for all tables and functions, providing type-safe access from client applications. Key types include:
// Table row types
type Character = {
id: string;
user_id: string;
name: string;
original_description: string;
character_description_prompt: string;
image_url: string;
source_image_url: string | null;
is_animal: boolean | null;
animal_type: string | null;
images_data: Json | null;
created_at: string;
updated_at: string;
};
type Story = {
id: string;
user_id: string;
title: string | null;
story_prompt: string;
story_text: string | null;
is_animal_story: boolean | null;
animal_type: string | null;
character_id: string | null;
character_name: string | null;
used_settings: Json | null;
characters_data: Json | null;
pages_data: Json | null;
created_at: string;
updated_at: string;
};
type Creator = {
id: string;
creator_id: string;
name: string;
type: string;
system_prompt: string;
description: string;
profile_picture: string | null;
extra_prompt_beginning: string | null;
extra_prompt_end: string | null;
created_at: string;
updated_at: string;
};
type Error = {
id: string;
user_id: string;
story_id: string | null;
character_id: string | null;
error_type: string;
error_details: Json;
created_at: string;
};
type StoryLogbook = {
id: string;
story_id: string;
user_id: string;
character_ids: string[] | null;
start_time: string;
end_time: string | null;
total_duration_ms: number | null;
success: boolean | null;
environment: string | null;
entries: Json;
metadata: Json;
summary: string | null;
created_at: string | null;
updated_at: string | null;
};
Development Recommendations
Immediate Actions Required
- Fix Function Security: Update
execute_as_userfunction to set search_path - Reduce OTP Expiry: Configure OTP to expire within 1 hour
- Optimize RLS Policies: Update policies to use subqueries for better performance
Performance Optimizations
- Review Unused Indexes: Consider removing unused GIN indexes on JSONB columns
- RLS Query Optimization: Implement suggested RLS performance improvements
Best Practices
- Use TypeScript Types: Leverage generated types for type-safe database access
- Monitor Query Performance: Use
pg_stat_statementsto track slow queries - Regular Security Audits: Run security advisors regularly after schema changes
- Test with Custom JWT: Ensure all features work with custom JWT authentication
Authentication Architecture
The system supports dual authentication methods:
- Standard Supabase Auth: Using
auth.uid() - Custom JWT: Using JWT claims from request headers
All RLS policies use COALESCE to support both authentication methods, prioritizing:
- Supabase auth UID
- Custom JWT claims (
subfield) - Fallback to
current_user_id()function
This architecture allows flexibility in authentication while maintaining security through consistent RLS policies.