create table model_platform.consumer_inbox ( consumer_name varchar(128) not null, event_id char(26) not null, process_status varchar(16) default 'processing' not null comment 'processing/succeeded/failed', created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, message_id varchar(128) null comment 'Inbox message ID', processed_at datetime(3) null, error_message varchar(2000) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, primary key (consumer_name, event_id) ) comment '消费者幂等 Inbox,防止 Stream 重投导致重复执行'; create index idx_consumer_inbox_status on model_platform.consumer_inbox (consumer_name, process_status, created_at); create table model_platform.data_resources ( resource_id char(26) not null primary key, workspace_id char(26) not null, storage_object_id char(26) not null, owner_user_id char(26) not null, resource_name varchar(255) not null, visibility varchar(16) default 'private' not null, status varchar(16) default 'active' not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), description varchar(1000) null, schema_json json null comment '字段结构、行数等可选元数据', is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null ) comment '数据资源'; create index idx_data_resources_owner on model_platform.data_resources (owner_user_id, status); create index idx_data_resources_workspace on model_platform.data_resources (workspace_id, visibility, status); create table model_platform.outbox_events ( event_id char(26) not null primary key, aggregate_type varchar(64) not null, aggregate_id varchar(128) not null, event_type varchar(128) not null, schema_version smallint default 1 not null, payload_json json not null, event_status varchar(16) default 'pending' not null comment 'pending/published/failed', available_at datetime(3) default CURRENT_TIMESTAMP(3) not null, retry_count int default 0 not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, trace_id varchar(64) null, idempotency_key varchar(128) null, published_at datetime(3) null, last_error varchar(2000) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null ) comment '事务 Outbox;提交后发布到内部事件总线'; create index idx_outbox_aggregate on model_platform.outbox_events (aggregate_type, aggregate_id, created_at); create index idx_outbox_idempotency on model_platform.outbox_events (idempotency_key); create index idx_outbox_pending on model_platform.outbox_events (event_status, available_at, created_at); create table model_platform.permissions ( permission_id char(26) not null primary key, permission_code varchar(128) not null, permission_name varchar(100) not null, module_code varchar(64) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, description varchar(500) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_permissions_code unique (permission_code) ) comment '权限点'; create index idx_permissions_module on model_platform.permissions (module_code); create table model_platform.role_permissions ( role_id char(26) not null, permission_id char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, primary key (role_id, permission_id) ) comment '角色权限'; create index fk_role_permissions_permission on model_platform.role_permissions (permission_id); create table model_platform.roles ( role_id char(26) not null primary key, role_code varchar(64) not null, role_name varchar(100) not null, role_scope varchar(16) not null comment 'platform/workspace', is_builtin tinyint(1) default 0 not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), description varchar(500) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_roles_code unique (role_code) ) comment '角色'; create table model_platform.schedule_edges ( edge_id char(26) not null primary key, schedule_id char(26) not null, source_node_id char(26) not null, target_node_id char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, condition_expr varchar(1000) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_schedule_edges_pair unique (schedule_id, source_node_id, target_node_id) ) comment 'DAG 有向边'; create index fk_schedule_edges_source on model_platform.schedule_edges (source_node_id); create index idx_schedule_edges_target on model_platform.schedule_edges (target_node_id); create table model_platform.schedule_node_runs ( node_run_id char(26) not null primary key, run_id char(26) not null, node_id char(26) not null, versions_id char(26) not null, attempt_no int default 1 not null, node_status varchar(24) default 'queued' not null comment 'queued/running/succeeded/failed/skipped/cancelled/timed_out', state_version int default 0 not null comment '乐观锁版本', created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, started_at datetime(3) null, finished_at datetime(3) null, duration_ms bigint null, exit_code int null, message varchar(2000) null, metrics_json json null, logs_object_id char(26) null, result_object_id char(26) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_node_runs_attempt unique (run_id, node_id, attempt_no) ) comment '调度节点运行与重试'; create index fk_node_runs_logs on model_platform.schedule_node_runs (logs_object_id); create index fk_node_runs_node on model_platform.schedule_node_runs (node_id); create index fk_node_runs_result on model_platform.schedule_node_runs (result_object_id); create index idx_node_runs_status on model_platform.schedule_node_runs (run_id, node_status); create index idx_node_runs_version on model_platform.schedule_node_runs (versions_id); create table model_platform.schedule_nodes ( node_id char(26) not null primary key, schedule_id char(26) not null, node_key varchar(64) not null comment '画布内稳定标识', node_name varchar(255) not null, versions_id char(26) not null, python_version varchar(8) default '3.12' not null comment '节点执行 Python 版本(3.8/3.10/3.12)', timeout_seconds int default 600 not null, retry_count int default 0 not null, retry_interval_sec int default 5 not null, position_x decimal(10, 2) default (0.00) not null, position_y decimal(10, 2) default (0.00) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), arguments_json json null, env_refs_json json null comment '只存密钥引用,不存明文密钥', is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_schedule_nodes_key unique (schedule_id, node_key) ) comment 'DAG 节点,必须引用稳定版本'; create index idx_schedule_nodes_version on model_platform.schedule_nodes (versions_id); create table model_platform.schedule_runs ( run_id char(26) not null primary key, schedule_id char(26) not null, workspace_id char(26) not null, workflow_version int not null, trigger_type varchar(16) not null comment 'manual/cron/api/retry', idempotency_key varchar(128) not null, run_status varchar(24) default 'queued' not null comment 'queued/running/succeeded/failed/cancelled/timed_out', state_version int default 0 not null comment '乐观锁版本', schedule_snapshot json not null comment '执行时 DAG 快照', queued_at datetime(3) default CURRENT_TIMESTAMP(3) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, triggered_by char(26) null, started_at datetime(3) null, finished_at datetime(3) null, duration_ms bigint null, error_code varchar(64) null, error_message text null, logs_object_id char(26) null, result_object_id char(26) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_schedule_runs_idempotency unique (idempotency_key) ) comment '调度运行'; create index fk_schedule_runs_logs on model_platform.schedule_runs (logs_object_id); create index fk_schedule_runs_result on model_platform.schedule_runs (result_object_id); create index fk_schedule_runs_user on model_platform.schedule_runs (triggered_by); create index idx_schedule_runs_schedule on model_platform.schedule_runs (schedule_id, created_at); create index idx_schedule_runs_status on model_platform.schedule_runs (run_status, queued_at); create index idx_schedule_runs_workspace_status on model_platform.schedule_runs (workspace_id, run_status, queued_at); create table model_platform.schedules ( schedule_id char(26) not null primary key, workspace_id char(26) not null, schedule_name varchar(255) not null, trigger_type varchar(16) default 'cron' not null comment 'manual/cron/api', timezone varchar(64) default 'Asia/Shanghai' not null, enabled tinyint(1) default 0 not null, workflow_version int default 1 not null, max_concurrency int default 1 not null, failure_policy varchar(24) default 'stop' not null comment 'stop/continue', created_by char(26) not null, updated_by char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), description varchar(1000) null, cron_expression varchar(128) null, last_run_at datetime(3) null, next_run_at datetime(3) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null ) comment '调度方案'; create index fk_schedules_created_by on model_platform.schedules (created_by); create index fk_schedules_updated_by on model_platform.schedules (updated_by); create index idx_schedules_due on model_platform.schedules (enabled, next_run_at); create index idx_schedules_workspace on model_platform.schedules (workspace_id, enabled, updated_at); create table model_platform.scripts ( script_id char(26) not null primary key, workspace_id char(26) not null, current_object_id char(26) not null comment '当前工作副本', owner_user_id char(26) not null, script_name varchar(255) not null, script_type varchar(16) not null comment 'python/notebook', visibility varchar(16) default 'private' not null, status varchar(16) default 'active' not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), is_deleted tinyint(1) default 0 not null, is_locked tinyint(1) default 1 not null, deleted_at datetime(3) null ) comment '可执行 Python/Notebook 脚本'; create index idx_scripts_owner on model_platform.scripts (owner_user_id, status); create index idx_scripts_workspace on model_platform.scripts (workspace_id, script_type, visibility, status); create table model_platform.storage_objects ( storage_object_id char(26) not null primary key, workspace_id char(26) not null, object_type varchar(16) not null comment 'file/directory', usage_type varchar(32) not null comment 'working_copy/public_script/data_resource/version_artifact/snapshot/run_log/run_result', storage_backend varchar(16) not null comment 's3', storage_uri varchar(1500) not null, file_name varchar(255) not null, size_bytes bigint default 0 not null, visibility varchar(16) default 'private' not null comment 'private/workspace/public', is_immutable tinyint(1) default 0 not null, object_status varchar(24) default 'available' not null comment 'uploading/available/deleting/deleted/failed', created_by char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), owner_user_id char(26) null, relative_path varchar(1024) null comment 'Workspace 相对路径', path_hash binary(32) null comment 'SHA-256(relative_path),由应用写入', bucket_name varchar(128) null, object_key varchar(1024) null, object_key_hash binary(32) null comment 'SHA-256(object_key),由应用写入', object_key_hash_active binary(32) as ((case when (`object_status` = _utf8mb4'available') then `object_key_hash` else NULL end)) comment 'VIRTUAL generated column used by uk_storage_bucket_key_active', file_extension varchar(32) null, mime_type varchar(255) null, content_hash char(64) null comment 'SHA-256 hex', object_etag varchar(255) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, trash_key varchar(1100) null comment 'Path inside the trash bucket where the soft-deleted bytes live. Format: ''{source_bucket}/{object_key}'' so a restore is a same-key copy back to the source bucket. NULL while the row is still available.', constraint uk_storage_bucket_key_active unique (storage_backend, bucket_name, object_key_hash_active) ) comment 'Workspace 文件和 RustFS 对象的统一元数据;目录树走 materialized path (relative_path),不要 join 邻接表列——已删除。'; create index fk_storage_created_by on model_platform.storage_objects (created_by); create index idx_storage_content_hash on model_platform.storage_objects (content_hash); create index idx_storage_owner on model_platform.storage_objects (owner_user_id, object_status); create index idx_storage_workspace_path on model_platform.storage_objects (workspace_id, storage_backend, path_hash); create index idx_storage_workspace_relative_path on model_platform.storage_objects (workspace_id, relative_path(255)); create index idx_storage_workspace_usage on model_platform.storage_objects (workspace_id, usage_type, object_status); create table model_platform.upload_sessions ( upload_id char(26) not null primary key, workspace_id char(26) not null, user_id char(26) not null, idempotency_key varchar(128) not null, bucket_name varchar(128) not null, object_key varchar(1024) not null, object_key_hash binary(32) not null, upload_status varchar(24) default 'created' not null comment 'created/uploading/completed/expired/aborted/failed', expires_at datetime(3) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), multipart_upload_id varchar(255) null, expected_size_bytes bigint null, expected_hash char(64) null, content_type varchar(255) null, storage_object_id char(26) null, completed_at datetime(3) null, file_name varchar(255) default '' not null, usage_type varchar(32) default 'working_copy' not null comment 'data_resource/version_artifact/snapshot/run_log/run_result/working_copy/public_script', visibility varchar(16) default 'private' not null comment 'private/workspace/public', is_immutable tinyint(1) default 0 not null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_upload_sessions_idempotency unique (idempotency_key) ) comment 'RustFS 预签名上传会话;URL 本身不持久化'; create index fk_upload_sessions_storage_object on model_platform.upload_sessions (storage_object_id); create index fk_upload_sessions_user on model_platform.upload_sessions (user_id); create index idx_upload_sessions_expiry on model_platform.upload_sessions (upload_status, expires_at); create index idx_upload_sessions_object_key on model_platform.upload_sessions (bucket_name, object_key_hash); create index idx_upload_sessions_workspace on model_platform.upload_sessions (workspace_id, user_id, created_at); create table model_platform.users ( user_id char(26) not null primary key, username varchar(64) not null, display_name varchar(100) not null, password_hash varchar(255) not null, status varchar(16) default 'active' not null comment 'active/disabled/locked', created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), email varchar(255) null, platform_role_id char(26) null, avatar_uri varchar(1000) null, last_login_at datetime(3) null, is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_users_email unique (email), constraint uk_users_username unique (username) ) comment '平台用户'; create index fk_users_platform_role on model_platform.users (platform_role_id); create index idx_users_status on model_platform.users (status); create table model_platform.versions ( versions_id char(26) not null comment '稳定版本唯一 ID' primary key, workspace_id char(26) not null, script_id char(26) not null, source_object_id char(26) not null comment '发布时的源对象', artifact_object_id char(26) not null comment 'S3 不可变版本制品', version_no int not null, version_label varchar(32) not null comment '例如 v1.0', source_path varchar(1024) not null comment '发布时路径快照', artifact_path varchar(1500) not null, content_hash char(64) not null, file_size_bytes bigint default 0 not null, visibility varchar(16) default 'private' not null, created_by char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, release_note varchar(1000) null, schedule_hidden_at datetime(3) null comment '从调度稳定版本列表移除的时间;不影响版本和运行历史', is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_versions_artifact unique (artifact_object_id), constraint uk_versions_script_hash unique (script_id, content_hash), constraint uk_versions_script_no unique (script_id, version_no) ) comment '不可变稳定版本;调度节点必须引用 versions_id'; create index fk_versions_source_object on model_platform.versions (source_object_id); create index idx_versions_creator on model_platform.versions (created_by, created_at); create index idx_versions_workspace_created on model_platform.versions (workspace_id, created_at); create table model_platform.workspace_members ( workspace_id char(26) not null, user_id char(26) not null, role_id char(26) not null, member_status varchar(16) default 'active' not null, joined_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, primary key (workspace_id, user_id) ) comment 'Workspace 成员与角色'; create index idx_workspace_members_role on model_platform.workspace_members (role_id); create index idx_workspace_members_user on model_platform.workspace_members (user_id, member_status); create table model_platform.workspaces ( workspace_id char(26) not null primary key, workspace_code varchar(64) not null, workspace_name varchar(150) not null, active_root_uri varchar(1500) not null comment '活动工作区,建议 NFS/PVC/file URI', quota_bytes bigint default 0 not null comment '0 表示不限额', used_bytes bigint default 0 not null, status varchar(24) default 'active' not null comment 'creating/active/suspended/deleting/deleted', created_by char(26) not null, created_at datetime(3) default CURRENT_TIMESTAMP(3) not null, updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3), description varchar(1000) null, artifact_bucket varchar(128) null comment 'S3 bucket', artifact_prefix varchar(512) null comment 'S3 object key prefix', is_deleted tinyint(1) default 0 not null, deleted_at datetime(3) null, constraint uk_workspaces_code unique (workspace_code) ) comment 'Workspace'; create index fk_workspaces_created_by on model_platform.workspaces (created_by); create index idx_workspaces_status on model_platform.workspaces (status);