Database Schema Reference (Definitive)
Auto-generated from
supabase/migrations/00001through00047. 135 tables documented here across 47 migrations, on Supabase PostgreSQL with pgvector.Coverage gap (audit 2026-04-12): The repository now has 53 migration files producing 177 unique tables (180
CREATE TABLEstatements;organizations,intentions, andcontext_snapshotsare re-declared withIF NOT EXISTSin later migrations). Migrations00048_provider_abstraction.sql,00049_unified_life_foundation.sql,00050_intentions_project_management.sql,00051_life_domains_part1.sql,00052_life_domains_part2.sql, and00053_entity_registry_backfill.sqlare not yet reflected in the per-table sections below. For the authoritative full-table inventory seedata-model-complete.mdand the raw migration SQL undersupabase/migrations/.
Table of Contents
- Extensions
- Functions and Triggers (shared)
- Scheduled Jobs (pg_cron)
- Migration 00001 -- Initial Schema
- Migration 00002 -- Intentions
- Migration 00003 -- Sovereign AI
- Migration 00004 -- Federation
- Migration 00005 -- Marketplace
- Migration 00006 -- Governance
- Migration 00007 -- Web3
- Migration 00008 -- Federated Marketplace
- Migration 00009 -- Calling
- Migration 00010 -- Agent Memory
- Migration 00011 -- Privacy
- Migration 00012 -- Notifications
- Migration 00013 -- Presence
- Migration 00014 -- Audit
- Migration 00015 -- Plugins
- Migration 00016 -- Documents
- Migration 00017 -- Rules
- Migration 00018 -- Scheduled Jobs
- Migration 00019 -- Rate Limits
- Migration 00020 -- Event Store
- Migration 00021 -- Streaming
- Migration 00022 -- Orgs
- Migration 00023 -- Developer
- Migration 00024 -- Search
- Migration 00025 -- Data Portability
- Migration 00026 -- Preferences
- Migration 00027 -- Monitoring
- Migration 00028 -- Billing
- Migration 00029 -- Security
- Migration 00030 -- Lineage
- Migration 00031 -- Credential Wallet
- Migration 00032 -- Tools
- Migration 00033 -- Audio Intelligence
- Migration 00034 -- Always-On Audio
- Migration 00035 -- Device Commands
- Migration 00036 -- Agent Worker
- Migration 00037 -- LLM Routing Rules
- Migration 00038 -- Unified Scheduler
- Migration 00039 -- RLS Hardening
- Migration 00040 -- Wiki
- Migration 00041 -- Inventory
- Migration 00042 -- Deep Comms
- Migration 00043 -- Deep Voice
- Migration 00044 -- Email Client
- Migration 00045 -- Meetings
- Migration 00046 -- Contact Timeline
- Migration 00047 -- Device Push Tokens
- Entity Relationship Map
- Service-to-Table Map
Extensions
Enabled in migration 00001:
| Extension | Purpose |
|---|---|
uuid-ossp | UUID generation |
pgcrypto | Cryptographic functions (gen_random_uuid, gen_random_bytes) |
vector | pgvector -- vector embeddings and similarity search |
pg_cron | Scheduled jobs (enabled in 00018) |
Functions and Triggers (shared)
set_updated_at() (00033)
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$;
Used by: audio_sessions, voice_commands
trigger_set_updated_at()
Referenced by migrations 00041-00047 for updated_at auto-update on: inventory_items, inventory_spaces, inventory_maintenance, inbox_items, phone_lines, ivr_flows, email_folders, email_threads, email_signatures, meetings, meeting_participants, meeting_recordings, contact_notes.
update_user_preferences_updated_at() (00026)
CREATE OR REPLACE FUNCTION update_user_preferences_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$;
update_schedules_updated_at() (00038)
Same pattern, dedicated to the schedules table.
prevent_inventory_event_mutation() (00041)
Raises an exception on UPDATE or DELETE to enforce append-only on inventory_events.
append_command_progress() (00036)
CREATE OR REPLACE FUNCTION append_command_progress(
p_command_id uuid, p_owner_id uuid, p_entry jsonb
) RETURNS void
Atomically appends a progress entry to device_commands.progress JSONB array. SECURITY DEFINER.
Scheduled Jobs (pg_cron)
Defined in migration 00018:
| Name | Schedule | Action |
|---|---|---|
process-retention-daily | 0 2 * * * (daily 2 AM UTC) | Calls Edge Function process-retention |
check-audit-alerts | */15 * * * * (every 15 min) | Calls Edge Function check-audit-alerts |
sync-presence | * * * * * (every minute) | Calls Edge Function sync-presence |
weekly-digest | 0 8 * * 1 (Mon 8 AM UTC) | Calls Edge Function weekly-digest |
expire-document-jobs | 0 3 * * * (daily 3 AM UTC) | Expires pending document_jobs older than 7 days |
Migration 00001 -- Initial Schema
persons
Core contact entity. All contacts from all sources land here.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
emails | jsonb | default '[]' |
phones | jsonb | default '[]' |
addresses | jsonb | default '[]' |
tags | jsonb | default '[]' |
birthday | date | |
notes | text | |
avatar_url | text | |
sources | jsonb | default '[]' |
aliases | text[] | NOT NULL default '{}' (added 00033) |
phonetic_key | text | (added 00033) |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their persons" ON persons
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
persons_phoneticon(owner_id, phonetic_key)WHEREphonetic_key IS NOT NULL(00033)persons_aliasesusing GIN on(aliases)WHEREarray_length(aliases, 1) > 0(00033)
Services: DataService (CRUD), ETLService (sync from MS Graph), RulesService (tag updates), EntityMergeService (merge/delete), ContactTimelineService (tag/merge updates)
organizations
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
domain | text | |
industry | text | |
address | jsonb | |
phone | text | |
website | text | |
sources | jsonb | default '[]' |
slug | text | UNIQUE (added 00022) |
avatar_url | text | (added 00022) |
billing_plan | text | default 'free', CHECK IN ('free','pro','team','enterprise') (added 00022) |
billing_status | text | default 'active', CHECK IN ('active','past_due','canceled','trialing') (added 00022) |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their organizations" ON organizations
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Indexes:
organizations_owner_idon(owner_id)(00022)organizations_slugon(slug)(00022)
Services: DataService (CRUD)
channels
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
plugin_id | text | NOT NULL |
type | text | NOT NULL |
name | text | NOT NULL |
capabilities | jsonb | default '{}' |
config | jsonb | default '{}' |
enabled | boolean | default true |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their channels" ON channels
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Services: ChannelService, ConnectorService
conversations
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
title | text | |
channel_id | uuid | FK channels(id) |
type | text | NOT NULL |
participants | jsonb | default '[]' |
thread_type | text | NOT NULL default 'single_channel' (added 00042) |
related_conversation_ids | uuid[] | default '{}' (added 00042) |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their conversations" ON conversations
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Foreign Keys: channel_id -> channels(id)
Services: DataService (CRUD), InboxService (cross-channel queries)
messages
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
conversation_id | uuid | FK conversations(id) |
sender_person_id | uuid | FK persons(id) |
direction | text | NOT NULL |
body | text | |
content_type | text | default 'text/plain' |
timestamp | timestamptz | NOT NULL |
provider_message_id | text | |
metadata | jsonb | default '{}' |
email_thread_id | uuid | FK email_threads(id) ON DELETE SET NULL (added 00044) |
folder_id | uuid | FK email_folders(id) ON DELETE SET NULL (added 00044) |
cc | jsonb | default '[]' (added 00044) |
bcc | jsonb | default '[]' (added 00044) |
reply_to | text | (added 00044) |
has_attachments | boolean | default false (added 00044) |
is_draft | boolean | default false (added 00044) |
subject | text | (added 00044) |
from_address | text | (added 00044) |
to_addresses | jsonb | default '[]' (added 00044) |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their messages" ON messages
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Indexes:
(conversation_id, timestamp DESC)(00001)(owner_id, timestamp DESC)(00001)idx_messages_email_threadon(email_thread_id, timestamp DESC)(00044)idx_messages_folderon(owner_id, folder_id, timestamp DESC)(00044)idx_messages_drafton(owner_id, is_draft)WHEREis_draft = true(00044)
Foreign Keys: conversation_id -> conversations(id), sender_person_id -> persons(id), email_thread_id -> email_threads(id), folder_id -> email_folders(id)
Services: DataService (CRUD), ETLService (sync), EmailService (draft CRUD, move, flag)
attachments
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
message_id | uuid | FK messages(id) |
storage_path | text | NOT NULL |
mime_type | text | NOT NULL |
filename | text | |
size_bytes | int | |
owner_id | uuid | NOT NULL, FK auth.users(id) (added 00039) |
created_at | timestamptz | default now() |
RLS: Enabled (added in 00039).
CREATE POLICY "users own their attachments" ON attachments
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Foreign Keys: message_id -> messages(id)
Services: DataService (CRUD)
events
Calendar events.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
title | text | NOT NULL |
description | text | |
start_time | timestamptz | NOT NULL |
end_time | timestamptz | |
location | text | |
location_geo | point | |
attendees | jsonb | default '[]' |
organizer_id | uuid | FK persons(id) |
all_day | boolean | default false |
recurrence | jsonb | |
sources | jsonb | default '[]' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their events" ON events
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Indexes: (owner_id, start_time) (00001)
Foreign Keys: organizer_id -> persons(id)
Services: DataService (CRUD), ETLService (sync from MS Graph), MeetingService (calendar_event_id link)
locations
Named places/geofences.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | |
address | text | |
coordinates | point | |
type | text | |
phone | text | |
radius_meters | int | default 100 |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their locations" ON locations
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Services: DataService (CRUD), InventoryService (location_id reference)
devices
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
name | text | NOT NULL |
platform | text | NOT NULL |
owner_id | uuid | FK auth.users(id) |
device_token | text | UNIQUE |
last_seen_at | timestamptz | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their devices" ON devices
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Services: DataService (CRUD), DeviceCommandService
location_history
Time-series device location data.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
device_id | uuid | FK devices(id) |
lat | float8 | NOT NULL |
lon | float8 | NOT NULL |
accuracy_m | float4 / real | |
altitude_m | float4 / real | |
speed_mps | float4 | |
wifi_ssid | text | |
ssid | text | (added 00002, separate column) |
owner_id | uuid | FK auth.users(id) (added 00002, hardened 00039) |
recorded_at | timestamptz | NOT NULL |
created_at | timestamptz | default now() |
RLS: Enabled (added in 00039).
CREATE POLICY "users own their location_history" ON location_history
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
(device_id, recorded_at DESC)(00001)location_history_owner_timeon(owner_id, recorded_at DESC)(00002)
Foreign Keys: device_id -> devices(id)
Services: DataService (write from Android app), RulesService (geofence evaluation)
tasks
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
title | text | NOT NULL |
description | text | |
due_date | timestamptz | |
status | text | default 'pending' |
priority | text | default 'medium' |
assignee_id | uuid | FK persons(id) |
related_event | uuid | FK events(id) |
sources | jsonb | default '[]' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their tasks" ON tasks
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Foreign Keys: assignee_id -> persons(id), related_event -> events(id)
Services: DataService (CRUD), ETLService (insert), AudioETLService (insert from extracted intelligence), RulesService (insert)
documents
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
title | text | NOT NULL |
content | text | |
storage_path | text | |
mime_type | text | |
created_by | uuid | FK persons(id) |
source | text | |
source_id | text | |
tags | jsonb | default '[]' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their documents" ON documents
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Foreign Keys: created_by -> persons(id)
Services: DataService (CRUD), ETLService (insert)
rules
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
enabled | boolean | default true |
trigger_event_types | text[] | NOT NULL |
condition_ast | jsonb | NOT NULL |
actions | jsonb[] | NOT NULL |
priority | int | default 100 |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their rules" ON rules
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Services: RulesService (evaluate), ToolRegistry (query for AI agent), DataService (CRUD)
job_records
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | FK auth.users(id) |
job_type | text | NOT NULL |
queue | text | NOT NULL |
payload | jsonb | NOT NULL |
status | text | default 'enqueued' |
attempts | int | default 0 |
last_error | text | |
triggered_by_event_id | text | |
correlation_id | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Not enabled (service-role only access).
Services: JobQueueService
audit_log
Append-only. No UPDATE or DELETE policies.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | FK auth.users(id) |
actor_type | text | NOT NULL |
actor_id | text | NOT NULL |
action | text | NOT NULL |
resource_type | text | NOT NULL |
resource_id | text | |
outcome | text | NOT NULL |
metadata | jsonb | default '{}' |
occurred_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users can read their audit log" ON audit_log
FOR SELECT USING (auth.uid() = owner_id);
INSERT allowed for service role only. No UPDATE or DELETE policies -- append-only by design.
Indexes:
(owner_id, occurred_at DESC)(00001)(actor_id, occurred_at DESC)(00001)
Services: PolicyService (insert), AuditService (read/query)
embeddings
pgvector embeddings for semantic search.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
entity_type | text | NOT NULL |
entity_id | uuid | NOT NULL |
model | text | NOT NULL |
embedding | vector(1536) | |
created_at | timestamptz | default now() |
Unique: (owner_id, entity_type, entity_id)
RLS: Enabled.
CREATE POLICY "users own their embeddings" ON embeddings
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
(WITH CHECK added in 00039)
Indexes: IVFFlat on (embedding vector_cosine_ops) with lists=100
Services: EmbeddingPipelineService, SearchService
Migration 00002 -- Intentions
intentions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
type | text | NOT NULL, CHECK IN ('reminder','task','goal','commitment') |
title | text | NOT NULL |
description | text | |
due_at | timestamptz | |
recurrence_rule | text | iCal RRULE |
status | text | NOT NULL default 'pending', CHECK IN ('pending','in_progress','completed','cancelled') |
entity_ref | jsonb | e.g. {"table":"events","id":"uuid"} |
boss_job_id | text | pg-boss job ID |
meta | jsonb | default '{}' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their intentions" ON intentions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: intentions_owner_due on (owner_id, due_at) WHERE status = 'pending'
Services: IntentionsService (CRUD, scheduling)
presence_snapshots
Durable snapshot of ephemeral presence state (primary in Redis).
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
dimension | text | NOT NULL ('location', 'activity', 'active_app', 'availability') |
state_json | jsonb | NOT NULL |
recorded_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their presence snapshots" ON presence_snapshots
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: presence_snapshots_owner_dim_time on (owner_id, dimension, recorded_at DESC)
Services: PresenceService
Migration 00003 -- Sovereign AI
agent_conversations
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
title | text | |
messages | jsonb | NOT NULL default '[]' |
context_json | jsonb | default '{}' |
model_used | text | |
token_count | integer | default 0 |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their agent conversations" ON agent_conversations
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: agent_conversations_owner_updated on (owner_id, updated_at DESC)
Services: AgentService (insert/update)
workflow_definitions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
definition | jsonb | NOT NULL |
enabled | boolean | default true |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their workflow definitions" ON workflow_definitions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Services: WorkflowService (CRUD)
workflow_runs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
workflow_id | uuid | NOT NULL, FK workflow_definitions(id) |
status | text | NOT NULL default 'running', CHECK IN ('running','paused','completed','failed','cancelled') |
trigger_context | jsonb | default '{}' |
step_context | jsonb | default '{}' |
current_step | text | |
error | text | |
started_at | timestamptz | default now() |
completed_at | timestamptz |
RLS: Enabled.
CREATE POLICY "users own their workflow runs" ON workflow_runs
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: workflow_runs_owner_status on (owner_id, status, started_at DESC)
Foreign Keys: workflow_id -> workflow_definitions(id)
Services: WorkflowService (insert/update)
llm_usage
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
provider | text | NOT NULL ('openrouter', 'ollama') |
model | text | NOT NULL |
prompt_tokens | integer | NOT NULL default 0 |
completion_tokens | integer | NOT NULL default 0 |
cost_usd | numeric(10,6) | default 0 |
routing_reason | text | |
conversation_id | uuid | nullable |
recorded_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their llm usage" ON llm_usage
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: llm_usage_owner_month on (owner_id, date_trunc('month', recorded_at AT TIME ZONE 'UTC'))
Services: LLMRoutingService (insert), AgentService
Migration 00004 -- Federation
dids
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
did | text | NOT NULL UNIQUE |
method | text | NOT NULL, CHECK IN ('key','web') |
document | jsonb | NOT NULL (W3C DID Document) |
public_key_b58 | text | NOT NULL |
private_key_enc | text | encrypted private key |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their dids" ON dids
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: dids_owner on (owner_id)
Services: DIDService (CRUD)
verifiable_credentials
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
vc_json | jsonb | NOT NULL (full W3C VC) |
vc_type | text | NOT NULL |
issuer_did | text | NOT NULL |
subject_did | text | NOT NULL |
issued_at | timestamptz | NOT NULL |
expires_at | timestamptz | |
revoked | boolean | default false |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their verifiable credentials" ON verifiable_credentials
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
vc_owner_typeon(owner_id, vc_type)vc_subject_didon(subject_did)
Services: VCService (issue, verify, insert)
federated_actors
Cached ActivityPub actor documents.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
actor_url | text | NOT NULL UNIQUE |
actor_json | jsonb | NOT NULL |
inbox_url | text | |
fetched_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Not enabled (public cache).
Indexes: federated_actors_url on (actor_url)
Services: ActivityPubService (insert/query)
follows
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
follower_actor_url | text | NOT NULL |
following_actor_url | text | NOT NULL |
status | text | NOT NULL default 'pending', CHECK IN ('pending','accepted','rejected','cancelled') |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
Unique: (follower_actor_url, following_actor_url)
RLS: Enabled.
CREATE POLICY "users own their follows" ON follows
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: follows_owner on (owner_id, status)
Services: ActivityPubService (insert/update)
activities
ActivityPub activity log.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
activity_id | text | NOT NULL UNIQUE |
activity_type | text | NOT NULL |
actor_url | text | NOT NULL |
object_json | jsonb | default '{}' |
direction | text | NOT NULL, CHECK IN ('inbound','outbound') |
processed | boolean | default false |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their activities" ON activities
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: activities_owner_dir on (owner_id, direction, created_at DESC)
Services: ActivityPubService (insert/update)
didcomm_messages
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
message_id | text | NOT NULL UNIQUE |
from_did | text | NOT NULL |
to_did | text | NOT NULL |
message_type | text | NOT NULL |
body_json | jsonb | NOT NULL |
direction | text | NOT NULL, CHECK IN ('inbound','outbound') |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their didcomm messages" ON didcomm_messages
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: didcomm_owner_dir on (owner_id, direction, created_at DESC)
Services: DIDCommService (insert)
Migration 00005 -- Marketplace
listings
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
listing_type | text | NOT NULL, CHECK IN ('data_product','service','physical','digital') |
title | text | NOT NULL |
description | text | |
price_amount | numeric(12,2) | |
price_currency | text | default 'USD' |
price_type | text | CHECK IN ('fixed','hourly','negotiable','free','time_credit') |
status | text | NOT NULL default 'draft', CHECK IN ('draft','active','paused','sold','expired') |
tags | text[] | default '{}' |
location_pref | text | |
visibility | text | NOT NULL default 'public', CHECK IN ('public','followers','private') |
data_product_id | uuid | FK to data_products (nullable) |
federated_ap_id | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "owners manage their listings" ON listings
USING (auth.uid() = owner_id OR visibility = 'public')
WITH CHECK (auth.uid() = owner_id);
Indexes:
listings_owneron(owner_id, status)listings_type_statuson(listing_type, status, created_at DESC)listings_tagsusing GIN on(tags)
Services: MarketplaceService (CRUD, status update)
data_products
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
query_def | jsonb | NOT NULL |
privacy_policy | jsonb | NOT NULL default '{}' |
output_format | text | NOT NULL default 'json', CHECK IN ('json','csv','parquet') |
sample_rows | integer | default 0 |
schema_json | jsonb | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "owners manage their data products" ON data_products
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Services: DataProductBuilder
marketplace_transactions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
listing_id | uuid | NOT NULL, FK listings(id) |
buyer_id | uuid | NOT NULL, FK auth.users(id) |
seller_id | uuid | NOT NULL, FK auth.users(id) |
amount | numeric(12,2) | |
currency | text | default 'USD' |
status | text | NOT NULL default 'created', CHECK IN ('created','funded','delivered','confirmed','disputed','refunded','completed') |
escrow_ref | text | |
dispute_reason | text | |
completed_at | timestamptz | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "participants see their transactions" ON marketplace_transactions
USING (auth.uid() = buyer_id OR auth.uid() = seller_id);
Indexes:
txn_buyeron(buyer_id, status)txn_selleron(seller_id, status)
Foreign Keys: listing_id -> listings(id)
Services: MarketplaceService
declarations
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
decl_type | text | NOT NULL, CHECK IN ('offer','need','willing_to_do') |
category | text | NOT NULL |
title | text | NOT NULL |
description | text | |
exchange_type | text | NOT NULL, CHECK IN ('reciprocal','gift','time_credit','monetary') |
location_pref | text | |
expires_at | timestamptz | |
status | text | NOT NULL default 'active', CHECK IN ('active','matched','expired','cancelled') |
federated_ap_id | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "owners manage their declarations" ON declarations
USING (auth.uid() = owner_id OR status = 'active')
WITH CHECK (auth.uid() = owner_id);
Indexes:
declarations_owneron(owner_id, status)declarations_categoryon(category, decl_type, status)
Services: ResourceCoordinationService (CRUD, cancel)
exchanges
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
offer_decl_id | uuid | FK declarations(id) |
need_decl_id | uuid | FK declarations(id) |
offer_user_id | uuid | NOT NULL, FK auth.users(id) |
need_user_id | uuid | NOT NULL, FK auth.users(id) |
status | text | NOT NULL default 'interest', CHECK IN ('interest','negotiating','agreed','exchanging','confirming','completed','cancelled') |
exchange_type | text | |
notes | text | |
completed_at | timestamptz | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "participants see their exchanges" ON exchanges
USING (auth.uid() = offer_user_id OR auth.uid() = need_user_id);
Indexes:
exchanges_offer_useron(offer_user_id, status)exchanges_need_useron(need_user_id, status)
Foreign Keys: offer_decl_id -> declarations(id), need_decl_id -> declarations(id)
Services: ResourceCoordinationService
trust_relationships
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
trusted_did | text | NOT NULL |
weight | numeric(3,2) | NOT NULL default 1.0, CHECK weight > 0 AND weight <= 1.0 |
context | text | |
created_at | timestamptz | default now() |
Unique: (owner_id, trusted_did)
RLS: Enabled.
CREATE POLICY "owners manage their trust" ON trust_relationships
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Services: ReputationService (CRUD, delete)
reputation_scores
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
domain | text | NOT NULL |
score | numeric(5,2) | NOT NULL default 0 |
vc_count | integer | default 0 |
last_computed | timestamptz | default now() |
Unique: (owner_id, domain)
RLS: Enabled.
CREATE POLICY "reputation scores are public" ON reputation_scores FOR SELECT USING (true);
CREATE POLICY "system can write reputation scores" ON reputation_scores FOR ALL USING (auth.uid() = owner_id);
Services: ReputationService
Migration 00006 -- Governance
daos
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
slug | text | NOT NULL UNIQUE |
dao_type | text | NOT NULL default 'community', CHECK IN ('community','cooperative','collective','trust') |
quorum_pct | numeric(5,2) | NOT NULL default 50.0 |
pass_threshold | numeric(5,2) | NOT NULL default 50.0 |
voting_period_h | integer | NOT NULL default 168 |
is_public | boolean | default true |
treasury_credits | numeric(12,2) | default 0 |
federated_ap_id | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "public daos are readable" ON daos FOR SELECT USING (is_public = true OR auth.uid() = owner_id);
CREATE POLICY "owners manage their daos" ON daos USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
daos_owneron(owner_id)daos_slugon(slug)
Services: DAOService
dao_members
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
dao_id | uuid | NOT NULL, FK daos(id) ON DELETE CASCADE |
user_id | uuid | NOT NULL, FK auth.users(id) |
role | text | NOT NULL default 'member', CHECK IN ('admin','member','observer') |
joined_at | timestamptz | default now() |
Unique: (dao_id, user_id)
RLS: Enabled.
CREATE POLICY "dao members can see membership" ON dao_members
FOR SELECT USING (auth.uid() = user_id OR EXISTS (SELECT 1 FROM daos WHERE id = dao_id AND (is_public = true OR owner_id = auth.uid())));
CREATE POLICY "admins manage membership" ON dao_members
USING (EXISTS (SELECT 1 FROM dao_members dm WHERE dm.dao_id = dao_id AND dm.user_id = auth.uid() AND dm.role = 'admin') OR auth.uid() = user_id)
WITH CHECK (EXISTS (SELECT 1 FROM dao_members dm WHERE dm.dao_id = dao_id AND dm.user_id = auth.uid() AND dm.role = 'admin'));
Indexes:
dao_members_daoon(dao_id, role)dao_members_useron(user_id)
Services: DAOService (CRUD, delete)
proposals
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
dao_id | uuid | NOT NULL, FK daos(id) ON DELETE CASCADE |
author_id | uuid | NOT NULL, FK auth.users(id) |
title | text | NOT NULL |
description | text | |
proposal_type | text | NOT NULL default 'general', CHECK IN ('general','treasury','membership','rule_change','dispute_resolution','resource_allocation') |
status | text | NOT NULL default 'draft', CHECK IN ('draft','active','passed','rejected','expired','executed') |
action_payload | jsonb | |
votes_yes | integer | NOT NULL default 0 |
votes_no | integer | NOT NULL default 0 |
votes_abstain | integer | NOT NULL default 0 |
quorum_reached | boolean | default false |
voting_opens_at | timestamptz | |
voting_closes_at | timestamptz | |
executed_at | timestamptz | |
federated_ap_id | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "dao members can see proposals" ON proposals FOR SELECT
USING (EXISTS (SELECT 1 FROM dao_members WHERE dao_id = proposals.dao_id AND user_id = auth.uid())
OR EXISTS (SELECT 1 FROM daos WHERE id = proposals.dao_id AND is_public = true));
CREATE POLICY "members create proposals" ON proposals FOR INSERT
WITH CHECK (EXISTS (SELECT 1 FROM dao_members WHERE dao_id = proposals.dao_id AND user_id = auth.uid() AND role IN ('admin','member')));
CREATE POLICY "authors update draft proposals" ON proposals FOR UPDATE
USING (auth.uid() = author_id AND status = 'draft');
Indexes:
proposals_daoon(dao_id, status)proposals_authoron(author_id)
Services: ProposalService, VotingService (vote count updates)
votes
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
proposal_id | uuid | NOT NULL, FK proposals(id) ON DELETE CASCADE |
voter_id | uuid | NOT NULL, FK auth.users(id) |
choice | text | NOT NULL, CHECK IN ('yes','no','abstain') |
weight | numeric(10,4) | NOT NULL default 1.0 |
voted_at | timestamptz | default now() |
Unique: (proposal_id, voter_id)
RLS: Enabled.
CREATE POLICY "voters own their votes" ON votes
USING (auth.uid() = voter_id) WITH CHECK (auth.uid() = voter_id);
CREATE POLICY "dao members can read votes" ON votes FOR SELECT
USING (EXISTS (SELECT 1 FROM proposals p JOIN dao_members dm ON dm.dao_id = p.dao_id WHERE p.id = votes.proposal_id AND dm.user_id = auth.uid()));
Indexes:
votes_proposalon(proposal_id, choice)votes_voteron(voter_id)
Services: VotingService
time_credits
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
balance | numeric(12,2) | NOT NULL default 0 |
lifetime_earned | numeric(12,2) | NOT NULL default 0 |
lifetime_spent | numeric(12,2) | NOT NULL default 0 |
updated_at | timestamptz | default now() |
Unique: (owner_id)
RLS: Enabled.
CREATE POLICY "users own their time credit balance" ON time_credits
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Services: TimeBankService (credit/debit)
time_credit_transactions
Append-only ledger.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
amount | numeric(12,2) | NOT NULL |
balance_after | numeric(12,2) | NOT NULL |
tx_type | text | NOT NULL, CHECK IN ('exchange_credit','exchange_debit','governance_reward','dao_treasury_deposit','dao_treasury_withdrawal','admin_adjustment') |
reference_id | text | |
note | text | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users see their own credit transactions" ON time_credit_transactions
FOR SELECT USING (auth.uid() = owner_id);
Indexes: tc_tx_owner on (owner_id, created_at DESC)
Services: TimeBankService
disputes
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) (claimant) |
respondent_id | uuid | NOT NULL, FK auth.users(id) |
subject_type | text | NOT NULL, CHECK IN ('exchange','listing','dao_action','other') |
subject_id | text | |
description | text | NOT NULL |
evidence_json | jsonb | default '[]' |
status | text | NOT NULL default 'open', CHECK IN ('open','under_review','resolved','dismissed','escalated') |
resolution | text | |
resolved_by | uuid | FK auth.users(id) |
moderator_id | uuid | FK auth.users(id) |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "parties see their disputes" ON disputes FOR SELECT
USING (auth.uid() = owner_id OR auth.uid() = respondent_id OR auth.uid() = moderator_id);
CREATE POLICY "claimants create disputes" ON disputes FOR INSERT WITH CHECK (auth.uid() = owner_id);
CREATE POLICY "moderators update disputes" ON disputes FOR UPDATE
USING (auth.uid() = moderator_id OR auth.uid() = owner_id);
Indexes:
disputes_owneron(owner_id, status)disputes_respondenton(respondent_id)disputes_moderatoron(moderator_id, status)
Services: DisputeService
moderation_actions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
moderator_id | uuid | NOT NULL, FK auth.users(id) |
target_type | text | NOT NULL |
target_id | text | NOT NULL |
action | text | NOT NULL, CHECK IN ('warn','hide','remove','ban','restore') |
reason | text | |
notes | text | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "moderators create and see actions" ON moderation_actions
FOR ALL USING (auth.uid() = moderator_id) WITH CHECK (auth.uid() = moderator_id);
Indexes:
mod_actions_targeton(target_type, target_id)mod_actions_moderatoron(moderator_id, created_at DESC)
Services: ModerationService
Migration 00007 -- Web3
wallet_connections
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
chain | text | NOT NULL, CHECK IN ('ethereum','solana','polygon') |
address | text | NOT NULL |
provider | text | NOT NULL, CHECK IN ('metamask','walletconnect','phantom','injected') |
is_verified | boolean | default false |
connected_at | timestamptz | default now() |
Unique: (owner_id, chain, address)
RLS: Enabled.
CREATE POLICY "users own their wallet connections" ON wallet_connections
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: wallet_connections_owner on (owner_id)
Services: WalletService (CRUD, delete)
time_credit_bridge_requests
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
direction | text | NOT NULL, CHECK IN ('mint','burn') |
amount | numeric(12,2) | NOT NULL |
chain | text | NOT NULL |
wallet_address | text | NOT NULL |
tx_hash | text | |
status | text | NOT NULL default 'pending', CHECK IN ('pending','confirmed','failed') |
created_at | timestamptz | default now() |
confirmed_at | timestamptz |
RLS: Enabled.
CREATE POLICY "users own their bridge requests" ON time_credit_bridge_requests
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: bridge_requests_owner on (owner_id, status)
Services: WalletService
Migration 00008 -- Federated Marketplace
federated_listing_cache
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
source_hub_url | text | NOT NULL |
remote_listing_id | text | NOT NULL |
title | text | NOT NULL |
description | text | |
listing_type | text | NOT NULL default 'service' |
credits_per_hour | numeric(10,2) | |
tags | text[] | default '{}' |
actor_url | text | |
raw_ap_object | jsonb | |
cached_at | timestamptz | default now() |
expires_at | timestamptz | default now() + interval '24 hours' |
Unique: (owner_id, source_hub_url, remote_listing_id)
RLS: Enabled.
CREATE POLICY "users manage their federation cache" ON federated_listing_cache
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
fed_listing_hubon(owner_id, source_hub_url)fed_listing_expireson(expires_at)
Services: FederatedMarketplaceService (insert)
hub_subscriptions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
hub_url | text | NOT NULL |
hub_name | text | |
actor_url | text | |
is_active | boolean | default true |
last_sync | timestamptz | |
created_at | timestamptz | default now() |
Unique: (owner_id, hub_url)
RLS: Enabled.
CREATE POLICY "users manage their hub subscriptions" ON hub_subscriptions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: hub_subs_owner on (owner_id, is_active)
Services: FederatedMarketplaceService (CRUD, delete, update)
Migration 00009 -- Calling
call_sessions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
call_sid | text | |
from_number | text | NOT NULL |
to_number | text | NOT NULL |
direction | text | NOT NULL, CHECK IN ('inbound','outbound') |
status | text | NOT NULL default 'initiated', CHECK IN ('initiated','ringing','in-progress','completed','failed','busy','no-answer') |
started_at | timestamptz | default now() |
ended_at | timestamptz | |
duration_seconds | integer | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their call sessions" ON call_sessions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
call_sessions_owneron(owner_id, started_at DESC)call_sessions_sidon(call_sid)
Services: TwilioCallingService (insert/update), ToolRegistry (query call_analyses by call_session_id)
Migration 00010 -- Agent Memory
agent_memory
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | text | NOT NULL |
memory_type | text | NOT NULL default 'working', CHECK IN ('working','episodic','semantic') |
key | text | NOT NULL |
value | jsonb | NOT NULL |
expires_at | timestamptz | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
Unique: (owner_id, session_id, key)
RLS: Enabled.
CREATE POLICY "users own their agent memory" ON agent_memory
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: agent_memory_session on (owner_id, session_id)
Services: AgentMemoryService (CRUD, delete)
agent_tool_calls
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | text | NOT NULL |
tool_name | text | NOT NULL |
input | jsonb | NOT NULL default '{}' |
output | jsonb | |
error | text | |
duration_ms | integer | |
called_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users see their tool calls" ON agent_tool_calls
FOR SELECT USING (auth.uid() = owner_id);
Indexes: agent_tool_calls_session on (owner_id, session_id, called_at DESC)
Services: AgentMemoryService (insert)
Migration 00011 -- Privacy
retention_policies
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
target_table | text | NOT NULL |
retention_days | integer | NOT NULL default 90 |
is_active | boolean | default true |
last_run_at | timestamptz | |
next_run_at | timestamptz | default now() + interval '1 day' |
rows_deleted | integer | default 0 |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users manage their retention policies" ON retention_policies
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
retention_policies_owneron(owner_id, is_active)retention_policies_next_runon(next_run_at)WHEREis_active = true
Services: AuditService (query), PrivacyService
consent_records
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
purpose | text | NOT NULL |
granted | boolean | NOT NULL default false |
granted_at | timestamptz | |
revoked_at | timestamptz | |
expires_at | timestamptz | |
metadata | jsonb | default '{}' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
Unique: (owner_id, purpose)
RLS: Enabled.
CREATE POLICY "users manage their consent records" ON consent_records
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: consent_records_owner on (owner_id, purpose)
Services: AuditService (query), PrivacyService
pii_scan_log
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
entity_type | text | NOT NULL |
entity_id | text | NOT NULL |
pii_types_found | text[] | default '{}' |
was_redacted | boolean | default false |
scanned_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users see their pii scan log" ON pii_scan_log
FOR SELECT USING (auth.uid() = owner_id);
Indexes: pii_scan_log_owner on (owner_id, scanned_at DESC)
Services: PrivacyService
Migration 00012 -- Notifications
notification_subscriptions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
subscription_type | text | NOT NULL, CHECK IN ('web_push','fcm','apns') |
endpoint | text | NOT NULL |
auth_key | text | |
p256dh_key | text | |
device_name | text | |
is_active | boolean | default true |
last_used_at | timestamptz | |
created_at | timestamptz | default now() |
Unique: (owner_id, endpoint)
RLS: Enabled.
CREATE POLICY "users manage their notification subscriptions" ON notification_subscriptions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: notif_subs_owner on (owner_id, is_active)
Services: NotificationService (CRUD, delete)
outbound_webhooks
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
url | text | NOT NULL |
secret | text | |
event_types | text[] | NOT NULL default '{}' |
is_active | boolean | default true |
failure_count | integer | default 0 |
last_triggered | timestamptz | |
last_success | timestamptz | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users manage their webhooks" ON outbound_webhooks
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: outbound_webhooks_owner on (owner_id, is_active)
Services: OutboundWebhookService (CRUD, delete)
webhook_delivery_log
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
webhook_id | uuid | NOT NULL, FK outbound_webhooks(id) ON DELETE CASCADE |
event_type | text | NOT NULL |
payload | jsonb | NOT NULL |
response_status | integer | |
response_body | text | |
duration_ms | integer | |
success | boolean | default false |
error | text | |
delivered_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users see their webhook logs" ON webhook_delivery_log
FOR SELECT USING (EXISTS (SELECT 1 FROM outbound_webhooks WHERE id = webhook_id AND owner_id = auth.uid()));
Indexes: webhook_log_webhook on (webhook_id, delivered_at DESC)
Foreign Keys: webhook_id -> outbound_webhooks(id) ON DELETE CASCADE
Services: OutboundWebhookService
Migration 00013 -- Presence
user_presence
| Column | Type | Constraints |
|---|---|---|
owner_id | uuid | PK, FK auth.users(id) |
status | text | NOT NULL default 'offline', CHECK IN ('online','away','busy','offline') |
activity | text | |
last_seen_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users manage their own presence" ON user_presence
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
CREATE POLICY "anyone can read presence" ON user_presence FOR SELECT USING (true);
Services: PresenceService, ScheduledJobService (stale presence cleanup)
collaboration_sessions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_type | text | NOT NULL default 'document', CHECK IN ('document','rule_edit','dao_vote','marketplace_review') |
entity_id | text | |
title | text | NOT NULL |
participants | uuid[] | default '{}' |
is_active | boolean | default true |
started_at | timestamptz | default now() |
ended_at | timestamptz | |
metadata | jsonb | default '{}' |
RLS: Enabled.
CREATE POLICY "participants can see sessions" ON collaboration_sessions
FOR SELECT USING (auth.uid() = owner_id OR auth.uid() = ANY(participants));
CREATE POLICY "owners manage sessions" ON collaboration_sessions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
collab_sessions_owneron(owner_id, is_active)collab_sessions_entityon(entity_id, session_type)
Services: CollaborationService
collaboration_cursors
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
session_id | uuid | NOT NULL, FK collaboration_sessions(id) ON DELETE CASCADE |
user_id | uuid | NOT NULL, FK auth.users(id) |
position | jsonb | NOT NULL default '{}' |
selection | jsonb | |
color | text | |
label | text | |
updated_at | timestamptz | default now() |
Unique: (session_id, user_id)
RLS: Enabled.
CREATE POLICY "participants see cursors" ON collaboration_cursors FOR SELECT
USING (EXISTS (SELECT 1 FROM collaboration_sessions s WHERE s.id = session_id AND (s.owner_id = auth.uid() OR auth.uid() = ANY(s.participants))));
CREATE POLICY "users own their cursor" ON collaboration_cursors
USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
Indexes: collab_cursors_session on (session_id, updated_at DESC)
Foreign Keys: session_id -> collaboration_sessions(id) ON DELETE CASCADE
Services: CollaborationService
Migration 00014 -- Audit
compliance_reports
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
report_type | text | NOT NULL, CHECK IN ('gdpr_access','gdpr_erasure','data_export','access_summary','consent_history','retention_summary') |
status | text | NOT NULL default 'pending', CHECK IN ('pending','generating','completed','failed') |
parameters | jsonb | default '{}' |
result_url | text | |
result_size_kb | integer | |
error | text | |
generated_at | timestamptz | |
expires_at | timestamptz | default now() + interval '7 days' |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their compliance reports" ON compliance_reports
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: compliance_reports_owner on (owner_id, created_at DESC)
Services: AuditService
audit_alert_rules
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
description | text | |
event_type | text | |
threshold | integer | default 10 |
window_minutes | integer | default 60 |
is_active | boolean | default true |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users manage their alert rules" ON audit_alert_rules
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Services: AuditService (CRUD, delete)
Migration 00015 -- Plugins
plugin_registry
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
plugin_id | text | NOT NULL UNIQUE |
name | text | NOT NULL |
description | text | |
version | text | NOT NULL default '1.0.0' |
plugin_type | text | NOT NULL, CHECK IN ('connector','channel','rule_operator','ai_tool','data_processor') |
author | text | |
icon_url | text | |
permissions | jsonb | default '[]' |
required_credentials | text[] | default '{}' |
optional_credentials | text[] | default '{}' |
capabilities | text[] | default '{}' |
is_builtin | boolean | default false |
is_active | boolean | default true |
install_count | integer | default 0 |
rating_avg | numeric(3,2) | default 0 |
rating_count | integer | default 0 |
manifest | jsonb | default '{}' |
owner_id | uuid | FK auth.users(id) (nullable) |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "anyone can read active plugins" ON plugin_registry
FOR SELECT USING (is_active = true);
Indexes: plugin_registry_type on (plugin_type, is_active)
Services: PluginRegistryService, PluginManager
user_plugins
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
plugin_id | text | NOT NULL, FK plugin_registry(plugin_id) |
is_enabled | boolean | default true |
config | jsonb | default '{}' |
installed_at | timestamptz | default now() |
last_used_at | timestamptz |
Unique: (owner_id, plugin_id)
RLS: Enabled.
CREATE POLICY "users manage their plugins" ON user_plugins
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: user_plugins_owner on (owner_id, is_enabled)
Foreign Keys: plugin_id -> plugin_registry(plugin_id)
Services: PluginRegistryService (install/uninstall/delete)
plugin_ratings
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
plugin_id | text | NOT NULL, FK plugin_registry(plugin_id) |
rating | integer | NOT NULL, CHECK BETWEEN 1 AND 5 |
review | text | |
created_at | timestamptz | default now() |
Unique: (owner_id, plugin_id)
RLS: Enabled.
CREATE POLICY "users manage their ratings" ON plugin_ratings
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
CREATE POLICY "anyone can read ratings" ON plugin_ratings FOR SELECT USING (true);
Foreign Keys: plugin_id -> plugin_registry(plugin_id)
Services: PluginRegistryService
Migration 00016 -- Documents
document_jobs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
document_id | text | NOT NULL |
job_type | text | NOT NULL, CHECK IN ('extract','summarize','classify','extract_entities','chunk','embed') |
status | text | NOT NULL default 'pending', CHECK IN ('pending','processing','completed','failed') |
result | jsonb | |
error | text | |
started_at | timestamptz | |
completed_at | timestamptz | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their document jobs" ON document_jobs
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
doc_jobs_owneron(owner_id, status, created_at DESC)doc_jobs_documenton(document_id, job_type)
Services: DocumentIntelligenceService
document_chunks
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
document_id | text | NOT NULL |
chunk_index | integer | NOT NULL |
content | text | NOT NULL |
token_count | integer | |
metadata | jsonb | default '{}' |
created_at | timestamptz | default now() |
Unique: (owner_id, document_id, chunk_index)
RLS: Enabled.
CREATE POLICY "users own their document chunks" ON document_chunks
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: doc_chunks_document on (owner_id, document_id, chunk_index)
Services: DocumentIntelligenceService, RAGService
document_entities
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
document_id | text | NOT NULL |
entity_type | text | NOT NULL |
entity_value | text | NOT NULL |
confidence | numeric(4,3) | default 1.0 |
context | text | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their entities" ON document_entities
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
doc_entities_documenton(owner_id, document_id)doc_entities_typeon(owner_id, entity_type)
Services: DocumentIntelligenceService
Migration 00017 -- Rules
rule_templates
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
name | text | NOT NULL |
description | text | |
category | text | NOT NULL default 'general', CHECK IN ('communication','schedule','location','automation','governance','privacy') |
condition_ast | jsonb | NOT NULL |
actions | jsonb | NOT NULL default '[]' |
tags | text[] | default '{}' |
use_count | integer | default 0 |
is_featured | boolean | default false |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "anyone can read templates" ON rule_templates FOR SELECT USING (true);
Indexes: rule_templates_category on (category, is_featured)
Services: RulesService (template queries)
rule_execution_log
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
rule_id | text | NOT NULL |
triggered_by | text | NOT NULL |
matched | boolean | NOT NULL |
actions_fired | integer | default 0 |
execution_ms | integer | |
error | text | |
context_snapshot | jsonb | default '{}' |
fired_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their rule executions" ON rule_execution_log
FOR SELECT USING (auth.uid() = owner_id);
Indexes:
rule_exec_owneron(owner_id, fired_at DESC)rule_exec_ruleon(rule_id, fired_at DESC)
Services: RulesService (insert after evaluation)
Migration 00018 -- Scheduled Jobs
No tables created. Enables pg_cron extension and schedules five recurring jobs. See Scheduled Jobs above.
Migration 00019 -- Rate Limits
rate_limit_events
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | |
policy | text | NOT NULL |
key | text | NOT NULL |
allowed | boolean | NOT NULL |
remaining | integer | NOT NULL |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(owner_id, created_at DESC)(policy, created_at DESC)
Services: RateLimiterService
circuit_breaker_snapshots
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
circuit_name | text | NOT NULL |
state | text | NOT NULL, CHECK IN ('CLOSED', 'OPEN', 'HALF_OPEN') |
failures | integer | NOT NULL default 0 |
recorded_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (circuit_name, recorded_at DESC)
Services: CircuitBreakerService
Migration 00020 -- Event Store
event_store
Append-only event sourcing store.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
stream_id | text | NOT NULL |
event_type | text | NOT NULL |
payload | jsonb | NOT NULL default '{}' |
version | integer | NOT NULL |
correlation_id | uuid | |
causation_id | uuid | |
metadata | jsonb | default '{}' |
occurred_at | timestamptz | NOT NULL default now() |
Unique: (stream_id, version)
RLS: Not enabled.
Indexes:
event_store_stream_version_idxon(stream_id, version)event_store_event_type_idxon(event_type, occurred_at DESC)
Services: EventStoreService
event_snapshots
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
stream_id | text | NOT NULL UNIQUE |
state | jsonb | NOT NULL |
version | integer | NOT NULL |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: event_snapshots_stream_id_idx on (stream_id)
Services: EventStoreService
Migration 00021 -- Streaming
activity_feed
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
type | text | NOT NULL |
title | text | NOT NULL |
description | text | NOT NULL |
entity_type | text | |
entity_id | uuid | |
metadata | jsonb | default '{}' |
is_read | boolean | NOT NULL default false |
occurred_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "activity_feed_owner_policy" ON activity_feed FOR ALL USING (owner_id = auth.uid());
Indexes:
activity_feed_owner_timeon(owner_id, occurred_at DESC)activity_feed_owner_unread_timeon(owner_id, is_read, occurred_at DESC)
Services: ActivityFeedService (CRUD, mark read)
Migration 00022 -- Orgs
Note: The organizations table was created in 00001 and extended here with slug, avatar_url, billing_plan, billing_status columns. See organizations above for the merged schema.
org_memberships
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) ON DELETE CASCADE |
user_id | uuid | NOT NULL, FK auth.users(id) |
role | text | NOT NULL default 'member', CHECK IN ('owner','admin','member','viewer') |
invited_by | uuid | FK auth.users(id) |
joined_at | timestamptz | NOT NULL default now() |
Unique: (org_id, user_id)
RLS: Not enabled (service-role access pattern).
Indexes:
(org_id)(user_id)
Foreign Keys: org_id -> organizations(id) ON DELETE CASCADE
Services: OrgService
org_invites
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) ON DELETE CASCADE |
email | text | NOT NULL |
role | text | NOT NULL default 'member' |
token | text | NOT NULL UNIQUE, default encode(gen_random_bytes(32), 'hex') |
expires_at | timestamptz | NOT NULL default now() + interval '7 days' |
created_by | uuid | NOT NULL, FK auth.users(id) |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(org_id)(token)
Foreign Keys: org_id -> organizations(id) ON DELETE CASCADE
Services: OrgService
usage_records
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) |
metric | text | NOT NULL |
value | numeric | NOT NULL default 0 |
period_start | timestamptz | NOT NULL |
period_end | timestamptz | NOT NULL |
recorded_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (org_id, metric, period_start)
Foreign Keys: org_id -> organizations(id)
Services: BillingService, UsageTrackingService
billing_events
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) |
type | text | NOT NULL |
metadata | jsonb | NOT NULL default '{}' |
occurred_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (org_id, occurred_at DESC)
Foreign Keys: org_id -> organizations(id)
Services: BillingService
Migration 00023 -- Developer
oauth_apps
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
name | text | NOT NULL |
description | text | |
client_id | text | NOT NULL UNIQUE, default encode(gen_random_bytes(16), 'hex') |
client_secret_hash | text | NOT NULL |
redirect_uris | text[] | NOT NULL default '{}' |
scopes | text[] | NOT NULL default '{}' |
logo_url | text | |
website_url | text | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(owner_id)(client_id)
Services: OAuthService
oauth_auth_codes
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
app_id | uuid | NOT NULL, FK oauth_apps(id) ON DELETE CASCADE |
user_id | uuid | NOT NULL |
code | text | NOT NULL UNIQUE, default encode(gen_random_bytes(32), 'hex') |
scopes | text[] | NOT NULL default '{}' |
redirect_uri | text | NOT NULL |
expires_at | timestamptz | NOT NULL default now() + interval '10 minutes' |
used_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (code)
Foreign Keys: app_id -> oauth_apps(id) ON DELETE CASCADE
Services: OAuthService
oauth_tokens
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
app_id | uuid | NOT NULL, FK oauth_apps(id) ON DELETE CASCADE |
user_id | uuid | NOT NULL |
access_token | text | NOT NULL UNIQUE, default encode(gen_random_bytes(32), 'hex') |
refresh_token | text | UNIQUE, default encode(gen_random_bytes(32), 'hex') |
scopes | text[] | NOT NULL default '{}' |
expires_at | timestamptz | NOT NULL default now() + interval '1 hour' |
revoked_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(access_token)(refresh_token)(user_id, app_id)
Foreign Keys: app_id -> oauth_apps(id) ON DELETE CASCADE
Services: OAuthService
api_keys
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
name | text | NOT NULL |
key_prefix | text | NOT NULL |
key_hash | text | NOT NULL UNIQUE |
scopes | text[] | NOT NULL default '{}' |
status | text | NOT NULL default 'active', CHECK IN ('active','revoked','expired') |
last_used_at | timestamptz | |
expires_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(owner_id)(key_hash)
Services: APIKeyService
Migration 00024 -- Search
saved_searches
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
name | text | NOT NULL |
query | jsonb | NOT NULL default '{}' |
alert_enabled | boolean | NOT NULL default false |
last_alert_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: saved_searches_owner_id_idx on (owner_id)
Services: SavedSearchService (CRUD, delete, update)
recommendations
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
type | text | NOT NULL, CHECK IN ('contact','rule_template','capability','content') |
entity_id | text | NOT NULL |
entity_type | text | NOT NULL |
reason | text | NOT NULL |
score | numeric | NOT NULL default 0 |
metadata | jsonb | default '{}' |
generated_at | timestamptz | NOT NULL default now() |
expires_at | timestamptz | NOT NULL default now() + interval '24 hours' |
dismissed | boolean | NOT NULL default false |
RLS: Not enabled.
Indexes:
recommendations_owner_dismissed_expires_idxon(owner_id, dismissed, expires_at)recommendations_owner_type_idxon(owner_id, type)
Services: RecommendationEngine (CRUD, delete), ScheduledJobService (cleanup expired)
Migration 00025 -- Data Portability
export_jobs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
format | text | NOT NULL, CHECK IN ('json','csv','vcard','ical','mbox','zip') |
entity_types | text[] | NOT NULL default '{}' |
filters | jsonb | default '{}' |
status | text | NOT NULL default 'pending', CHECK IN ('pending','processing','ready','failed','expired') |
download_url | text | |
size_bytes | bigint | |
record_count | integer | |
error | text | |
created_at | timestamptz | NOT NULL default now() |
completed_at | timestamptz | |
expires_at | timestamptz |
RLS: Not enabled.
Indexes:
(owner_id, created_at DESC)(status, created_at)
Services: DataPortabilityService
import_jobs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL |
format | text | NOT NULL, CHECK IN ('json','csv','vcard','ical') |
file_name | text | NOT NULL |
status | text | NOT NULL default 'pending', CHECK IN ('pending','processing','completed','failed') |
total_records | integer | |
imported_records | integer | NOT NULL default 0 |
failed_records | integer | NOT NULL default 0 |
errors | jsonb | NOT NULL default '[]' |
created_at | timestamptz | NOT NULL default now() |
completed_at | timestamptz |
RLS: Not enabled.
Indexes: (owner_id, created_at DESC)
Services: DataPortabilityService
Migration 00026 -- Preferences
user_preferences
| Column | Type | Constraints |
|---|---|---|
user_id | uuid | PK, NOT NULL |
color_scheme | text | NOT NULL default 'system', CHECK IN ('light','dark','system') |
locale | text | NOT NULL default 'en', CHECK IN ('en','es','fr','de','ja','zh') |
text_size | text | NOT NULL default 'md', CHECK IN ('sm','md','lg','xl') |
contrast_mode | text | NOT NULL default 'normal', CHECK IN ('normal','high') |
reduced_motion | boolean | NOT NULL default false |
timezone | text | NOT NULL default 'UTC' |
date_format | text | NOT NULL default 'MM/DD/YYYY' |
time_format | text | NOT NULL default '12h', CHECK IN ('12h','24h') |
currency | text | NOT NULL default 'USD' |
notification_email | boolean | NOT NULL default true |
notification_push | boolean | NOT NULL default true |
notification_in_app | boolean | NOT NULL default true |
notification_digest | text | NOT NULL default 'none', CHECK IN ('none','daily','weekly') |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "user_preferences_select_own" ON user_preferences FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "user_preferences_insert_own" ON user_preferences FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "user_preferences_update_own" ON user_preferences FOR UPDATE USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
Triggers: user_preferences_updated_at BEFORE UPDATE -> update_user_preferences_updated_at()
Services: PreferencesService
Migration 00027 -- Monitoring
tracked_errors
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
fingerprint | text | NOT NULL |
type | text | NOT NULL |
message | text | NOT NULL |
stack | text | |
context | jsonb | NOT NULL default '{}' |
severity | text | NOT NULL default 'medium', CHECK IN ('low','medium','high','critical') |
count | integer | NOT NULL default 1 |
first_seen_at | timestamptz | NOT NULL default now() |
last_seen_at | timestamptz | NOT NULL default now() |
resolved | boolean | NOT NULL default false |
RLS: Not enabled.
Indexes:
tracked_errors_fingerprint_idxon(fingerprint)tracked_errors_severity_resolved_idxon(severity, resolved, last_seen_at DESC)tracked_errors_resolved_idxon(resolved, last_seen_at DESC)
Services: ErrorTrackingService
email_queue
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
to_address | text | NOT NULL |
from_address | text | NOT NULL default 'noreply@made-open.app' |
subject | text | NOT NULL |
html_body | text | NOT NULL |
text_body | text | |
template_id | text | |
template_vars | jsonb | default '{}' |
status | text | NOT NULL default 'pending', CHECK IN ('pending','sent','failed','bounced') |
attempts | integer | NOT NULL default 0 |
last_error | text | |
scheduled_at | timestamptz | NOT NULL default now() |
sent_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
email_queue_status_scheduled_idxon(status, scheduled_at)email_queue_to_address_created_idxon(to_address, created_at DESC)
Services: EmailQueueService
Migration 00028 -- Billing
stripe_customers
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) ON DELETE CASCADE, UNIQUE |
stripe_customer_id | text | NOT NULL UNIQUE |
stripe_subscription_id | text | UNIQUE |
stripe_price_id | text | |
subscription_status | text | CHECK IN ('active','trialing','past_due','canceled','unpaid') |
current_period_start | timestamptz | |
current_period_end | timestamptz | |
cancel_at_period_end | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
(stripe_customer_id)(org_id)
Foreign Keys: org_id -> organizations(id) ON DELETE CASCADE
Services: BillingService
checkout_sessions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
org_id | uuid | NOT NULL, FK organizations(id) |
price_id | text | NOT NULL |
success_url | text | NOT NULL |
cancel_url | text | NOT NULL |
session_id | text | NOT NULL UNIQUE |
url | text | NOT NULL |
expires_at | timestamptz | NOT NULL |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (session_id)
Foreign Keys: org_id -> organizations(id)
Services: BillingService
feature_flags
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
name | text | NOT NULL UNIQUE |
description | text | NOT NULL default '' |
enabled | boolean | NOT NULL default false |
rollout_percentage | integer | NOT NULL default 0, CHECK BETWEEN 0 AND 100 |
enabled_for_orgs | text[] | NOT NULL default '{}' |
enabled_for_plans | text[] | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: (name)
Services: FeatureFlagService
Migration 00029 -- Security
user_sessions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
user_id | uuid | NOT NULL |
user_agent | text | |
ip_address | text | |
last_active_at | timestamptz | NOT NULL default now() |
expires_at | timestamptz | NOT NULL default now() + interval '30 days' |
revoked_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes: user_sessions_user_revoked_expires_idx on (user_id, revoked_at, expires_at)
Services: SessionService
analytics_events
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | |
event_type | text | NOT NULL |
properties | jsonb | NOT NULL default '{}' |
session_id | uuid | |
occurred_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Indexes:
analytics_events_owner_type_time_idxon(owner_id, event_type, occurred_at DESC)analytics_events_type_time_idxon(event_type, occurred_at DESC)
Services: AnalyticsService
Migration 00030 -- Lineage
entity_lineage
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
entity_type | text | NOT NULL |
entity_id | uuid | NOT NULL |
owner_id | uuid | NOT NULL |
fields | jsonb | NOT NULL default '[]' |
merged_from_ids | uuid[] | NOT NULL default '{}' |
primary_source | text | NOT NULL default 'manual' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
Unique: (entity_type, entity_id)
RLS: Not enabled.
Indexes:
(owner_id, entity_type)(entity_id)
Services: EntityMergeService, LineageService
merge_candidates
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
entity_type | text | NOT NULL |
entity_a_id | uuid | NOT NULL |
entity_b_id | uuid | NOT NULL |
confidence | numeric | NOT NULL default 0 |
match_reasons | text[] | NOT NULL default '{}' |
status | text | NOT NULL default 'pending', CHECK IN ('pending','merged','rejected') |
created_at | timestamptz | NOT NULL default now() |
resolved_at | timestamptz |
Unique: (entity_type, entity_a_id, entity_b_id)
RLS: Not enabled.
Indexes:
(status, confidence DESC)(entity_a_id)(entity_b_id)
Services: EntityMergeService
conflict_resolution_rules
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
field | text | NOT NULL UNIQUE |
strategy | text | NOT NULL default 'newest', CHECK IN ('newest','oldest','highest_confidence','source_priority','manual') |
source_priority | text[] | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
RLS: Not enabled.
Services: EntityMergeService
Migration 00031 -- Credential Wallet
user_credentials
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
credential_type | text | NOT NULL |
display_info | text | |
is_active | boolean | default true |
vault_keys | text[] | NOT NULL default '{}' |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
Unique: (owner_id, credential_type)
RLS: Enabled.
CREATE POLICY "users own their credentials" ON user_credentials
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: (owner_id)
Services: CredentialWalletService, CapabilityRegistry, PluginManager
Migration 00032 -- Tools
tool_jobs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
operation | text | NOT NULL |
category | text | NOT NULL, CHECK IN ('pdf','image','audio','video','document','font','archive','data','qrcode','crypto','text','color','svg','code','math','regex','datetime','markdown','validate','jwt','html','generate','cron','geo','network','diff','template','ai') |
status | text | NOT NULL default 'pending', CHECK IN ('pending','processing','completed','failed','cancelled') |
priority | text | NOT NULL default 'interactive', CHECK IN ('realtime','interactive','background') |
input_paths | jsonb | NOT NULL default '[]' |
output_paths | jsonb | NOT NULL default '[]' |
params | jsonb | NOT NULL default '{}' |
result | jsonb | |
error | text | |
progress | integer | default 0, CHECK >= 0 AND <= 100 |
callback_url | text | |
started_at | timestamptz | |
completed_at | timestamptz | |
created_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their tool jobs" ON tool_jobs
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
tool_jobs_owner_statuson(owner_id, status, created_at DESC)tool_jobs_categoryon(category, status)tool_jobs_pendingon(status, priority, created_at)WHEREstatus = 'pending'
Services: ToolsService
fonts
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
family | text | NOT NULL |
style | text | NOT NULL default 'normal', CHECK IN ('normal','italic','oblique') |
weight | integer | NOT NULL default 400 |
storage_path | text | NOT NULL |
format | text | NOT NULL, CHECK IN ('ttf','otf','woff','woff2') |
metadata | jsonb | default '{}' |
preview_url | text | |
created_at | timestamptz | default now() |
Unique: (owner_id, family, style, weight)
RLS: Enabled.
CREATE POLICY "users own their fonts" ON fonts
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: fonts_owner on (owner_id, family)
Services: ToolsService (CRUD, delete)
Migration 00033 -- Audio Intelligence
audio_sessions
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
source | text | NOT NULL, CHECK IN ('microphone','system','both') |
status | text | NOT NULL default 'recording', CHECK IN ('recording','paused','completed','processing') |
device_id | text | |
audio_storage_path | text | |
duration_seconds | numeric(10,2) | |
session_type | text | CHECK IN ('manual','continuous','meeting') (added 00034) |
ended_reason | text | CHECK IN ('user_stop','rotation','silence_gap','crash_recovery','app_exit') (added 00034) |
started_at | timestamptz | NOT NULL default now() |
ended_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their audio sessions" ON audio_sessions
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
audio_sessions_owner_statuson(owner_id, status, started_at DESC)audio_sessions_deviceon(owner_id, device_id, started_at DESC)
Triggers: audio_sessions_updated_at BEFORE UPDATE -> set_updated_at()
Services: AudioETLService, AlwaysOnAudioService
transcripts
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | uuid | NOT NULL, FK audio_sessions(id) ON DELETE CASCADE |
segments | jsonb | NOT NULL default '[]' |
full_text | text | NOT NULL default '' |
model | text | NOT NULL |
pass | smallint | NOT NULL, CHECK IN (1,2,3) |
avg_confidence | numeric(4,3) | |
context | jsonb | (added 00034) |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their transcripts" ON transcripts
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
transcripts_sessionon(session_id, pass)transcripts_owner_createdon(owner_id, created_at DESC)transcripts_fulltextusing GIN onto_tsvector('english', full_text)
Foreign Keys: session_id -> audio_sessions(id) ON DELETE CASCADE
Services: AudioETLService, TranscriptionService
voice_commands
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | uuid | NOT NULL, FK audio_sessions(id) ON DELETE CASCADE |
raw_transcript | text | NOT NULL |
command_text | text | NOT NULL |
intent | text | NOT NULL |
confidence | numeric(4,3) | |
resolved_contact | jsonb | |
params | jsonb | NOT NULL default '{}' |
job_id | text | |
status | text | NOT NULL default 'queued', CHECK IN ('queued','processing','completed','failed','disambiguation-needed') |
error | text | |
disambiguation_sent | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their voice commands" ON voice_commands
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
voice_commands_owner_statuson(owner_id, status, created_at DESC)voice_commands_sessionon(session_id)voice_commands_intenton(owner_id, intent, created_at DESC)
Triggers: voice_commands_updated_at BEFORE UPDATE -> set_updated_at()
Foreign Keys: session_id -> audio_sessions(id) ON DELETE CASCADE
Services: VoiceCommandService, AudioETLService
extracted_intelligence
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | uuid | NOT NULL, FK audio_sessions(id) ON DELETE CASCADE |
transcript_id | uuid | NOT NULL, FK transcripts(id) ON DELETE CASCADE |
type | text | NOT NULL, CHECK IN ('action-item','decision','commitment','question','deadline','idea','problem','follow-up','entity-mention','topic') |
content | text | NOT NULL |
source_text | text | |
offset_ms | integer | |
mentioned_person_ids | jsonb | NOT NULL default '[]' |
task_id | uuid | |
event_id | uuid | |
confidence | numeric(4,3) | |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their extracted intelligence" ON extracted_intelligence
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
extracted_intelligence_sessionon(session_id, type)extracted_intelligence_owner_typeon(owner_id, type, created_at DESC)
Foreign Keys: session_id -> audio_sessions(id), transcript_id -> transcripts(id) ON DELETE CASCADE
Services: AudioETLService
daily_briefs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
date | date | NOT NULL |
session_count | integer | NOT NULL default 0 |
total_audio_seconds | numeric(12,2) | NOT NULL default 0 |
summary | text | NOT NULL default '' |
stats | jsonb | NOT NULL default '{}' |
recurring_topics | jsonb | NOT NULL default '[]' |
unresolved_questions | jsonb | NOT NULL default '[]' |
created_at | timestamptz | NOT NULL default now() |
Unique: (owner_id, date)
RLS: Enabled.
CREATE POLICY "users own their daily briefs" ON daily_briefs
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: daily_briefs_owner_date on (owner_id, date DESC)
Services: AudioETLService, DailyBriefService
Migration 00034 -- Always-On Audio
context_snapshots
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
hash | text | NOT NULL |
context | jsonb | NOT NULL |
created_at | timestamptz | NOT NULL default now() |
Unique: (owner_id, hash)
RLS: Enabled.
CREATE POLICY "users own their context snapshots" ON context_snapshots
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: context_snapshots_owner_hash on (owner_id, hash)
Services: AlwaysOnAudioService
transcript_chunks
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | uuid | NOT NULL, FK audio_sessions(id) ON DELETE CASCADE |
full_text | text | NOT NULL default '' |
offset_ms | integer | NOT NULL default 0 |
duration_ms | integer | NOT NULL default 0 |
context_hash | text | |
model | text | |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their transcript chunks" ON transcript_chunks
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
transcript_chunks_fulltextusing GIN onto_tsvector('english', full_text)transcript_chunks_sessionon(session_id, created_at)transcript_chunks_owner_createdon(owner_id, created_at DESC)
Foreign Keys: session_id -> audio_sessions(id) ON DELETE CASCADE
Services: AlwaysOnAudioService
passive_intents
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
session_id | uuid | NOT NULL, FK audio_sessions(id) ON DELETE CASCADE |
text | text | NOT NULL |
intent_type | text | NOT NULL, CHECK IN ('reminder','follow-up','delegation','save-context','bookmark','question') |
confidence | numeric(4,3) | NOT NULL |
context | jsonb | |
confirmed | boolean | NOT NULL default false |
acted_on | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their passive intents" ON passive_intents
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
passive_intents_owneron(owner_id, confirmed, created_at DESC)passive_intents_sessionon(session_id)
Foreign Keys: session_id -> audio_sessions(id) ON DELETE CASCADE
Services: AlwaysOnAudioService
Migration 00035 -- Device Commands
device_commands
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
device_id | text | NOT NULL |
owner_id | uuid | NOT NULL, FK auth.users(id) |
module | text | NOT NULL, CHECK IN ('filesystem','process','clipboard','display','power','network','registry','notifications','input','shell','agent') (expanded in 00036) |
action | text | NOT NULL |
params | jsonb | NOT NULL default '{}' |
status | text | NOT NULL default 'pending', CHECK IN ('pending','sent','received','executing','completed','failed','rejected','expired') |
priority | text | NOT NULL default 'interactive', CHECK IN ('realtime','interactive','background') |
source | text | NOT NULL default 'api', CHECK IN ('voice-command','web-ui','rules-engine','api','agent-worker') (expanded in 00036) |
source_command_id | text | |
result | jsonb | |
error | text | |
progress | jsonb | NOT NULL default '[]' (added 00036) |
created_at | timestamptz | NOT NULL default now() |
sent_at | timestamptz | |
received_at | timestamptz | |
completed_at | timestamptz | |
expires_at | timestamptz |
Constraint: valid_module_action -- validates module+action combinations (see migration 00035/00036 for full matrix).
RLS: Enabled.
CREATE POLICY "users own their device commands" ON device_commands
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
device_commands_pendingon(device_id, status, created_at)WHEREstatus = 'pending'device_commands_owneron(owner_id, created_at DESC)device_commands_expireson(expires_at)WHEREstatus IN ('pending', 'sent') AND expires_at IS NOT NULLdevice_commands_agent_pendingon(device_id, status, created_at)WHEREmodule = 'agent' AND status = 'pending'(00036)
Supabase Realtime: Table is added to supabase_realtime publication.
Services: DeviceCommandService, AgentWorkerService
Migration 00036 -- Agent Worker
No new tables. Extends device_commands with:
agentmodule andagent-workersource (constraint updates)progressJSONB columnappend_command_progress()RPC function- Agent-specific pending index
Migration 00037 -- LLM Routing Rules
llm_routing_rules
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
name | text | NOT NULL |
priority | integer | NOT NULL default 100 |
enabled | boolean | NOT NULL default true |
data_domains | text[] | default '{}' |
query_types | text[] | default '{}' |
provider | text | NOT NULL, CHECK IN ('openrouter', 'ollama') |
model | text | |
reason | text | |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
RLS: Enabled.
CREATE POLICY "users own their routing rules" ON llm_routing_rules
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: llm_routing_rules_owner on (owner_id, priority)
Services: LLMRoutingService
Migration 00038 -- Unified Scheduler
schedules
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | FK auth.users(id) ON DELETE CASCADE (nullable for system schedules) |
name | text | NOT NULL |
description | text | |
schedule_type | text | NOT NULL, CHECK IN ('one_shot', 'recurring') |
cron_expression | text | |
rrule | text | |
trigger_at | timestamptz | |
delay_ms | bigint | |
payload | jsonb | NOT NULL default '{}' |
status | text | NOT NULL default 'active', CHECK IN ('active', 'paused', 'completed', 'failed', 'cancelled') |
source_type | text | NOT NULL default 'custom', CHECK IN ('system', 'rule', 'workflow', 'intention', 'connector', 'custom') |
source_id | text | |
boss_job_id | text | |
boss_schedule_name | text | |
last_run_at | timestamptz | |
next_run_at | timestamptz | |
run_count | integer | NOT NULL default 0 |
error_count | integer | NOT NULL default 0 |
last_error | text | |
timezone | text | NOT NULL default 'UTC' |
idempotency_key | text | UNIQUE |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users_own_schedules" ON schedules
USING (owner_id IS NULL OR auth.uid() = owner_id)
WITH CHECK (owner_id IS NULL OR auth.uid() = owner_id);
Indexes:
idx_schedules_owner_statuson(owner_id, status)idx_schedules_sourceon(source_type, source_id)idx_schedules_next_runon(next_run_at)WHEREstatus = 'active'idx_schedules_boss_scheduleon(boss_schedule_name)WHEREboss_schedule_name IS NOT NULL
Triggers: trg_schedules_updated_at BEFORE UPDATE -> update_schedules_updated_at()
Services: SchedulerService (full CRUD, cancel, pause, resume, run tracking)
schedule_runs
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
schedule_id | uuid | NOT NULL, FK schedules(id) ON DELETE CASCADE |
owner_id | uuid | FK auth.users(id) ON DELETE SET NULL |
status | text | NOT NULL, CHECK IN ('started', 'completed', 'failed') |
started_at | timestamptz | NOT NULL default now() |
completed_at | timestamptz | |
duration_ms | integer | |
error | text | |
result | jsonb | |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users_own_schedule_runs" ON schedule_runs
USING (owner_id IS NULL OR auth.uid() = owner_id)
WITH CHECK (owner_id IS NULL OR auth.uid() = owner_id);
Indexes:
idx_schedule_runs_scheduleon(schedule_id, started_at DESC)idx_schedule_runs_owneron(owner_id, started_at DESC)
Foreign Keys: schedule_id -> schedules(id) ON DELETE CASCADE
Services: SchedulerService (insert/update)
Migration 00039 -- RLS Hardening
No new tables. Adds owner_id and RLS to attachments and location_history, and adds WITH CHECK to 11 tables that previously only had USING:
organizations,channels,conversations,messages,events,locations,devices,tasks,documents,rules,embeddings
Migration 00040 -- Wiki
wiki_pages
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) |
slug | text | NOT NULL |
title | text | NOT NULL |
page_type | text | NOT NULL, CHECK IN ('entity', 'concept', 'summary', 'comparison', 'source', 'index', 'log') |
content | text | NOT NULL default '' |
frontmatter | jsonb | NOT NULL default '{}' |
source_ids | uuid[] | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
Unique: (owner_id, slug)
RLS: Enabled.
CREATE POLICY "users own their wiki pages" ON wiki_pages
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_wiki_pages_owneron(owner_id)idx_wiki_pages_typeon(owner_id, page_type)idx_wiki_pages_frontmatterusing GIN on(frontmatter)
Services: WikiService (CRUD, log page updates)
wiki_links
| Column | Type | Constraints |
|---|---|---|
from_page_id | uuid | NOT NULL, FK wiki_pages(id) ON DELETE CASCADE |
to_page_id | uuid | NOT NULL, FK wiki_pages(id) ON DELETE CASCADE |
link_type | text | NOT NULL, CHECK IN ('reference', 'related', 'contradicts', 'supersedes') |
created_at | timestamptz | NOT NULL default now() |
Primary Key: (from_page_id, to_page_id, link_type)
RLS: Enabled.
CREATE POLICY "users see links from their pages" ON wiki_links
USING (EXISTS (SELECT 1 FROM wiki_pages WHERE wiki_pages.id = wiki_links.from_page_id AND wiki_pages.owner_id = auth.uid()))
WITH CHECK (EXISTS (SELECT 1 FROM wiki_pages WHERE wiki_pages.id = wiki_links.from_page_id AND wiki_pages.owner_id = auth.uid()));
Indexes:
idx_wiki_links_fromon(from_page_id)idx_wiki_links_toon(to_page_id)
Foreign Keys: from_page_id -> wiki_pages(id) ON DELETE CASCADE, to_page_id -> wiki_pages(id) ON DELETE CASCADE
Services: WikiService
Migration 00041 -- Inventory
inventory_items
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
parent_item_id | uuid | FK inventory_items(id) ON DELETE SET NULL |
item_type | text | NOT NULL, CHECK IN ('property','vehicle','appliance','electronics','furniture','tool','clothing','collectible','other') |
name | text | NOT NULL |
description | text | |
brand | text | |
model | text | |
serial_number | text | |
status | text | NOT NULL default 'active', CHECK IN ('wishlist','purchased','active','in_repair','in_warranty','disposing','gone') |
purchase_date | date | |
purchase_price | numeric(12,2) | |
purchase_location | text | |
purchase_url | text | |
warranty_expiry | date | |
expected_lifespan_months | integer | |
disposition_type | text | CHECK IN ('sell','give_away','trash','recycle','donate') |
disposition_date | timestamptz | |
location_id | uuid | FK locations(id) ON DELETE SET NULL |
space_id | uuid | FK inventory_spaces(id) ON DELETE SET NULL |
categories | text[] | NOT NULL default '{}' |
attributes | jsonb | NOT NULL default '{}' |
media | jsonb | NOT NULL default '[]' |
metadata | jsonb | NOT NULL default '{}' |
tags | text[] | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their inventory items" ON inventory_items
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_inventory_items_owner_statuson(owner_id, status)idx_inventory_items_owner_typeon(owner_id, item_type)idx_inventory_items_parenton(parent_item_id)idx_inventory_items_owner_createdon(owner_id, created_at DESC)idx_inventory_items_locationon(location_id)idx_inventory_items_categoriesusing GIN on(categories)idx_inventory_items_tagsusing GIN on(tags)
Foreign Keys: parent_item_id -> inventory_items(id), location_id -> locations(id), space_id -> inventory_spaces(id)
Triggers: set_inventory_items_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: InventoryService (CRUD, status update, event logging)
inventory_spaces
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
property_item_id | uuid | NOT NULL, FK inventory_items(id) ON DELETE CASCADE |
name | text | NOT NULL |
parent_space_id | uuid | FK inventory_spaces(id) ON DELETE SET NULL |
metadata | jsonb | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their inventory spaces" ON inventory_spaces
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_inventory_spaces_owner_propertyon(owner_id, property_item_id)idx_inventory_spaces_parenton(parent_space_id)
Foreign Keys: property_item_id -> inventory_items(id) ON DELETE CASCADE, parent_space_id -> inventory_spaces(id) ON DELETE SET NULL
Triggers: set_inventory_spaces_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: InventoryService
inventory_maintenance
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
item_id | uuid | NOT NULL, FK inventory_items(id) ON DELETE CASCADE |
title | text | NOT NULL |
description | text | |
status | text | NOT NULL default 'scheduled', CHECK IN ('scheduled','overdue','in_progress','completed','skipped') |
schedule_type | text | NOT NULL default 'one_time', CHECK IN ('one_time','recurring') |
recurrence_rule | text | |
next_due_date | date | |
last_completed_date | date | |
cost | numeric(12,2) | |
provider | text | |
notes | text | |
metadata | jsonb | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their inventory maintenance" ON inventory_maintenance
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_inventory_maintenance_owner_itemon(owner_id, item_id)idx_inventory_maintenance_owner_status_dueon(owner_id, status, next_due_date)
Foreign Keys: item_id -> inventory_items(id) ON DELETE CASCADE
Triggers: set_inventory_maintenance_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: InventoryService (update)
inventory_events
Append-only ledger. UPDATE and DELETE are blocked by trigger.
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
item_id | uuid | NOT NULL, FK inventory_items(id) ON DELETE CASCADE |
event_type | text | NOT NULL, CHECK IN ('purchased','moved','repaired','warranty_claimed','status_changed','value_updated','photo_added','document_attached','disposed') |
data | jsonb | NOT NULL default '{}' |
occurred_at | timestamptz | NOT NULL default now() |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their inventory events" ON inventory_events
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: idx_inventory_events_owner_item_occurred on (owner_id, item_id, occurred_at DESC)
Triggers:
inventory_events_no_updateBEFORE UPDATE ->prevent_inventory_event_mutation()(raises exception)inventory_events_no_deleteBEFORE DELETE ->prevent_inventory_event_mutation()(raises exception)
Foreign Keys: item_id -> inventory_items(id) ON DELETE CASCADE
Services: InventoryService (insert)
Migration 00042 -- Deep Comms
inbox_items
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
type | text | NOT NULL, CHECK IN ('call','sms','email','video','calendar_event','voicemail') |
conversation_id | uuid | FK conversations(id) ON DELETE SET NULL |
contact_id | uuid | FK persons(id) ON DELETE SET NULL |
channel_type | text | NOT NULL, CHECK IN ('twilio_voice','twilio_sms','ms_graph_email','twilio_video') |
direction | text | NOT NULL, CHECK IN ('inbound','outbound') |
subject | text | |
preview | text | |
timestamp | timestamptz | NOT NULL default now() |
read | boolean | NOT NULL default false |
starred | boolean | NOT NULL default false |
archived | boolean | NOT NULL default false |
source_table | text | |
source_id | uuid | |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their inbox items" ON inbox_items
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_inbox_items_owner_timestampon(owner_id, timestamp DESC)idx_inbox_items_owner_read_timestampon(owner_id, read, timestamp DESC)idx_inbox_items_owner_contact_timestampon(owner_id, contact_id, timestamp DESC)
Foreign Keys: conversation_id -> conversations(id), contact_id -> persons(id)
Triggers: set_inbox_items_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: InboxService (CRUD, mark read, star, archive), ContactTimelineService (update contact_id on merge)
Migration 00043 -- Deep Voice
phone_lines
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
phone_number | text | NOT NULL |
twilio_sid | text | |
label | text | NOT NULL default 'Main' |
settings | jsonb | NOT NULL default '{}' |
is_default | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their phone lines" ON phone_lines
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_phone_lines_owneron(owner_id)idx_phone_lines_owner_numberUNIQUE on(owner_id, phone_number)
Triggers: set_phone_lines_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: PhoneLineService
voicemails
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
call_session_id | uuid | |
phone_line_id | uuid | FK phone_lines(id) ON DELETE SET NULL |
from_number | text | NOT NULL |
contact_id | uuid | |
recording_url | text | NOT NULL |
recording_sid | text | |
transcription | text | |
duration_seconds | integer | |
listened | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their voicemails" ON voicemails
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_voicemails_owner_createdon(owner_id, created_at DESC)idx_voicemails_owner_listenedon(owner_id, listened, created_at DESC)
Foreign Keys: phone_line_id -> phone_lines(id) ON DELETE SET NULL
Services: VoicemailService
call_recordings
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
call_session_id | uuid | NOT NULL |
recording_sid | text | NOT NULL |
url | text | NOT NULL |
duration_seconds | integer | |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their call recordings" ON call_recordings
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_call_recordings_owneron(owner_id)idx_call_recordings_sessionon(call_session_id)
Services: PhoneLineService, TranscriptionService
call_transcripts
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
call_session_id | uuid | NOT NULL |
segments | jsonb | NOT NULL default '[]' |
full_text | text | NOT NULL default '' |
provider | text | NOT NULL default 'whisper' |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their call transcripts" ON call_transcripts
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_call_transcripts_sessionon(call_session_id)idx_call_transcripts_owneron(owner_id)
Services: TranscriptionService
call_analyses
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
call_session_id | uuid | NOT NULL |
transcript_id | uuid | FK call_transcripts(id) ON DELETE SET NULL |
summary | text | |
action_items | jsonb | NOT NULL default '[]' |
sentiment | text | CHECK IN ('positive','neutral','negative') |
key_topics | text[] | NOT NULL default '{}' |
entities | jsonb | NOT NULL default '[]' |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their call analyses" ON call_analyses
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_call_analyses_sessionon(call_session_id)idx_call_analyses_owneron(owner_id, created_at DESC)
Foreign Keys: transcript_id -> call_transcripts(id) ON DELETE SET NULL
Services: TranscriptionService, ToolRegistry (query by call_session_id)
ivr_flows
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
phone_line_id | uuid | FK phone_lines(id) ON DELETE SET NULL |
name | text | NOT NULL |
flow_definition | jsonb | NOT NULL default '{}' |
is_active | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their ivr flows" ON ivr_flows
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_ivr_flows_owneron(owner_id)idx_ivr_flows_lineon(phone_line_id, is_active)
Foreign Keys: phone_line_id -> phone_lines(id) ON DELETE SET NULL
Triggers: set_ivr_flows_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: PhoneLineService
Migration 00044 -- Email Client
email_folders
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
name | text | NOT NULL |
ms_graph_id | text | |
parent_folder_id | uuid | FK email_folders(id) ON DELETE SET NULL |
unread_count | integer | NOT NULL default 0 |
total_count | integer | NOT NULL default 0 |
folder_type | text | NOT NULL default 'custom', CHECK IN ('inbox','sent','drafts','trash','archive','junk','custom') |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their email folders" ON email_folders
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_email_folders_owneron(owner_id)idx_email_folders_owner_typeon(owner_id, folder_type)idx_email_folders_ms_graph_idon(owner_id, ms_graph_id)idx_email_folders_parenton(parent_folder_id)
Foreign Keys: parent_folder_id -> email_folders(id) ON DELETE SET NULL
Triggers: set_email_folders_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: EmailService
email_threads
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
ms_graph_conversation_id | text | |
subject | text | NOT NULL default '(No subject)' |
last_message_at | timestamptz | NOT NULL default now() |
folder_id | uuid | FK email_folders(id) ON DELETE SET NULL |
participants | jsonb | NOT NULL default '[]' |
snippet | text | |
unread | boolean | NOT NULL default true |
starred | boolean | NOT NULL default false |
message_count | integer | NOT NULL default 0 |
has_attachments | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their email threads" ON email_threads
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_email_threads_owner_folder_laston(owner_id, folder_id, last_message_at DESC)idx_email_threads_owner_unreadon(owner_id, unread, last_message_at DESC)idx_email_threads_owner_starredon(owner_id, starred, last_message_at DESC)idx_email_threads_ms_graph_convon(owner_id, ms_graph_conversation_id)
Foreign Keys: folder_id -> email_folders(id) ON DELETE SET NULL
Triggers: set_email_threads_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: EmailService (CRUD, mark read, star)
email_signatures
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
name | text | NOT NULL |
body_html | text | NOT NULL default '' |
is_default | boolean | NOT NULL default false |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their email signatures" ON email_signatures
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: idx_email_signatures_owner on (owner_id)
Triggers: set_email_signatures_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: EmailService (CRUD, delete, default toggle)
Migration 00045 -- Meetings
meetings
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
title | text | NOT NULL |
room_name | text | NOT NULL UNIQUE |
scheduled_start | timestamptz | |
scheduled_end | timestamptz | |
status | text | NOT NULL default 'scheduled', CHECK IN ('scheduled','active','ended') |
settings | jsonb | NOT NULL default '{}' |
calendar_event_id | uuid | FK events(id) ON DELETE SET NULL |
invite_link | text | |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their meetings" ON meetings
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_meetings_owner_statuson(owner_id, status)idx_meetings_owner_scheduledon(owner_id, scheduled_start DESC)idx_meetings_room_nameon(room_name)
Foreign Keys: calendar_event_id -> events(id) ON DELETE SET NULL
Triggers: set_meetings_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: MeetingService (full lifecycle -- create, start, join, end, update)
meeting_participants
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
meeting_id | uuid | NOT NULL, FK meetings(id) ON DELETE CASCADE |
contact_id | uuid | FK persons(id) ON DELETE SET NULL |
email | text | |
role | text | NOT NULL default 'participant', CHECK IN ('host','participant') |
status | text | NOT NULL default 'invited', CHECK IN ('invited','joined','left') |
joined_at | timestamptz | |
left_at | timestamptz | |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "meeting participants visible to meeting owner" ON meeting_participants
USING (EXISTS (SELECT 1 FROM meetings WHERE meetings.id = meeting_participants.meeting_id AND meetings.owner_id = auth.uid()));
Indexes:
idx_meeting_participants_meetingon(meeting_id)idx_meeting_participants_contacton(contact_id)
Foreign Keys: meeting_id -> meetings(id) ON DELETE CASCADE, contact_id -> persons(id) ON DELETE SET NULL
Triggers: set_meeting_participants_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: MeetingService (insert/update)
meeting_recordings
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
meeting_id | uuid | NOT NULL, FK meetings(id) ON DELETE CASCADE |
recording_sid | text | |
url | text | |
duration_seconds | integer | |
composition_status | text | NOT NULL default 'enqueued', CHECK IN ('enqueued','processing','completed','failed') |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "meeting recordings visible to meeting owner" ON meeting_recordings
USING (EXISTS (SELECT 1 FROM meetings WHERE meetings.id = meeting_recordings.meeting_id AND meetings.owner_id = auth.uid()));
Indexes: idx_meeting_recordings_meeting on (meeting_id)
Foreign Keys: meeting_id -> meetings(id) ON DELETE CASCADE
Triggers: set_meeting_recordings_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: MeetingService (update composition status)
meeting_analyses
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
meeting_id | uuid | NOT NULL, FK meetings(id) ON DELETE CASCADE |
transcript_id | uuid | |
summary | text | |
action_items | jsonb | NOT NULL default '[]' |
key_decisions | jsonb | NOT NULL default '[]' |
sentiment | text | CHECK IN ('positive','neutral','negative') |
key_topics | text[] | NOT NULL default '{}' |
entities | jsonb | NOT NULL default '{}' |
created_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "meeting analyses visible to meeting owner" ON meeting_analyses
USING (EXISTS (SELECT 1 FROM meetings WHERE meetings.id = meeting_analyses.meeting_id AND meetings.owner_id = auth.uid()));
Indexes: idx_meeting_analyses_meeting on (meeting_id)
Foreign Keys: meeting_id -> meetings(id) ON DELETE CASCADE
Services: MeetingService
Migration 00046 -- Contact Timeline
contact_notes
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
contact_id | uuid | NOT NULL, FK persons(id) ON DELETE CASCADE |
body | text | NOT NULL |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their contact notes" ON contact_notes
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes: idx_contact_notes_owner_contact on (owner_id, contact_id, created_at DESC)
Foreign Keys: contact_id -> persons(id) ON DELETE CASCADE
Triggers: set_contact_notes_updated_at BEFORE UPDATE -> trigger_set_updated_at()
Services: ContactTimelineService (CRUD, delete)
contact_merges
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
primary_id | uuid | NOT NULL, FK persons(id) ON DELETE CASCADE |
merged_id | uuid | NOT NULL, FK persons(id) ON DELETE CASCADE |
merged_at | timestamptz | NOT NULL default now() |
undone_at | timestamptz |
Unique: (primary_id, merged_id) (named unique_merge)
RLS: Enabled.
CREATE POLICY "users own their contact merges" ON contact_merges
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_contact_merges_owneron(owner_id)idx_contact_merges_primaryon(primary_id)idx_contact_merges_mergedon(merged_id)
Foreign Keys: primary_id -> persons(id) ON DELETE CASCADE, merged_id -> persons(id) ON DELETE CASCADE
Services: ContactTimelineService (merge/undo merge)
Migration 00047 -- Device Push Tokens
device_push_tokens
| Column | Type | Constraints |
|---|---|---|
id | uuid | PK, default gen_random_uuid() |
owner_id | uuid | NOT NULL, FK auth.users(id) ON DELETE CASCADE |
device_id | text | NOT NULL |
fcm_token | text | NOT NULL |
platform | text | NOT NULL default 'android', CHECK IN ('android','ios','web') |
device_name | text | |
is_active | boolean | NOT NULL default true |
created_at | timestamptz | NOT NULL default now() |
updated_at | timestamptz | NOT NULL default now() |
RLS: Enabled.
CREATE POLICY "users own their push tokens" ON device_push_tokens
USING (auth.uid() = owner_id) WITH CHECK (auth.uid() = owner_id);
Indexes:
idx_push_tokens_owner_deviceUNIQUE on(owner_id, device_id)idx_push_tokens_owner_activeon(owner_id, is_active)idx_push_tokens_fcmon(fcm_token)
Services: PushNotificationService (register/update)
Entity Relationship Map
auth.users (Supabase Auth)
|
+-- persons --------+-- messages (sender_person_id)
| +-- events (organizer_id)
| +-- tasks (assignee_id)
| +-- documents (created_by)
| +-- contact_notes (contact_id)
| +-- contact_merges (primary_id, merged_id)
| +-- inbox_items (contact_id)
| +-- meeting_participants (contact_id)
|
+-- organizations ---+-- org_memberships (org_id)
| +-- org_invites (org_id)
| +-- usage_records (org_id)
| +-- billing_events (org_id)
| +-- stripe_customers (org_id)
| +-- checkout_sessions (org_id)
|
+-- channels --------+-- conversations (channel_id)
|
+-- conversations ---+-- messages (conversation_id)
| +-- inbox_items (conversation_id)
|
+-- messages --------+-- attachments (message_id)
|
+-- email_folders ---+-- email_threads (folder_id)
| (self-ref) +-- messages (folder_id)
|
+-- email_threads ---+-- messages (email_thread_id)
|
+-- devices ---------+-- location_history (device_id)
|
+-- locations -------+-- inventory_items (location_id)
|
+-- events ----------+-- tasks (related_event)
| +-- meetings (calendar_event_id)
|
+-- workflow_definitions -- workflow_runs (workflow_id)
|
+-- daos ------------+-- dao_members (dao_id)
| +-- proposals (dao_id)
|
+-- proposals -------+-- votes (proposal_id)
|
+-- declarations ----+-- exchanges (offer_decl_id, need_decl_id)
|
+-- listings --------+-- marketplace_transactions (listing_id)
|
+-- outbound_webhooks -- webhook_delivery_log (webhook_id)
|
+-- collaboration_sessions -- collaboration_cursors (session_id)
|
+-- audio_sessions --+-- transcripts (session_id)
| +-- voice_commands (session_id)
| +-- extracted_intelligence (session_id)
| +-- transcript_chunks (session_id)
| +-- passive_intents (session_id)
|
+-- transcripts -----+-- extracted_intelligence (transcript_id)
|
+-- phone_lines -----+-- voicemails (phone_line_id)
| +-- ivr_flows (phone_line_id)
|
+-- call_transcripts +-- call_analyses (transcript_id)
|
+-- meetings --------+-- meeting_participants (meeting_id)
| +-- meeting_recordings (meeting_id)
| +-- meeting_analyses (meeting_id)
|
+-- wiki_pages ------+-- wiki_links (from_page_id, to_page_id)
|
+-- inventory_items -+-- inventory_spaces (property_item_id)
| (self-ref) +-- inventory_maintenance (item_id)
| +-- inventory_events (item_id)
|
+-- inventory_spaces (self-ref: parent_space_id)
|
+-- schedules -------+-- schedule_runs (schedule_id)
|
+-- plugin_registry -+-- user_plugins (plugin_id)
| +-- plugin_ratings (plugin_id)
|
+-- oauth_apps ------+-- oauth_auth_codes (app_id)
+-- oauth_tokens (app_id)
Service-to-Table Map
| Service | Tables Read | Tables Written |
|---|---|---|
| DataService | All tables (generic CRUD) | All tables (generic CRUD) |
| PolicyService | audit_log | audit_log |
| AuditService | audit_log, consent_records, retention_policies, compliance_reports, audit_alert_rules | compliance_reports, audit_alert_rules (delete) |
| RulesService | rules, rule_templates, persons, location_history | rule_execution_log, tasks, persons (tag updates) |
| ETLService | -- | persons, documents, tasks, events, messages |
| AgentService | agent_conversations | agent_conversations |
| AgentMemoryService | agent_memory, agent_tool_calls | agent_memory (upsert/delete), agent_tool_calls |
| WorkflowService | workflow_definitions, workflow_runs | workflow_runs |
| IntentionsService | intentions | intentions |
| SchedulerService | schedules, schedule_runs | schedules, schedule_runs |
| ScheduledJobService | user_presence, recommendations | user_presence, recommendations (delete) |
| DIDService | dids | dids |
| VCService | verifiable_credentials | verifiable_credentials |
| DIDCommService | didcomm_messages | didcomm_messages |
| ActivityPubService | federated_actors, follows, activities | federated_actors, follows, activities |
| MarketplaceService | listings | listings |
| FederatedMarketplaceService | hub_subscriptions, federated_listing_cache | hub_subscriptions, federated_listing_cache |
| ResourceCoordinationService | declarations | declarations |
| DAOService | daos, dao_members | daos, dao_members (delete) |
| VotingService | votes, proposals | votes, proposals (count updates) |
| TimeBankService | time_credits, time_credit_transactions | time_credits, time_credit_transactions |
| ReputationService | reputation_scores, trust_relationships | reputation_scores, trust_relationships (delete) |
| WalletService | wallet_connections | wallet_connections (delete) |
| TwilioCallingService | call_sessions | call_sessions |
| InboxService | inbox_items | inbox_items |
| ContactTimelineService | contact_notes, contact_merges, persons, inbox_items | contact_notes (delete), contact_merges, persons, inbox_items |
| EmailService | email_threads, email_folders, email_signatures, messages | email_threads, messages, email_signatures (delete) |
| MeetingService | meetings, meeting_participants, meeting_recordings | meetings, meeting_participants, meeting_recordings |
| PhoneLineService | phone_lines, voicemails, ivr_flows | phone_lines, voicemails, ivr_flows |
| AudioETLService | audio_sessions, transcripts | tasks, extracted_intelligence |
| WikiService | wiki_pages, wiki_links | wiki_pages |
| InventoryService | inventory_items, inventory_spaces, inventory_maintenance, inventory_events | inventory_items, inventory_events, inventory_maintenance |
| ToolsService | tool_jobs, fonts | tool_jobs, fonts (delete) |
| PushNotificationService | device_push_tokens | device_push_tokens |
| PresenceService | user_presence, presence_snapshots | user_presence, presence_snapshots |
| ActivityFeedService | activity_feed | activity_feed |
| EmbeddingPipelineService | embeddings | embeddings |
| SearchService | embeddings | -- |
| SavedSearchService | saved_searches | saved_searches (delete/update) |
| RecommendationEngine | recommendations | recommendations (delete) |
| NotificationService | notification_subscriptions | notification_subscriptions (delete) |
| OutboundWebhookService | outbound_webhooks, webhook_delivery_log | outbound_webhooks (delete), webhook_delivery_log |
| EntityMergeService | persons, merge_candidates, entity_lineage, conflict_resolution_rules | persons, merge_candidates |
| PluginRegistryService | plugin_registry, user_plugins, plugin_ratings | plugin_registry, user_plugins (delete) |
| CredentialWalletService | user_credentials | user_credentials |
| DeviceCommandService | device_commands | device_commands |
| LLMRoutingService | llm_routing_rules, llm_usage | llm_usage |
| BillingService | stripe_customers, checkout_sessions, billing_events, usage_records | All billing tables |
| OAuthService | oauth_apps, oauth_auth_codes, oauth_tokens | All OAuth tables |
| ErrorTrackingService | tracked_errors | tracked_errors |
| ToolRegistry (AI) | rules, call_analyses | -- |