mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Implement self-hosted MCP server for admin actions, update AI generation tools in admin dashboard, and refine mobile app stores and components.
6.0 KiB
6.0 KiB
Database Schema
Entity Relationship Diagram
erDiagram
%% Core Authentication
auth_users {
uuid id PK
string email
jsonb raw_user_meta_data
}
%% User Management
profiles {
uuid id PK,FK "references auth.users"
text name
text avatar_url
text push_token
boolean is_premium
uuid couple_id FK
timestamptz created_at
timestamptz updated_at
}
couples {
uuid id PK
text invite_code UK
timestamptz created_at
}
%% Content
question_packs {
uuid id PK
text name
text description
text icon
boolean is_premium
boolean is_public
int sort_order
timestamptz created_at
}
questions {
uuid id PK
uuid pack_id FK
text text
text partner_text "for two-part questions"
int intensity "1-5"
text[] allowed_couple_genders "couple composition filter"
text[] target_user_genders "individual user filter"
text[] required_props "props/accessories required"
timestamptz created_at
}
%% Couple Pack Selection
couple_packs {
uuid couple_id PK,FK
uuid pack_id PK,FK
boolean enabled
timestamptz created_at
}
%% User Interaction
responses {
uuid id PK
uuid user_id FK
uuid question_id FK
uuid couple_id FK
answer_type answer "yes/no/maybe"
timestamptz created_at
}
matches {
uuid id PK
uuid couple_id FK
uuid question_id FK
match_type match_type "yes_yes/yes_maybe/maybe_maybe"
boolean is_new
timestamptz created_at
}
messages {
uuid id PK
uuid match_id FK
uuid user_id FK
text content
text media_path
timestamptz read_at
timestamptz created_at
}
%% Subscriptions
subscriptions {
uuid id PK
uuid user_id FK
text revenuecat_app_user_id
text product_id
subscription_status status
text[] entitlement_ids
timestamptz purchased_at
timestamptz expires_at
text original_transaction_id
text store
boolean is_sandbox
text cancel_reason
timestamptz grace_period_expires_at
timestamptz created_at
timestamptz updated_at
}
revenuecat_webhook_events {
uuid id PK
text event_id UK
text event_type
text app_user_id
timestamptz processed_at
jsonb payload
}
%% Feedback
feedback {
uuid id PK
uuid user_id FK
feedback_type type "bug/feature_request/general"
text title
text description
text screenshot_url
jsonb device_info
feedback_status status
text admin_notes
timestamptz created_at
timestamptz updated_at
}
%% Relationships
auth_users ||--|| profiles : "extends"
couples ||--o{ profiles : "has members"
couples ||--o{ couple_packs : "selects packs"
couples ||--o{ responses : "has responses"
couples ||--o{ matches : "has matches"
question_packs ||--o{ questions : "contains"
question_packs ||--o{ couple_packs : "selected by"
questions ||--o{ responses : "answered by"
questions ||--o{ matches : "generates"
profiles ||--o{ responses : "submits"
profiles ||--o{ feedback : "submits"
profiles ||--o{ subscriptions : "has"
matches ||--o{ messages : "has chat"
auth_users ||--o{ messages : "sends"
Enums
| Enum | Values |
|---|---|
answer_type |
yes, no, maybe |
match_type |
yes_yes, yes_maybe, maybe_maybe |
feedback_type |
bug, feature_request, general |
feedback_status |
new, reviewed, in_progress, resolved, closed |
subscription_status |
active, cancelled, expired, billing_issue, paused |
Key Flows
Response & Match Flow
- User submits response via
submit-responseedge function - Response saved to
responsestable (UPSERT onuser_id, question_id) - Function checks for partner's response on same question
- If both answered positively (not "no"), a
matchis created - Match triggers push notification to both partners
- Match unlocks chat thread in
messagestable
Couple Pairing Flow
- First user creates couple, gets
invite_code - Second user joins via
manage-coupleedge function with invite code - Both profiles'
couple_idset to same couple
Pack Selection Flow
- Couples can enable/disable packs via
couple_packsjunction table get_recommended_questions()function filters questions by enabled packs- Two-part questions show
partner_textto second responder
Question Targeting System
Questions can be targeted at specific audiences using two complementary filters:
| Field | Purpose | Level | Example |
|---|---|---|---|
allowed_couple_genders |
Couple composition filter | Couple | ['male+female', 'female+female'] |
target_user_genders |
Individual user filter | User | ['female', 'non-binary'] |
How targeting works:
-
Couple filter (
allowed_couple_genders): Questions only shown to couples matching the composition (e.g., same-sex specific questions) -
User filter (
target_user_genders): Controls who sees the question as initiator (first responder)- If user's gender matches → they can see and answer first
- If user's gender doesn't match → they only see it after partner answers (via
partner_text)
Example flow:
Question:
text: "Have your partner suck your tits"
partner_text: "Suck your partner's tits"
target_user_genders: ['female']
1. Female sees "Have your partner suck your tits" → swipes YES
2. Male sees "Suck your partner's tits" (partner_text, unlocked by her answer)
3. Both answered → Match created!
This ensures gender-appropriate phrasing while still allowing both partners to respond.