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 165 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:113 |
user_id |
String |
— | no | — | yes | users.id |
— | backend/models/management.py:114 |
workspace_id |
String |
— | yes | — | — | — | — | backend/models/management.py:115 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:116 |
token_hash |
String |
— | no | yes | yes | — | redacted | backend/models/management.py:117 |
token_prefix |
String |
— | no | — | — | — | redacted | backend/models/management.py:118 |
scopes |
String |
— | — | — | — | — | 'read,write' | backend/models/management.py:119 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:120 |
last_used_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/management.py:121 |
revoked |
Integer |
— | — | — | — | — | 0 | backend/models/management.py:122 |
articles — Article¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/reader.py:32 |
source_id |
Integer |
— | — | — | — | feed_sources.id |
— | backend/models/reader.py:33 |
title |
String |
— | — | — | — | — | — | backend/models/reader.py:34 |
url |
String |
— | — | yes | — | — | — | backend/models/reader.py:35 |
content |
Text |
— | — | — | — | — | — | backend/models/reader.py:40 |
full_content |
Text |
— | yes | — | — | — | — | backend/models/reader.py:41 |
published_at |
DateTime(timezone=True) |
— | — | — | — | — | — | backend/models/reader.py:42 |
is_read |
Boolean |
— | — | — | — | — | False | backend/models/reader.py:43 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/reader.py:44 |
contacts — Contact¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | no | — | — | — | lambda: str(uuid.uuid4()) | backend/models/contact.py:31 |
workspace_id |
String |
— | no | — | yes | workspaces.id |
— | backend/models/contact.py:32 |
type |
String |
— | no | — | — | — | ContactType.PERSONAL.value | backend/models/contact.py:35 |
name |
String |
— | no | — | — | — | — | backend/models/contact.py:37 |
email |
String |
— | no | — | yes | — | — | backend/models/contact.py:38 |
phone |
String |
— | yes | — | — | — | — | backend/models/contact.py:39 |
company |
String |
— | yes | — | — | — | — | backend/models/contact.py:41 |
job_title |
String |
— | yes | — | — | — | — | backend/models/contact.py:42 |
address |
String |
— | yes | — | — | — | — | backend/models/contact.py:43 |
notes |
Text |
— | yes | — | — | — | — | backend/models/contact.py:44 |
emails |
Text |
— | no | — | — | — | '[]' | backend/models/contact.py:46 |
phones |
Text |
— | no | — | — | — | '[]' | backend/models/contact.py:47 |
addresses |
Text |
— | no | — | — | — | '[]' | backend/models/contact.py:48 |
google_resource_name |
String |
— | yes | — | yes | — | — | backend/models/contact.py:50 |
apple_resource_id |
String |
— | yes | — | — | — | — | backend/models/contact.py:51 |
last_synced_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/contact.py:53 |
source |
String |
— | no | — | — | — | ContactSource.LOCAL.value | backend/models/contact.py:54 |
photo_url |
String |
— | yes | — | — | — | — | backend/models/contact.py:55 |
tags |
String |
— | no | — | — | — | '[]' | backend/models/contact.py:57 |
created_at |
DateTime(timezone=True) |
— | no | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/contact.py:59 |
updated_at |
DateTime(timezone=True) |
— | no | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/contact.py:62 |
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:15 |
user_id |
String |
— | yes | — | yes | — | — | backend/models/calendar.py:16 |
hidden_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/calendar.py:19 |
mail_message_tags — MailMessageTag¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
message_identity |
String |
yes | — | — | — | — | — | backend/models/mail.py:55 |
tag_id |
String |
yes | — | — | — | mail_tags.id |
— | backend/models/mail.py:56 |
message_id |
String |
— | no | — | yes | — | — | backend/models/mail.py:57 |
identity_kind |
String |
— | no | — | — | — | 'legacy' | backend/models/mail.py:58 |
account_email |
String |
— | — | — | — | — | '' | backend/models/mail.py:59 |
provider |
String |
— | — | — | — | — | '' | backend/models/mail.py:60 |
folder |
String |
— | — | — | — | — | '' | backend/models/mail.py:61 |
provider_uid |
String |
— | — | — | — | — | '' | backend/models/mail.py:62 |
subject |
String |
— | — | — | — | — | '' | backend/models/mail.py:63 |
sender |
String |
— | — | — | — | — | '' | backend/models/mail.py:64 |
date_str |
String |
— | — | — | — | — | '' | backend/models/mail.py:65 |
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:46 |
name |
String |
— | no | — | — | — | — | backend/models/mail.py:47 |
color |
String |
— | — | — | — | — | '#3b82f6' | backend/models/mail.py:48 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:49 |
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:71 |
name |
String |
— | no | — | — | — | — | backend/models/mail.py:72 |
fields |
Text |
— | — | — | — | — | '[]' | backend/models/mail.py:73 |
filters |
Text |
— | — | — | — | — | '[]' | backend/models/mail.py:74 |
filter_logic |
String |
— | — | — | — | — | 'AND' | backend/models/mail.py:75 |
group_by |
String |
— | — | — | — | — | 'none' | backend/models/mail.py:76 |
sort_by |
String |
— | — | — | — | — | 'date' | backend/models/mail.py:77 |
sort_dir |
String |
— | — | — | — | — | 'desc' | backend/models/mail.py:78 |
actions |
Text |
— | — | — | — | — | '["archive","trash","mark_read"]' | backend/models/mail.py:79 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:80 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/mail.py:81 |
memberships — Membership¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
user_id |
String |
yes | — | — | — | users.id |
— | backend/models/management.py:58 |
workspace_id |
String |
yes | — | — | — | workspaces.id |
— | backend/models/management.py:59 |
role |
String |
— | — | — | — | — | UserRole.VIEWER | backend/models/management.py:60 |
permissions |
String |
— | — | — | — | — | '{"capabilities": ["read"]}' | backend/models/management.py:61 |
joined_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:62 |
messages — MailMessage¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | — | — | yes | — | — | backend/models/mail.py:23 |
thread_id |
String |
— | — | — | yes | — | — | backend/models/mail.py:24 |
account_email |
String |
— | — | — | yes | — | — | backend/models/mail.py:25 |
subject |
String |
— | — | — | — | — | — | backend/models/mail.py:26 |
sender |
String |
— | — | — | — | — | — | backend/models/mail.py:27 |
recipient |
String |
— | — | — | — | — | — | backend/models/mail.py:28 |
cc |
String |
— | — | — | — | — | — | backend/models/mail.py:29 |
bcc |
String |
— | — | — | — | — | — | backend/models/mail.py:30 |
date |
String |
— | — | — | — | — | — | backend/models/mail.py:31 |
timestamp |
Integer |
— | — | — | — | — | — | backend/models/mail.py:32 |
body_text |
Text |
— | — | — | — | — | — | backend/models/mail.py:33 |
body_html |
Text |
— | — | — | — | — | — | backend/models/mail.py:34 |
snippet |
String |
— | — | — | — | — | — | backend/models/mail.py:35 |
is_read |
Boolean |
— | — | — | — | — | False | backend/models/mail.py:36 |
is_starred |
Boolean |
— | — | — | — | — | False | backend/models/mail.py:37 |
category |
String |
— | — | — | — | — | — | backend/models/mail.py:38 |
labels |
String |
— | — | — | — | — | — | backend/models/mail.py:39 |
raw_json |
Text |
— | — | — | — | — | — | backend/models/mail.py:40 |
newsletter_account — NewsletterAccount¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
Integer |
yes | — | — | yes | — | — | backend/models/reader.py:53 |
mail_server |
String |
— | — | — | — | — | '' | backend/models/reader.py:54 |
mail_port |
Integer |
— | — | — | — | — | 110 | backend/models/reader.py:55 |
mail_ssl |
String |
— | — | — | — | — | 'starttls' | backend/models/reader.py:57 |
email |
String |
— | — | — | — | — | '' | backend/models/reader.py:58 |
password |
String |
— | — | — | — | — | redacted | backend/models/reader.py:59 |
delete_after_ingest |
Boolean |
— | — | — | — | — | True | backend/models/reader.py:60 |
updated_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/reader.py:61 |
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 | no | — | yes | — | — | backend/models/pdf_annotation.py:25 |
source_uri |
String |
— | no | — | yes | — | — | backend/models/pdf_annotation.py:29 |
page |
Integer |
— | no | — | — | — | — | backend/models/pdf_annotation.py:31 |
type |
String |
— | no | — | — | — | — | backend/models/pdf_annotation.py:35 |
color |
String |
— | yes | — | — | — | '#ffeb3b' | backend/models/pdf_annotation.py:37 |
rects_json |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:41 |
text |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:43 |
comment |
Text |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:45 |
tags |
String |
— | yes | — | — | — | — | backend/models/pdf_annotation.py:48 |
managed_key |
String |
— | yes | yes | yes | — | — | backend/models/pdf_annotation.py:52 |
created_at |
DateTime(timezone=True) |
— | yes | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/pdf_annotation.py:59 |
updated_at |
DateTime(timezone=True) |
— | yes | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/pdf_annotation.py:64 |
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:136 |
page_id |
String |
— | no | — | yes | — | — | backend/models/management.py:137 |
workspace_id |
String |
— | no | — | — | — | — | backend/models/management.py:138 |
vault_id |
String |
— | yes | — | — | — | — | backend/models/management.py:144 |
created_by |
String |
— | — | — | — | — | — | backend/models/management.py:145 |
permission |
String |
— | — | — | — | — | 'view' | backend/models/management.py:146 |
expires_at |
DateTime(timezone=True) |
— | yes | — | — | — | — | backend/models/management.py:147 |
revoked |
Integer |
— | — | — | — | — | 0 | backend/models/management.py:148 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:149 |
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:15 |
task_name |
String |
— | no | — | yes | — | — | backend/models/scheduler.py:16 |
description |
String |
— | — | — | — | — | — | backend/models/scheduler.py:17 |
status |
String |
— | no | — | — | — | — | backend/models/scheduler.py:18 |
message |
Text |
— | — | — | — | — | — | backend/models/scheduler.py:19 |
started_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/scheduler.py:21 |
finished_at |
DateTime(timezone=True) |
— | — | — | — | — | — | backend/models/scheduler.py:22 |
duration_seconds |
Float |
— | — | — | — | — | — | backend/models/scheduler.py:23 |
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:22 |
email |
String |
— | no | yes | yes | — | — | backend/models/management.py:23 |
name |
String |
— | — | — | — | — | — | backend/models/management.py:24 |
avatar_url |
String |
— | — | — | — | — | — | backend/models/management.py:25 |
password_hash |
String |
— | yes | — | — | — | redacted | backend/models/management.py:30 |
auto_provisioned |
Boolean |
— | no | — | — | — | False | backend/models/management.py:37 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:38 |
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:90 |
vault_id |
String |
— | no | — | — | vaults.id |
— | backend/models/management.py:91 |
user_id |
String |
— | no | — | — | users.id |
— | backend/models/management.py:92 |
workspace_id |
String |
— | no | — | — | workspaces.id |
— | backend/models/management.py:93 |
permissions |
String |
— | — | — | — | — | '{"capabilities": ["read"]}' | backend/models/management.py:95 |
granted_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:96 |
vaults — Vault¶
| Column | Type | Primary key | Nullable | Unique | Index | Foreign key | Source default | Source |
|---|---|---|---|---|---|---|---|---|
id |
String |
yes | no | — | — | — | lambda: str(uuid.uuid4()) | backend/models/management.py:71 |
workspace_id |
String |
— | yes | — | — | workspaces.id |
— | backend/models/management.py:72 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:73 |
slug |
String |
— | yes | — | yes | — | — | backend/models/management.py:77 |
path_override |
String |
— | yes | — | — | — | — | backend/models/management.py:78 |
created_at |
DateTime(timezone=True) |
— | no | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:79 |
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:46 |
name |
String |
— | no | — | — | — | — | backend/models/management.py:47 |
slug |
String |
— | — | yes | yes | — | — | backend/models/management.py:48 |
created_at |
DateTime(timezone=True) |
— | — | — | — | — | lambda: datetime.now(timezone.utc) | backend/models/management.py:49 |