Skyvern/skyvern/forge/sdk/db/models.py

690 lines
28 KiB
Python

import datetime
from sqlalchemy import (
JSON,
Boolean,
Column,
DateTime,
Enum,
ForeignKey,
Index,
Integer,
Numeric,
String,
UnicodeText,
UniqueConstraint,
desc,
)
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlalchemy.orm import DeclarativeBase
from skyvern.forge.sdk.db.enums import OrganizationAuthTokenType, TaskType
from skyvern.forge.sdk.db.id import (
generate_action_id,
generate_ai_suggestion_id,
generate_artifact_id,
generate_aws_secret_parameter_id,
generate_bitwarden_credit_card_data_parameter_id,
generate_bitwarden_login_credential_parameter_id,
generate_bitwarden_sensitive_information_parameter_id,
generate_credential_id,
generate_credential_parameter_id,
generate_org_id,
generate_organization_auth_token_id,
generate_organization_bitwarden_collection_id,
generate_output_parameter_id,
generate_persistent_browser_session_id,
generate_step_id,
generate_task_generation_id,
generate_task_id,
generate_task_run_id,
generate_task_v2_id,
generate_thought_id,
generate_totp_code_id,
generate_workflow_id,
generate_workflow_parameter_id,
generate_workflow_permanent_id,
generate_workflow_run_block_id,
generate_workflow_run_id,
)
from skyvern.forge.sdk.schemas.task_v2 import ThoughtType
class Base(AsyncAttrs, DeclarativeBase):
pass
class TaskModel(Base):
__tablename__ = "tasks"
__table_args__ = (Index("idx_tasks_org_created", "organization_id", "created_at"),)
task_id = Column(String, primary_key=True, index=True, default=generate_task_id)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
status = Column(String, index=True)
webhook_callback_url = Column(String)
totp_verification_url = Column(String)
totp_identifier = Column(String)
title = Column(String)
task_type = Column(String, default=TaskType.general)
url = Column(String)
navigation_goal = Column(String)
data_extraction_goal = Column(String)
complete_criterion = Column(String)
terminate_criterion = Column(String)
navigation_payload = Column(JSON)
extracted_information = Column(JSON)
failure_reason = Column(String)
proxy_location = Column(String)
extracted_information_schema = Column(JSON)
workflow_run_id = Column(String, ForeignKey("workflow_runs.workflow_run_id"), index=True)
order = Column(Integer, nullable=True)
retry = Column(Integer, nullable=True)
error_code_mapping = Column(JSON, nullable=True)
errors = Column(JSON, default=[], nullable=False)
max_steps_per_run = Column(Integer, nullable=True)
application = Column(String, nullable=True)
include_action_history_in_verification = Column(Boolean, default=False, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False, index=True)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
index=True,
)
class StepModel(Base):
__tablename__ = "steps"
__table_args__ = (
Index("org_task_index", "organization_id", "task_id"),
Index("created_at_org_index", "created_at", "organization_id"),
)
step_id = Column(String, primary_key=True, index=True, default=generate_step_id)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
task_id = Column(String, ForeignKey("tasks.task_id"), index=True)
status = Column(String)
output = Column(JSON)
order = Column(Integer)
is_last = Column(Boolean, default=False)
retry_index = Column(Integer, default=0)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
input_token_count = Column(Integer, default=0)
output_token_count = Column(Integer, default=0)
reasoning_token_count = Column(Integer, default=0)
cached_token_count = Column(Integer, default=0)
step_cost = Column(Numeric, default=0)
class OrganizationModel(Base):
__tablename__ = "organizations"
organization_id = Column(String, primary_key=True, index=True, default=generate_org_id)
organization_name = Column(String, nullable=False)
webhook_callback_url = Column(UnicodeText)
max_steps_per_run = Column(Integer, nullable=True)
max_retries_per_step = Column(Integer, nullable=True)
domain = Column(String, nullable=True, index=True)
bw_organization_id = Column(String, nullable=True, default=None)
bw_collection_ids = Column(JSON, nullable=True, default=None)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
class OrganizationAuthTokenModel(Base):
__tablename__ = "organization_auth_tokens"
id = Column(
String,
primary_key=True,
index=True,
default=generate_organization_auth_token_id,
)
organization_id = Column(String, ForeignKey("organizations.organization_id"), index=True, nullable=False)
token_type = Column(Enum(OrganizationAuthTokenType), nullable=False)
token = Column(String, index=True, nullable=False)
valid = Column(Boolean, nullable=False, default=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class ArtifactModel(Base):
__tablename__ = "artifacts"
__table_args__ = (Index("org_task_step_index", "organization_id", "task_id", "step_id"),)
artifact_id = Column(String, primary_key=True, index=True, default=generate_artifact_id)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
workflow_run_id = Column(String, index=True)
workflow_run_block_id = Column(String, index=True)
observer_cruise_id = Column(String, index=True)
observer_thought_id = Column(String, index=True)
ai_suggestion_id = Column(String, index=True)
task_id = Column(String)
step_id = Column(String, index=True)
artifact_type = Column(String)
uri = Column(String)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
class WorkflowModel(Base):
__tablename__ = "workflows"
__table_args__ = (
UniqueConstraint(
"organization_id",
"workflow_permanent_id",
"version",
name="uc_org_permanent_id_version",
),
Index("permanent_id_version_idx", "workflow_permanent_id", "version"),
Index("organization_id_title_idx", "organization_id", "title"),
Index("workflow_oid_status_idx", "organization_id", "status"),
)
workflow_id = Column(String, primary_key=True, index=True, default=generate_workflow_id)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
title = Column(String, nullable=False)
description = Column(String, nullable=True)
workflow_definition = Column(JSON, nullable=False)
proxy_location = Column(String)
webhook_callback_url = Column(String)
totp_verification_url = Column(String)
totp_identifier = Column(String)
persist_browser_session = Column(Boolean, default=False, nullable=False)
model = Column(JSON, nullable=True)
status = Column(String, nullable=False, default="published")
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
workflow_permanent_id = Column(String, nullable=False, default=generate_workflow_permanent_id, index=True)
version = Column(Integer, default=1, nullable=False)
is_saved_task = Column(Boolean, default=False, nullable=False)
class WorkflowRunModel(Base):
__tablename__ = "workflow_runs"
__table_args__ = (Index("idx_workflow_runs_org_created", "organization_id", "created_at"),)
workflow_run_id = Column(String, primary_key=True, index=True, default=generate_workflow_run_id)
workflow_id = Column(String, nullable=False)
workflow_permanent_id = Column(String, nullable=False, index=True)
# workfow runs with parent_workflow_run_id are nested workflow runs which won't show up in the workflow run history
parent_workflow_run_id = Column(String, nullable=True, index=True)
organization_id = Column(String, nullable=False, index=True)
status = Column(String, nullable=False)
failure_reason = Column(String)
proxy_location = Column(String)
webhook_callback_url = Column(String)
totp_verification_url = Column(String)
totp_identifier = Column(String)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
index=True,
)
class WorkflowParameterModel(Base):
__tablename__ = "workflow_parameters"
workflow_parameter_id = Column(String, primary_key=True, index=True, default=generate_workflow_parameter_id)
workflow_parameter_type = Column(String, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
workflow_id = Column(String, index=True, nullable=False)
default_value = Column(String, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class OutputParameterModel(Base):
__tablename__ = "output_parameters"
output_parameter_id = Column(String, primary_key=True, index=True, default=generate_output_parameter_id)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
workflow_id = Column(String, index=True, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class AWSSecretParameterModel(Base):
__tablename__ = "aws_secret_parameters"
aws_secret_parameter_id = Column(String, primary_key=True, index=True, default=generate_aws_secret_parameter_id)
workflow_id = Column(String, index=True, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
aws_key = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class BitwardenLoginCredentialParameterModel(Base):
__tablename__ = "bitwarden_login_credential_parameters"
bitwarden_login_credential_parameter_id = Column(
String,
primary_key=True,
index=True,
default=generate_bitwarden_login_credential_parameter_id,
)
workflow_id = Column(String, index=True, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
bitwarden_client_id_aws_secret_key = Column(String, nullable=False)
bitwarden_client_secret_aws_secret_key = Column(String, nullable=False)
bitwarden_master_password_aws_secret_key = Column(String, nullable=False)
bitwarden_collection_id = Column(String, nullable=True, default=None)
bitwarden_item_id = Column(String, nullable=True, default=None)
url_parameter_key = Column(String, nullable=True, default=None)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class BitwardenSensitiveInformationParameterModel(Base):
__tablename__ = "bitwarden_sensitive_information_parameters"
bitwarden_sensitive_information_parameter_id = Column(
String,
primary_key=True,
index=True,
default=generate_bitwarden_sensitive_information_parameter_id,
)
workflow_id = Column(String, index=True, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
bitwarden_client_id_aws_secret_key = Column(String, nullable=False)
bitwarden_client_secret_aws_secret_key = Column(String, nullable=False)
bitwarden_master_password_aws_secret_key = Column(String, nullable=False)
bitwarden_collection_id = Column(String, nullable=False)
bitwarden_identity_key = Column(String, nullable=False)
# This is a list of fields to extract from the Bitwarden Identity.
bitwarden_identity_fields = Column(JSON, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(
DateTime,
default=datetime.datetime.utcnow,
onupdate=datetime.datetime.utcnow,
nullable=False,
)
deleted_at = Column(DateTime, nullable=True)
class BitwardenCreditCardDataParameterModel(Base):
__tablename__ = "bitwarden_credit_card_data_parameters"
bitwarden_credit_card_data_parameter_id = Column(
String,
primary_key=True,
index=True,
default=generate_bitwarden_credit_card_data_parameter_id,
)
workflow_id = Column(String, index=True, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
bitwarden_client_id_aws_secret_key = Column(String, nullable=False)
bitwarden_client_secret_aws_secret_key = Column(String, nullable=False)
bitwarden_master_password_aws_secret_key = Column(String, nullable=False)
bitwarden_collection_id = Column(String, nullable=False)
bitwarden_item_id = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
deleted_at = Column(DateTime, nullable=True)
class CredentialParameterModel(Base):
__tablename__ = "credential_parameters"
credential_parameter_id = Column(String, primary_key=True, index=True, default=generate_credential_parameter_id)
workflow_id = Column(String, index=True, nullable=False)
key = Column(String, nullable=False)
description = Column(String, nullable=True)
credential_id = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
deleted_at = Column(DateTime, nullable=True)
class WorkflowRunParameterModel(Base):
__tablename__ = "workflow_run_parameters"
workflow_run_id = Column(
String,
primary_key=True,
index=True,
)
workflow_parameter_id = Column(
String,
primary_key=True,
index=True,
)
# Can be bool | int | float | str | dict | list depending on the workflow parameter type
value = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
class WorkflowRunOutputParameterModel(Base):
__tablename__ = "workflow_run_output_parameters"
workflow_run_id = Column(
String,
primary_key=True,
index=True,
)
output_parameter_id = Column(
String,
primary_key=True,
index=True,
)
value = Column(JSON, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
class TaskGenerationModel(Base):
"""
Generate a task based on the prompt (natural language description of the task) from the user
"""
__tablename__ = "task_generations"
task_generation_id = Column(String, primary_key=True, default=generate_task_generation_id)
organization_id = Column(String, nullable=False)
user_prompt = Column(String, nullable=False)
user_prompt_hash = Column(String, index=True)
url = Column(String)
navigation_goal = Column(String)
navigation_payload = Column(JSON)
data_extraction_goal = Column(String)
extracted_information_schema = Column(JSON)
suggested_title = Column(String) # task title suggested by the language model
llm = Column(String) # language model to use
llm_prompt = Column(String) # The prompt sent to the language model
llm_response = Column(String) # The response from the language model
source_task_generation_id = Column(String, index=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class AISuggestionModel(Base):
__tablename__ = "ai_suggestions"
ai_suggestion_id = Column(String, primary_key=True, default=generate_ai_suggestion_id)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
ai_suggestion_type = Column(String)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class TOTPCodeModel(Base):
__tablename__ = "totp_codes"
totp_code_id = Column(String, primary_key=True, default=generate_totp_code_id)
totp_identifier = Column(String, nullable=False, index=True)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
task_id = Column(String, ForeignKey("tasks.task_id"))
workflow_id = Column(String, ForeignKey("workflows.workflow_id"))
workflow_run_id = Column(String, ForeignKey("workflow_runs.workflow_run_id"))
content = Column(String, nullable=False)
code = Column(String, nullable=False)
source = Column(String)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False, index=True)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
expired_at = Column(DateTime, index=True)
class ActionModel(Base):
__tablename__ = "actions"
__table_args__ = (
Index("action_org_task_step_index", "organization_id", "task_id", "step_id"),
Index("action_org_created_at_index", "organization_id", desc("created_at")),
)
action_id = Column(String, primary_key=True, index=True, default=generate_action_id)
action_type = Column(String, nullable=False)
source_action_id = Column(String, nullable=True, index=True)
organization_id = Column(String, nullable=True)
workflow_run_id = Column(String, nullable=True)
task_id = Column(String, nullable=False, index=True)
step_id = Column(String, nullable=False)
step_order = Column(Integer, nullable=False)
action_order = Column(Integer, nullable=False)
status = Column(String, nullable=False)
reasoning = Column(String, nullable=True)
intention = Column(String, nullable=True)
response = Column(String, nullable=True)
element_id = Column(String, nullable=True)
skyvern_element_hash = Column(String, nullable=True)
skyvern_element_data = Column(JSON, nullable=True)
action_json = Column(JSON, nullable=True)
confidence_float = Column(Numeric, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class WorkflowRunBlockModel(Base):
__tablename__ = "workflow_run_blocks"
__table_args__ = (Index("wfrb_org_wfr_index", "organization_id", "workflow_run_id"),)
workflow_run_block_id = Column(String, primary_key=True, default=generate_workflow_run_block_id)
workflow_run_id = Column(String, nullable=False)
# this is the inner workflow run id of the taskv2 block
block_workflow_run_id = Column(String, nullable=True)
parent_workflow_run_block_id = Column(String, nullable=True)
organization_id = Column(String, nullable=True)
description = Column(String, nullable=True)
task_id = Column(String, nullable=True)
label = Column(String, nullable=True)
block_type = Column(String, nullable=False)
status = Column(String, nullable=False)
output = Column(JSON, nullable=True)
continue_on_failure = Column(Boolean, nullable=False, default=False)
failure_reason = Column(String, nullable=True)
# for loop block
loop_values = Column(JSON, nullable=True)
current_value = Column(String, nullable=True)
current_index = Column(Integer, nullable=True)
# email block
recipients = Column(JSON, nullable=True)
attachments = Column(JSON, nullable=True)
subject = Column(String, nullable=True)
body = Column(String, nullable=True)
# prompt block
prompt = Column(String, nullable=True)
# wait block
wait_sec = Column(Integer, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class TaskV2Model(Base):
__tablename__ = "observer_cruises"
__table_args__ = (Index("oc_org_wfr_index", "organization_id", "workflow_run_id"),)
# observer_cruise_id is the task_id for task v2
observer_cruise_id = Column(String, primary_key=True, default=generate_task_v2_id)
status = Column(String, nullable=False, default="created")
organization_id = Column(String, nullable=True)
workflow_run_id = Column(String, nullable=True)
workflow_id = Column(String, nullable=True)
workflow_permanent_id = Column(String, nullable=True)
prompt = Column(UnicodeText, nullable=True)
url = Column(String, nullable=True)
summary = Column(String, nullable=True)
output = Column(JSON, nullable=True)
webhook_callback_url = Column(String, nullable=True)
totp_verification_url = Column(String, nullable=True)
totp_identifier = Column(String, nullable=True)
proxy_location = Column(String, nullable=True)
extracted_information_schema = Column(JSON, nullable=True)
error_code_mapping = Column(JSON, nullable=True)
max_steps = Column(Integer, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class ThoughtModel(Base):
__tablename__ = "observer_thoughts"
__table_args__ = (Index("observer_cruise_index", "organization_id", "observer_cruise_id"),)
observer_thought_id = Column(String, primary_key=True, default=generate_thought_id)
organization_id = Column(String, nullable=True)
observer_cruise_id = Column(String, nullable=False)
workflow_run_id = Column(String, nullable=True)
workflow_run_block_id = Column(String, nullable=True)
workflow_id = Column(String, nullable=True)
workflow_permanent_id = Column(String, nullable=True)
user_input = Column(UnicodeText, nullable=True)
observation = Column(String, nullable=True)
thought = Column(String, nullable=True)
answer = Column(String, nullable=True)
input_token_count = Column(Integer, nullable=True)
output_token_count = Column(Integer, nullable=True)
reasoning_token_count = Column(Integer, nullable=True)
cached_token_count = Column(Integer, nullable=True)
thought_cost = Column(Numeric, nullable=True)
observer_thought_type = Column(String, nullable=True, default=ThoughtType.plan)
observer_thought_scenario = Column(String, nullable=True)
output = Column(JSON, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class PersistentBrowserSessionModel(Base):
__tablename__ = "persistent_browser_sessions"
persistent_browser_session_id = Column(String, primary_key=True, default=generate_persistent_browser_session_id)
organization_id = Column(String, nullable=False, index=True)
runnable_type = Column(String, nullable=True)
runnable_id = Column(String, nullable=True, index=True)
browser_id = Column(String, nullable=True)
browser_address = Column(String, nullable=True)
status = Column(String, nullable=True, default="created")
timeout_minutes = Column(Integer, nullable=True)
started_at = Column(DateTime, nullable=True)
completed_at = Column(DateTime, nullable=True)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False, index=True)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
deleted_at = Column(DateTime, nullable=True)
class TaskRunModel(Base):
__tablename__ = "task_runs"
__table_args__ = (
Index("task_run_org_url_index", "organization_id", "url_hash", "cached"),
Index("task_run_org_run_id_index", "organization_id", "run_id"),
)
task_run_id = Column(String, primary_key=True, default=generate_task_run_id)
organization_id = Column(String, nullable=False)
task_run_type = Column(String, nullable=False)
run_id = Column(String, nullable=False)
title = Column(String, nullable=True)
url = Column(String, nullable=True)
url_hash = Column(String, nullable=True)
cached = Column(Boolean, nullable=False, default=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class OrganizationBitwardenCollectionModel(Base):
__tablename__ = "organization_bitwarden_collections"
organization_bitwarden_collection_id = Column(
String, primary_key=True, default=generate_organization_bitwarden_collection_id
)
organization_id = Column(String, nullable=False, index=True)
collection_id = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
class CredentialModel(Base):
__tablename__ = "credentials"
credential_id = Column(String, primary_key=True, default=generate_credential_id)
organization_id = Column(String, nullable=False)
item_id = Column(String, nullable=True)
name = Column(String, nullable=False)
credential_type = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
deleted_at = Column(DateTime, nullable=True)