Data Model
All application data is stored in Snowflake Hybrid Tables within FORTY_TWO_FORMS_DB.APP_DATA.
All tables inherit created_at, updated_at, created_by, updated_by, and archived from TimestampMixin.
AccessLog
Section titled “AccessLog”Table: accesslog
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
submission_id | int (optional) | FK → submission.id | None | - |
project_id | int (optional) | FK → project.id | None | - |
account_id | int | FK → account.id | - | - |
action | str # "view", "edit", "create_submission", etc. | - | - | - |
details | str (optional) | - | None | - |
ip_address | str (optional) | - | None | - |
Account
Section titled “Account”Table: account
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
name | str | - | - | - |
email | str | IDX | - | - |
hashed_password | str (optional) | - | None | - |
auth_provider | str (optional) | - | None | - |
locale | str | - | ”en-US” | - |
currency_code | str | - | ”USD” | - |
snowflake_username | str (optional) | IDX | None | - |
last_login_at | datetime (optional) | - | None | - |
ApiKey
Section titled “ApiKey”Table: apikey
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
account_id | int | FK → account.id, IDX | - | - |
name | str # e.g. "Claude Code", "CI/CD" | - | - | - |
key_prefix | str # First 8 chars for identification (e.g. "ftf_Ab3x") | - | - | - |
key_hash | str # bcrypt hash of the full key | - | - | - |
last_used_at | datetime (optional) | - | null | - |
expires_at | datetime (optional) | - | null | - |
FormField
Section titled “FormField”Table: field
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id | - | - |
title | str | - | - | - |
description | str (optional) | - | None | - |
code | str (optional) | - | None | - |
field_type | str | - | - | - |
required | bool | - | False | - |
round_precision | int (optional) | - | None | - |
range_min | float (optional) | - | None | - |
range_max | float (optional) | - | None | - |
default_value | str (optional) | - | None | - |
field_group_id | int (optional) | - | None | - |
parent_field_id | int (optional) | FK → field.id | None | - |
multiline | bool | - | False | - |
include_time | bool | - | False | - |
allow_multiple | bool | - | False | - |
source | str (optional) | - | null | - |
FormVersion
Section titled “FormVersion”Table: formversion
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id | - | - |
version_number | int | - | 1 | - |
structure_json | str | - | - | - |
status | str | - | - | - |
published_at | datetime (optional) | - | None | - |
parent_version_id | int (optional) | - | null | - |
ImportLog
Section titled “ImportLog”Table: importlog
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id, IDX | - | - |
partition_id | int | FK → partition.id, IDX | - | - |
filename | str | - | - | - |
status | str | - | - | - |
total_rows | int | - | 0 | - |
rows_succeeded | int | - | 0 | - |
rows_failed | int | - | 0 | - |
column_mappings | str | - | - | - |
error_details | str (optional) | - | null | - |
Organization
Section titled “Organization”Table: organization
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
name | str | - | - | - |
slug | str | - | - | - |
is_personal | bool | - | - | - |
OrganizationMember
Section titled “OrganizationMember”Table: organizationmember
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
organization_id | int | FK → organization.id | - | - |
account_id | int (optional) | - | null | - |
role | str | - | - | - |
status | str | - | - | - |
seat_type | str | - | - | - |
is_admin | bool | - | - | - |
snowflake_username | str (optional) | - | None | - |
invite_email | str (optional) | - | None | - |
Partition
Section titled “Partition”Table: partition
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id | - | - |
title | str | - | - | - |
description | str (optional) | - | None | - |
Relationships: submissions → Submission
PartitionAccount
Section titled “PartitionAccount”Table: partitionaccount
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
partition_id | int | FK → partition.id | - | - |
account_id | int | FK → account.id | - | - |
can_submit | bool | - | False | - |
can_read | bool | - | False | - |
can_read_all | bool | - | False | - |
can_edit | bool | - | False | - |
can_edit_all | bool | - | False | - |
can_delete | bool | - | False | - |
can_delete_all | bool | - | False | - |
can_manage | bool | - | False | - |
PartitionAccountFieldGroup
Section titled “PartitionAccountFieldGroup”Table: partitionaccountfieldgroup
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
partition_account_id | int | FK → partitionaccount.id | - | - |
field_group_id | int | - | - | - |
permission | str | - | - | - |
Project
Section titled “Project”Table: project
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
org_id | int | FK → organization.id, IDX | - | - |
title | str | - | - | - |
description | str (optional) | - | None | - |
workflow_enabled | bool | - | False | - |
auto_save_enabled | bool | - | True | - |
multi_step_enabled | bool | - | False | - |
notify_on_submission | bool | - | False | - |
notify_on_review | bool | - | False | - |
export_database | str (optional) | - | None | - |
export_schema | str (optional) | - | None | - |
export_enabled | bool | - | False | - |
export_cron | str (optional) | - | None | - |
Relationships: fields → FormField, partitions → Partition
ProjectChangeLog
Section titled “ProjectChangeLog”Table: projectchangelog
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id | - | - |
action | str | - | - | - |
entity_type | str | - | - | - |
entity_name | str (optional) | - | None | - |
old_value | str (optional) | - | None | - |
new_value | str (optional) | - | None | - |
changed_by | int | FK → account.id | - | - |
ProjectFavorite
Section titled “ProjectFavorite”Table: projectfavorite
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
account_id | int | FK → account.id, IDX | - | - |
project_id | int | FK → project.id, IDX | - | - |
ProjectRelationship
Section titled “ProjectRelationship”Table: projectrelationship
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
parent_project_id | int | FK → project.id, IDX | - | - |
child_project_id | int | FK → project.id, IDX | - | - |
parent_field_id | int | FK → field.id | - | - |
child_field_id | int | FK → field.id | - | - |
label | str (optional) | - | None | - |
sort_order | int | - | 0 | - |
SemanticViewLink
Section titled “SemanticViewLink”Table: semanticviewlink
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
org_id | int | FK → organization.id, IDX | - | - |
connection_id | int | FK → snowflakeconnection.id | - | - |
view_fqn | str # "DATABASE.SCHEMA.VIEW_NAME" | - | - | - |
root_project_id | int | FK → project.id | - | - |
logical_table_map | str # JSON: {"TABLE_NAME": project_id, ...} | - | - | - |
relationship_map | str (optional) | - | null | - |
SnowflakeColumnPolicy
Section titled “SnowflakeColumnPolicy”Cached Snowflake policy metadata for a sync config’s source table.
Table: snowflakecolumnpolicy
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
sync_config_id | int | FK → snowflakesyncconfig.id, IDX | - | - |
column_name | str | - | - | - |
policy_kind | str # "MASKING_POLICY" or "ROW_ACCESS_POLICY" | - | - | - |
policy_fqn | str # Fully qualified policy name in Snowflake | - | - | - |
policy_ddl | str # Raw DDL from GET_DDL() | - | - | - |
masked_values | str (optional) | - | null | - |
last_refreshed_at | datetime | - | - | - |
SnowflakeConnection
Section titled “SnowflakeConnection”Table: snowflakeconnection
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
org_id | int | FK → organization.id, IDX | - | - |
name | str | - | - | - |
account_identifier | str | - | - | - |
warehouse | str | - | - | - |
database | str | - | - | - |
schema_name | str | - | - | - |
username | str | - | - | - |
encrypted_password | str (optional) | - | None | - |
role | str (optional) | - | None | - |
authenticator | str | - | - | - |
is_native | bool | - | False | - |
SnowflakeSyncConfig
Section titled “SnowflakeSyncConfig”Table: snowflakesyncconfig
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
project_id | int | FK → project.id | - | - |
connection_id | int (optional) | FK → snowflakeconnection.id | None | - |
direction | str # "import" (Snowflake -> 42Forms) or "export" (42Forms -> Snowflake) | - | - | - |
partition_id | int | FK → partition.id | - | - |
source_table | str # Fully qualified or unqualified table/view name in Snowflake | - | - | - |
source_type | str | - | - | - |
column_mappings | str # JSON string: maps Snowflake columns to 42Forms field IDs | - | - | - |
schedule_cron | str (optional) | - | null | - |
enabled | bool | - | True | - |
last_sync_at | datetime (optional) | - | None | - |
last_sync_status | str (optional) | - | null | - |
last_sync_message | str (optional) | - | None | - |
SnowflakeSyncLog
Section titled “SnowflakeSyncLog”Table: snowflakesynclog
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
sync_config_id | int | FK → snowflakesyncconfig.id | - | - |
direction | str | - | - | - |
started_at | datetime | - | - | - |
completed_at | datetime (optional) | - | None | - |
status | str # "running", "success", "partial", "error" | - | - | - |
rows_processed | int | - | 0 | - |
rows_succeeded | int | - | 0 | - |
rows_failed | int | - | 0 | - |
error_details | str (optional) | - | null | - |
created_by | int (optional) | - | None | - |
Submission
Section titled “Submission”Table: submission
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
partition_id | int | FK → partition.id, IDX | - | - |
status | str | IDX | ”draft” | - |
snowflake_row_key | str (optional) | IDX | None | - |
sync_config_id | int (optional) | FK → snowflakesyncconfig.id | None | - |
Relationships: fields → SubmissionField
SubmissionField
Section titled “SubmissionField”Table: submissionfield
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
submission_id | int | FK → submission.id, IDX | - | - |
field_id | int | FK → field.id, IDX | - | - |
value | str (optional) | - | None | - |
is_masked | bool | - | False | - |
SubmissionFieldHistory
Section titled “SubmissionFieldHistory”Table: submissionfieldhistory
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
submission_field_id | int | FK → submissionfield.id | - | - |
field_id | int | FK → field.id | - | - |
old_value | str (optional) | - | None | - |
new_value | str (optional) | - | None | - |
changed_by | int | - | - | - |
SubmissionStatusHistory
Section titled “SubmissionStatusHistory”Table: submissionstatushistory
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
submission_id | int | FK → submission.id, IDX | - | - |
from_status | str (optional) | - | None | - |
to_status | str | - | - | - |
changed_by | int | FK → account.id | - | - |
comment | str (optional) | - | None | - |
SystemLog
Section titled “SystemLog”Table: systemlog
| Field | Type | Key | Default | Description |
|---|---|---|---|---|
id | int (optional) | PK | None | - |
org_id | int | FK → organization.id, IDX | - | - |
project_id | int (optional) | FK → project.id, IDX | None | - |
severity | str # "error", "warning", "info" | - | - | - |
source | str # "formula_eval", "snowflake_sync", "data_format", etc. | - | - | - |
message | str | - | - | - |
details | str (optional) | - | None | - |
context | str (optional) | - | null | - |
created_at | datetime | - | - | - |