# 数据库 Schema

## projects 表（项目主表）

```sql
CREATE TABLE projects (
    id              BIGSERIAL PRIMARY KEY,
    project_id      VARCHAR(64) UNIQUE NOT NULL,
    name            VARCHAR(128) NOT NULL,
    namespace       VARCHAR(64) UNIQUE NOT NULL,

    -- 生命周期状态: INIT/DRAFTING/REVIEWING/RELEASED/MODIFYING/ARCHIVED
    lifecycle_status    VARCHAR(32) DEFAULT 'INIT',
    -- 认证状态: draft/pending/official
    certification_status VARCHAR(32) DEFAULT 'draft',

    -- 当前正式版本号
    current_version     INT DEFAULT 0,

    -- JSONB 存储
    basic_info          JSONB,
    deploy_business     JSONB,
    deploy_env          JSONB,
    deploy_middleware   JSONB,

    -- 填写人
    detail_filler_id    BIGINT,
    detail_filler_name  VARCHAR(64),

    -- 审计字段
    created_by          BIGINT,
    created_by_name     VARCHAR(64),
    created_at          TIMESTAMPTZ DEFAULT NOW(),
    updated_at          TIMESTAMPTZ DEFAULT NOW(),
    deleted_at          TIMESTAMPTZ
);

CREATE INDEX idx_projects_namespace ON projects(namespace);
CREATE INDEX idx_projects_lifecycle ON projects(lifecycle_status);
CREATE INDEX idx_projects_deleted ON projects(deleted_at);
```

## project_versions 表（版本历史）

```sql
CREATE TABLE project_versions (
    id              BIGSERIAL PRIMARY KEY,
    project_id      VARCHAR(64) NOT NULL,

    -- 版本号 (正式版本递增, 草稿为0)
    version         INT NOT NULL DEFAULT 0,
    -- 版本类型: official/fill_draft/modify_draft
    version_type    VARCHAR(32) NOT NULL,

    -- 基准版本号（草稿基于哪个正式版本创建）
    base_version    INT DEFAULT 0,

    -- 草稿所属用户
    user_id         BIGINT,
    user_name       VARCHAR(64),

    -- 关联工单
    workflow_id     VARCHAR(64),

    -- 完整快照
    snapshot_data   JSONB,

    -- 变更信息
    commit_message  VARCHAR(255),
    committer_id    BIGINT,
    committer_name  VARCHAR(64),

    created_at      TIMESTAMPTZ DEFAULT NOW(),
    updated_at      TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_versions_project ON project_versions(project_id);
CREATE INDEX idx_versions_workflow ON project_versions(workflow_id);
CREATE INDEX idx_versions_user ON project_versions(user_id);
CREATE UNIQUE INDEX idx_versions_project_version ON project_versions(project_id, version) WHERE version > 0;
```

## project_workflows 表（项目工单关联）

```sql
CREATE TABLE project_workflows (
    id              BIGSERIAL PRIMARY KEY,
    project_id      VARCHAR(64) NOT NULL,
    workflow_id     VARCHAR(64) UNIQUE NOT NULL,

    -- 工单类型: fill(填写)/modify(修改)
    workflow_type   VARCHAR(32) NOT NULL,

    -- 工单状态 (冗余存储，便于查询)
    status          VARCHAR(32),

    created_at      TIMESTAMPTZ DEFAULT NOW(),
    updated_at      TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_pw_project ON project_workflows(project_id);
CREATE INDEX idx_pw_status ON project_workflows(status);
```

## project_auth_configs 表（授权配置）

```sql
CREATE TABLE project_auth_configs (
    id              BIGSERIAL PRIMARY KEY,
    project_id      VARCHAR(64) UNIQUE NOT NULL,

    tier_one_secret VARCHAR(128),    -- 一级TOTP密钥 (加密存储)
    time_offset     INT DEFAULT 30,  -- 允许时间偏移(秒)
    totp_enabled    BOOLEAN DEFAULT FALSE,

    tier_two_secret VARCHAR(128),    -- 二级TOTP密钥 (来自Watchdog)

    auth_type       VARCHAR(32),     -- permanent/time_limited
    auth_days       INT,             -- 授权有效期(天)
    authorized_at   TIMESTAMPTZ,
    revoked_at      TIMESTAMPTZ,
    is_offline      BOOLEAN DEFAULT FALSE,

    created_at      TIMESTAMPTZ DEFAULT NOW(),
    updated_at      TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_auth_project ON project_auth_configs(project_id);
```

## JSONB 结构定义

### basic_info

```json
{
  "province": "北京市",
  "city": "北京市",
  "industry_contact": "张三",
  "industry_phone": "13800138000",
  "project_nature": "market"
}
```

### deploy_business

```json
{
  "deployer_name": "李四",
  "deployer_phone": "13900139000",
  "deploy_start_time": "2026-01-01",
  "deploy_end_time": "2026-01-15",
  "system_version": "v2.0.0",
  "system_type": "fly-control",
  "main_entrance": "https://example.com",
  "admin_username": "admin",
  "admin_password": "<encrypted>"
}
```

### deploy_env

```json
{
  "hosts": [
    {
      "hostname": "master-01",
      "internal_ip": "192.168.1.10",
      "public_ip": "",
      "can_access_public": false,
      "ssh_port": 22,
      "ssh_user": "root",
      "ssh_pwd": "<encrypted>",
      "role": "master"
    }
  ],
  "network_type": "internal",
  "main_public_ip": "",
  "domain_url": "",
  "ssl_enabled": false,
  "management_type": "bastion",
  "management_url": "",
  "management_user": "",
  "management_pwd": "<encrypted>",
  "host_count": 3,
  "total_cpu": 24,
  "cpu_model": "Intel Xeon",
  "total_memory": 64,
  "total_storage": 1000
}
```

### deploy_middleware

```json
{
  "mysql": {
    "public_ip": "",
    "public_port": 0,
    "internal_ip": "192.168.1.10",
    "internal_port": 3306,
    "k8s_address": "mysql-svc",
    "k8s_port": 3306,
    "admin_user": "root",
    "admin_pwd": "<encrypted>",
    "version": "8.0"
  },
  "redis": { ... },
  "emqx": { ... },
  "minio": { ... },
  "influxdb": { ... },
  "nacos": { ... },
  "k8s_dashboard": { ... }
}
```

## 敏感字段加密说明

以下字段必须使用 AES-256 加密存储：

| 表 | 字段路径 | 说明 |
|:---|:---|:---|
| projects | `deploy_business.admin_password` | 系统超管密码 |
| projects | `deploy_env.hosts[*].ssh_pwd` | SSH密码 |
| projects | `deploy_env.management_pwd` | 管理后台密码 |
| projects | `deploy_middleware.*.admin_pwd` | 中间件超管密码 |
| project_auth_configs | `tier_one_secret` | 一级TOTP密钥 |
| project_auth_configs | `tier_two_secret` | 二级TOTP密钥 |

## 索引优化建议

```sql
-- 常用查询优化
CREATE INDEX idx_projects_lifecycle_cert ON projects(lifecycle_status, certification_status);
CREATE INDEX idx_projects_province ON projects((basic_info->>'province'));

-- JSONB GIN 索引（按需添加）
CREATE INDEX idx_projects_basic_gin ON projects USING GIN (basic_info);
```
