Relational data model¶
Static SQLAlchemy table and column catalog. Runtime SQLite inspection remains authoritative for an installed instance, especially after lightweight migrations.
Regenerate with python pipeline/skills/technical_documentation/scripts/generate.py.
Discovered 19 mapped tables and 160 mapped columns.
Table summary¶
api_tokens — ApiToken¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:103 |
user_id |
String |
— | no | — | yes | users.id |
— | backend/models/management.py:104 |
workspace_id |
String |
— | yes | — | — | — | — | backend/models/management.py:105 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:106 |
token_hash |
String |
— | no | yes | yes | — | redacted | backend/models/management.py:107 |
token_prefix |
String |
— | no | — | — | — | redacted | backend/models/management.py:108 |
scopes |
String |
— | — | — | — | — | 'read,write' | backend/models/management.py:109 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:110 |
last_used_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/management.py:111 |
revoked |
Integer |
— | — | — | — | — | 0 | backend/models/management.py:112 |
articles — Article¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/reader.py:26 |
source_id |
Integer |
— | — | — | — | feed_sources.id |
— | backend/models/reader.py:27 |
title |
String |
— | — | — | — | — | — | backend/models/reader.py:28 |
url |
String |
— | — | yes | — | — | — | backend/models/reader.py:29 |
content |
Text |
— | — | — | — | — | — | backend/models/reader.py:34 |
full_content |
Text |
— | yes | — | — | — | — | backend/models/reader.py:35 |
published_at |
DateTime(timezone=True) |
— | — | — | — | — | — | backend/models/reader.py:36 |
is_read |
Boolean |
— | — | — | — | — | False | backend/models/reader.py:37 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/reader.py:38 |
contacts — Contact¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/contact.py:34 |
workspace_id |
String |
— | no | — | yes | workspaces.id |
— | backend/models/contact.py:35 |
type |
String |
— | no | — | — | — | ContactType.PERSONAL.value | backend/models/contact.py:38 |
name |
String |
— | no | — | — | — | — | backend/models/contact.py:40 |
email |
String |
— | no | — | yes | — | — | backend/models/contact.py:41 |
phone |
String |
— | yes | — | — | — | — | backend/models/contact.py:42 |
company |
String |
— | yes | — | — | — | — | backend/models/contact.py:44 |
job_title |
String |
— | yes | — | — | — | — | backend/models/contact.py:45 |
address |
String |
— | yes | — | — | — | — | backend/models/contact.py:46 |
notes |
Text |
— | yes | — | — | — | — | backend/models/contact.py:47 |
emails |
Text |
— | — | — | — | — | '[]' | backend/models/contact.py:49 |
phones |
Text |
— | — | — | — | — | '[]' | backend/models/contact.py:50 |
addresses |
Text |
— | — | — | — | — | '[]' | backend/models/contact.py:51 |
google_resource_name |
String |
— | yes | — | yes | — | — | backend/models/contact.py:53 |
apple_resource_id |
String |
— | yes | — | — | — | — | backend/models/contact.py:54 |
last_synced_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/contact.py:56 |
source |
String |
— | no | — | — | — | ContactSource.LOCAL.value | backend/models/contact.py:57 |
photo_url |
String |
— | yes | — | — | — | — | backend/models/contact.py:58 |
tags |
String |
— | — | — | — | — | '[]' | backend/models/contact.py:60 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/contact.py:62 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/contact.py:63 |
feed_sources — FeedSource¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/reader.py:14 |
name |
String |
— | — | — | yes | — | — | backend/models/reader.py:15 |
url |
String |
— | — | yes | yes | — | — | backend/models/reader.py:16 |
category |
String |
— | — | — | yes | — | — | backend/models/reader.py:17 |
type |
String |
— | — | — | — | — | 'rss' | backend/models/reader.py:18 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/reader.py:19 |
hidden_events — HiddenEvent¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
event_id |
String |
yes | — | — | yes | — | — | backend/models/calendar.py:13 |
user_id |
String |
— | yes | — | yes | — | — | backend/models/calendar.py:14 |
hidden_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/calendar.py:15 |
mail_message_tags — MailMessageTag¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
message_id |
String |
yes | — | — | — | — | — | backend/models/mail.py:45 |
tag_id |
String |
yes | — | — | — | mail_tags.id |
— | backend/models/mail.py:46 |
account_email |
String |
— | — | — | — | — | '' | backend/models/mail.py:47 |
subject |
String |
— | — | — | — | — | '' | backend/models/mail.py:48 |
sender |
String |
— | — | — | — | — | '' | backend/models/mail.py:49 |
date_str |
String |
— | — | — | — | — | '' | backend/models/mail.py:50 |
mail_tags — MailTag¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/mail.py:36 |
name |
String |
— | no | — | — | — | — | backend/models/mail.py:37 |
color |
String |
— | — | — | — | — | '#3b82f6' | backend/models/mail.py:38 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:39 |
mail_views — MailView¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/mail.py:56 |
name |
String |
— | no | — | — | — | — | backend/models/mail.py:57 |
fields |
Text |
— | — | — | — | — | '[]' | backend/models/mail.py:58 |
filters |
Text |
— | — | — | — | — | '[]' | backend/models/mail.py:59 |
filter_logic |
String |
— | — | — | — | — | 'AND' | backend/models/mail.py:60 |
group_by |
String |
— | — | — | — | — | 'none' | backend/models/mail.py:61 |
sort_by |
String |
— | — | — | — | — | 'date' | backend/models/mail.py:62 |
sort_dir |
String |
— | — | — | — | — | 'desc' | backend/models/mail.py:63 |
actions |
Text |
— | — | — | — | — | '["archive","trash","mark_read"]' | backend/models/mail.py:64 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:65 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:66 |
memberships — Membership¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
user_id |
String |
yes | — | — | — | users.id |
— | backend/models/management.py:54 |
workspace_id |
String |
yes | — | — | — | workspaces.id |
— | backend/models/management.py:55 |
role |
String |
— | — | — | — | — | UserRole.VIEWER | backend/models/management.py:56 |
permissions |
String |
— | — | — | — | — | '{"capabilities": ["read"]}' | backend/models/management.py:57 |
joined_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:58 |
messages — MailMessage¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | yes | — | — | backend/models/mail.py:13 |
thread_id |
String |
— | — | — | yes | — | — | backend/models/mail.py:14 |
account_email |
String |
— | — | — | yes | — | — | backend/models/mail.py:15 |
subject |
String |
— | — | — | — | — | — | backend/models/mail.py:16 |
sender |
String |
— | — | — | — | — | — | backend/models/mail.py:17 |
recipient |
String |
— | — | — | — | — | — | backend/models/mail.py:18 |
cc |
String |
— | — | — | — | — | — | backend/models/mail.py:19 |
bcc |
String |
— | — | — | — | — | — | backend/models/mail.py:20 |
date |
String |
— | — | — | — | — | — | backend/models/mail.py:21 |
timestamp |
Integer |
— | — | — | — | — | — | backend/models/mail.py:22 |
body_text |
Text |
— | — | — | — | — | — | backend/models/mail.py:23 |
body_html |
Text |
— | — | — | — | — | — | backend/models/mail.py:24 |
snippet |
String |
— | — | — | — | — | — | backend/models/mail.py:25 |
is_read |
Boolean |
— | — | — | — | — | False | backend/models/mail.py:26 |
is_starred |
Boolean |
— | — | — | — | — | False | backend/models/mail.py:27 |
category |
String |
— | — | — | — | — | — | backend/models/mail.py:28 |
labels |
String |
— | — | — | — | — | — | backend/models/mail.py:29 |
raw_json |
Text |
— | — | — | — | — | — | backend/models/mail.py:30 |
newsletter_account — NewsletterAccount¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/reader.py:47 |
mail_server |
String |
— | — | — | — | — | '' | backend/models/reader.py:48 |
mail_port |
Integer |
— | — | — | — | — | 110 | backend/models/reader.py:49 |
mail_ssl |
String |
— | — | — | — | — | 'starttls' | backend/models/reader.py:51 |
email |
String |
— | — | — | — | — | '' | backend/models/reader.py:52 |
password |
String |
— | — | — | — | — | redacted | backend/models/reader.py:53 |
delete_after_ingest |
Boolean |
— | — | — | — | — | True | backend/models/reader.py:54 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/reader.py:55 |
notifications — Notification¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/notification.py:14 |
workspace_id |
String |
— | no | — | yes | workspaces.id |
— | backend/models/notification.py:15 |
level |
String |
— | no | — | — | — | 'INFO' | backend/models/notification.py:17 |
title |
String |
— | no | — | — | — | — | backend/models/notification.py:18 |
message |
Text |
— | no | — | — | — | — | backend/models/notification.py:19 |
is_read |
Boolean |
— | — | — | — | — | False | backend/models/notification.py:20 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/notification.py:24 |
pdf_annotations — PdfAnnotation¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/pdf_annotation.py:24 |
source_uri |
String |
— | no | — | yes | — | — | backend/models/pdf_annotation.py:28 |
page |
Integer |
— | no | — | — | — | — | backend/models/pdf_annotation.py:30 |
type |
String |
— | no | — | — | — | — | backend/models/pdf_annotation.py:34 |
color |
String |
— | — | — | — | — | '#ffeb3b' | backend/models/pdf_annotation.py:36 |
rects_json |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:40 |
text |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:42 |
comment |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:44 |
tags |
String |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:47 |
managed_key |
String |
— | yes | yes | yes | — | — | backend/models/pdf_annotation.py:51 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/pdf_annotation.py:53 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/pdf_annotation.py:57 |
share_links — ShareLink¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: uuid.uuid4().hex | backend/models/management.py:123 |
page_id |
String |
— | no | — | yes | — | — | backend/models/management.py:124 |
workspace_id |
String |
— | no | — | — | — | — | backend/models/management.py:125 |
vault_id |
String |
— | yes | — | — | — | — | backend/models/management.py:131 |
created_by |
String |
— | — | — | — | — | — | backend/models/management.py:132 |
permission |
String |
— | — | — | — | — | 'view' | backend/models/management.py:133 |
expires_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/management.py:134 |
revoked |
Integer |
— | — | — | — | — | 0 | backend/models/management.py:135 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:136 |
task_execution_history — TaskExecutionHistory¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/scheduler.py:12 |
task_name |
String |
— | no | — | yes | — | — | backend/models/scheduler.py:13 |
description |
String |
— | — | — | — | — | — | backend/models/scheduler.py:14 |
status |
String |
— | no | — | — | — | — | backend/models/scheduler.py:15 |
message |
Text |
— | — | — | — | — | — | backend/models/scheduler.py:16 |
started_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/scheduler.py:18 |
finished_at |
DateTime(timezone=True) |
— | — | — | — | — | — | backend/models/scheduler.py:19 |
duration_seconds |
Float |
— | — | — | — | — | — | backend/models/scheduler.py:20 |
users — User¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:20 |
email |
String |
— | no | yes | yes | — | — | backend/models/management.py:21 |
name |
String |
— | — | — | — | — | — | backend/models/management.py:22 |
avatar_url |
String |
— | — | — | — | — | — | backend/models/management.py:23 |
password_hash |
String |
— | yes | — | — | — | redacted | backend/models/management.py:28 |
auto_provisioned |
Boolean |
— | no | — | — | — | False | backend/models/management.py:35 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:36 |
vault_access — VaultAccess¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:82 |
vault_id |
String |
— | no | — | — | vaults.id |
— | backend/models/management.py:83 |
user_id |
String |
— | no | — | — | users.id |
— | backend/models/management.py:84 |
workspace_id |
String |
— | no | — | — | workspaces.id |
— | backend/models/management.py:85 |
permissions |
String |
— | — | — | — | — | '{"capabilities": ["read"]}' | backend/models/management.py:87 |
granted_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:88 |
vaults — Vault¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:66 |
workspace_id |
String |
— | — | — | — | workspaces.id |
— | backend/models/management.py:67 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:68 |
slug |
String |
— | — | — | yes | — | — | backend/models/management.py:72 |
path_override |
String |
— | — | — | — | — | — | backend/models/management.py:73 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:74 |
workspaces — Workspace¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:43 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:44 |
slug |
String |
— | — | yes | yes | — | — | backend/models/management.py:45 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:46 |