文档修改
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
# Fonrey — Public Schema 数据模型
|
||||
|
||||
> **作者**: Backend Architect
|
||||
> **版本**: v1.0
|
||||
> **日期**: 2026-04-24
|
||||
> **版本**: v1.2
|
||||
> **日期**: 2026-04-26
|
||||
> **权威源**: 本文件是 `public` schema 所有表的唯一权威定义
|
||||
> **设计依据**: 系统管理模块 PRD(`PRD/系统管理/系统管理模块PRD.md`);客户端发布管理模块 PRD(`PRD/发布管理/客户端发布管理模块PRD.md`)
|
||||
> **索引文档**: [`DATA_MODEL.md §三`](./DATA_MODEL.md)(仅保留摘要索引,开发以本文件为准)
|
||||
@@ -20,7 +20,7 @@
|
||||
PostgreSQL Instance
|
||||
│
|
||||
├── public schema(平台运营层)← 本文件覆盖
|
||||
│ ├── tenants 租户注册与生命周期
|
||||
│ ├── tenants 租户注册与生命周期(含 feature_flags JSONB)
|
||||
│ ├── domains 域名路由
|
||||
│ ├── tenant_status_logs 状态变更审计
|
||||
│ ├── platform_admins 管理员账号
|
||||
@@ -32,8 +32,10 @@ PostgreSQL Instance
|
||||
│ ├── backup_records 备份记录
|
||||
│ ├── export_tasks 数据导出
|
||||
│ ├── system_versions 版本历史
|
||||
│ ├── upgrade_events 升级记录
|
||||
│ └── client_releases 客户端版本发布
|
||||
│ ├── upgrade_events 升级事件(A/B/C 分级 + B 类分批编排)
|
||||
│ ├── client_releases 客户端版本发布
|
||||
│ ├── feature_flag_definitions Feature Flag 定义(C 类灰度控制平面)
|
||||
│ └── feature_flag_change_log Feature Flag 变更历史(append-only)
|
||||
│
|
||||
├── tenant_abc schema(租户业务层,见各子文档)
|
||||
└── tenant_xyz schema
|
||||
@@ -55,8 +57,11 @@ PostgreSQL Instance
|
||||
| `public.backup_records` | 备份任务执行记录(自动/手动/升级前/恢复前) | §2.4 |
|
||||
| `public.export_tasks` | 数据导出异步任务(CSV/JSON/SQL Dump) | §2.4 |
|
||||
| `public.system_versions` | 平台版本历史,唯一 current 约束 | §2.5 |
|
||||
| `public.upgrade_events` | 升级/回滚事件,含灰度租户维度进度快照 | §2.5 |
|
||||
| `public.upgrade_events` | 升级/回滚事件,A/B/C 升级类型分级,B 类按租户分批编排 + 健康门控 | §2.5 |
|
||||
| `public.client_releases` | Windows 客户端发布版本,含安装包 URL、SHA256、强制更新标记 | §2.6 |
|
||||
| `public.feature_flag_definitions` | Feature Flag 全局定义(C 类运行时灰度控制平面) | §2.7 |
|
||||
| `public.tenants.feature_flags` | 租户级 Flag 显式覆盖(`tenants` 表新增 JSONB 列) | §2.7 |
|
||||
| `public.feature_flag_change_log` | Feature Flag 变更历史(append-only) | §2.7 |
|
||||
|
||||
---
|
||||
|
||||
@@ -106,6 +111,11 @@ CREATE TABLE public.tenants (
|
||||
-- 灰度升级
|
||||
is_canary BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE = 内测租户,参与灰度升级
|
||||
|
||||
-- Feature Flag 租户级覆盖(详见 §2.7)
|
||||
-- 格式: {"flag_key": true|false, ...}
|
||||
-- 业务代码只读;写入由 apps.admin_console 经 feature_flag_change_log 审计
|
||||
feature_flags JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
|
||||
-- 元数据
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
@@ -119,6 +129,9 @@ CREATE INDEX idx_tenants_suspended_until ON public.tenants(suspended_until)
|
||||
CREATE INDEX idx_tenants_canary ON public.tenants(is_canary) WHERE is_canary = TRUE;
|
||||
CREATE INDEX idx_tenants_pending_delete ON public.tenants(deleted_at)
|
||||
WHERE status = 'pending_delete';
|
||||
-- Feature Flag 租户级覆盖的 GIN 索引(详见 §2.7)
|
||||
-- 同时在 §2.7 中以 ALTER TABLE ADD COLUMN IF NOT EXISTS 兜底,便于按模块独立部署
|
||||
CREATE INDEX idx_tenants_feature_flags_gin ON public.tenants USING gin (feature_flags);
|
||||
|
||||
-- 域名映射表(支持多域名绑定一个租户,子域名创建后不可修改)
|
||||
CREATE TABLE public.domains (
|
||||
@@ -351,32 +364,89 @@ CREATE UNIQUE INDEX idx_system_versions_current ON public.system_versions(status
|
||||
WHERE status = 'current'; -- 全局只允许一个 current 版本
|
||||
|
||||
-- 升级事件(每次执行升级或回滚对应一条记录)
|
||||
-- 设计依据: 系统管理技术文档 §8.5–§8.6(A/B/C 升级类型分级 + B 类分批编排)
|
||||
CREATE TABLE public.upgrade_events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
from_version_id UUID REFERENCES public.system_versions(id) ON DELETE SET NULL,
|
||||
to_version_id UUID NOT NULL REFERENCES public.system_versions(id) ON DELETE RESTRICT,
|
||||
event_type VARCHAR(10) NOT NULL
|
||||
CHECK (event_type IN ('upgrade','rollback')),
|
||||
|
||||
-- 升级类型(决定本表大部分字段是否生效;详见技术文档 §8.5)
|
||||
-- A_app = 应用代码升级(蓝绿全量切换,灰度名单/批次字段无效)
|
||||
-- B_schema = 租户 Schema 迁移(按租户分批,批次字段全部生效)
|
||||
-- C_feature = Feature Flag 灰度(不在本表编排,详见 §2.7;本字段保留以便统一记录)
|
||||
upgrade_type VARCHAR(16) NOT NULL DEFAULT 'B_schema'
|
||||
CHECK (upgrade_type IN ('A_app','B_schema','C_feature')),
|
||||
|
||||
strategy VARCHAR(10) NOT NULL DEFAULT 'full'
|
||||
CHECK (strategy IN ('full','canary')), -- full = 全量,canary = 灰度
|
||||
status VARCHAR(15) NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending','health_check','in_progress','success','failed','rolled_back')),
|
||||
|
||||
-- 升级进度:每个租户的状态存为 JSONB 数组
|
||||
-- [{tenant_id, tenant_name, status, started_at, completed_at, error}]
|
||||
-- 升级编排状态机(与技术文档 §8.6.1 一致)
|
||||
-- draft → pre_check → pre_backup → batch_running ⇄ batch_done → succeeded
|
||||
-- ↓ 任一批失败/门控不通过
|
||||
-- halted → rollback_running → rolled_back
|
||||
-- ↓ 整体失败
|
||||
-- failed
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'draft'
|
||||
CHECK (status IN (
|
||||
'draft','pre_check','pre_backup','batch_running','batch_done',
|
||||
'halted','succeeded','failed','rollback_running','rolled_back'
|
||||
)),
|
||||
halted_reason TEXT, -- halted 状态时记录失败指标快照(健康门控不通过原因)
|
||||
|
||||
-- 灰度名单(B_schema 类型生效;A_app 类型必须为空数组)
|
||||
-- [tenant_id, ...]
|
||||
gray_tenant_ids JSONB NOT NULL DEFAULT '[]',
|
||||
|
||||
-- 批次编排参数(B_schema 类型生效)
|
||||
batch_size INTEGER NOT NULL DEFAULT 5
|
||||
CHECK (batch_size BETWEEN 1 AND 100), -- 每批包含的租户数
|
||||
batch_concurrency INTEGER NOT NULL DEFAULT 2
|
||||
CHECK (batch_concurrency BETWEEN 1 AND 20), -- 批内并发执行的租户数
|
||||
batch_interval_seconds INTEGER NOT NULL DEFAULT 300
|
||||
CHECK (batch_interval_seconds BETWEEN 0 AND 86400), -- 批间观察窗口(秒)
|
||||
failure_policy VARCHAR(16) NOT NULL DEFAULT 'halt_batch'
|
||||
CHECK (failure_policy IN ('halt_batch','continue')),
|
||||
-- halt_batch = 任一租户失败立即中断当前批,进入 halted 等待人工
|
||||
-- continue = 其他租户继续,仅标记失败(适用低风险变更)
|
||||
current_batch_no INTEGER NOT NULL DEFAULT 0, -- 已完成批次序号
|
||||
total_batch_count INTEGER, -- 总批次数 = ceil(len(gray_tenant_ids)/batch_size)
|
||||
|
||||
-- 健康门控阈值(覆盖默认值;默认值见技术文档 §8.6.5)
|
||||
-- {"error_rate_5xx_5m": 0.005, "p95_latency_5m": 2000,
|
||||
-- "celery_queue_pending": 1000, "sentry_new_issues_5m": 5}
|
||||
health_gate_config JSONB NOT NULL DEFAULT '{}',
|
||||
|
||||
-- 升级前全局备份引用(B_schema 必须;恢复兜底用)
|
||||
pre_backup_record_id UUID REFERENCES public.backup_records(id) ON DELETE SET NULL,
|
||||
|
||||
-- 单租户进度快照
|
||||
-- 数组格式(保留向后兼容):
|
||||
-- [{tenant_id, tenant_name, status, started_at, completed_at,
|
||||
-- snapshot_id, batch_no, error}]
|
||||
-- status 取值:pending | running | success | failed | rolled_back
|
||||
tenant_progress JSONB NOT NULL DEFAULT '[]',
|
||||
|
||||
-- 回滚触发条件
|
||||
-- 回滚相关
|
||||
rollback_reason TEXT,
|
||||
incident_report TEXT, -- 回滚后生成的事件报告
|
||||
incident_report TEXT, -- 回滚后生成的事件报告(halted 转 rolled_back 时写)
|
||||
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
initiated_by UUID REFERENCES public.platform_admins(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
-- 数据完整性约束:A_app 类型不允许带灰度名单(蓝绿全量切换)
|
||||
CONSTRAINT chk_app_upgrade_no_gray
|
||||
CHECK (upgrade_type <> 'A_app' OR gray_tenant_ids = '[]'::jsonb)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_upgrade_events_status ON public.upgrade_events(status, created_at DESC);
|
||||
CREATE INDEX idx_upgrade_events_type ON public.upgrade_events(upgrade_type, created_at DESC);
|
||||
-- 用于「halted 状态需要超管处理」的实时告警查询
|
||||
CREATE INDEX idx_upgrade_events_halted ON public.upgrade_events(created_at DESC)
|
||||
WHERE status = 'halted';
|
||||
```
|
||||
|
||||
### 2.6 客户端发布管理
|
||||
@@ -460,6 +530,92 @@ CREATE INDEX idx_client_releases_status ON public.client_releases(status, create
|
||||
CREATE INDEX idx_client_releases_version ON public.client_releases(version);
|
||||
```
|
||||
|
||||
### 2.7 Feature Flag 灰度体系
|
||||
|
||||
```sql
|
||||
-- ────────────────────────────────────────────────────────────
|
||||
-- 7. Feature Flag 灰度体系
|
||||
-- ────────────────────────────────────────────────────────────
|
||||
-- 设计依据: 系统管理技术文档 §8.7(C 类升级 / 运行时功能灰度)
|
||||
-- 说明: 与 §2.5 upgrade_events 的 B 类(schema 迁移)配合使用,
|
||||
-- 负责「行为切换」的运行时灰度。详见技术文档 §8.7.6 四步发布流程。
|
||||
|
||||
-- 全局 Flag 注册表(控制平面)
|
||||
CREATE TABLE public.feature_flag_definitions (
|
||||
key VARCHAR(64) PRIMARY KEY,
|
||||
-- 命名规范:snake_case,业务前缀 + 功能名 + 版本号
|
||||
-- 例:'property_ai_description_v2' / 'search_ranking_algo_2026q2'
|
||||
description TEXT NOT NULL, -- 业务说明(必填,便于审计回溯)
|
||||
default_value BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
-- 未在 tenants.feature_flags 显式覆盖、且不命中 rollout_strategy 时返回此值
|
||||
|
||||
-- 灰度策略
|
||||
rollout_strategy VARCHAR(16) NOT NULL DEFAULT 'tenant'
|
||||
CHECK (rollout_strategy IN ('tenant','percentage','user')),
|
||||
-- tenant = 仅按 tenants.feature_flags 显式开关,不做百分比
|
||||
-- percentage = 按租户 ID 稳定哈希进百分比桶(rollout_config.percentage)
|
||||
-- user = 按用户 ID 稳定哈希(rollout_config.percentage),需调用方传 user
|
||||
rollout_config JSONB NOT NULL DEFAULT '{}',
|
||||
-- percentage / user 策略下:{"percentage": 30}
|
||||
-- tenant 策略下:通常为空 {}
|
||||
|
||||
owner_admin_id UUID REFERENCES public.platform_admins(id) ON DELETE SET NULL,
|
||||
-- 责任人(用于到期清理提醒、问题归因)
|
||||
|
||||
-- 生命周期
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
archived_at TIMESTAMPTZ,
|
||||
-- 归档后所有查询永久返回 FALSE;不删除以保留审计链路
|
||||
archived_reason TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ff_def_active ON public.feature_flag_definitions(rollout_strategy)
|
||||
WHERE archived_at IS NULL;
|
||||
CREATE INDEX idx_ff_def_owner ON public.feature_flag_definitions(owner_admin_id)
|
||||
WHERE archived_at IS NULL;
|
||||
|
||||
-- 租户级 Flag 覆盖(存于 tenants 表的 JSONB 列)
|
||||
-- 设计上不单建表,避免每次 is_enabled() 多查一次 JOIN;
|
||||
-- public.tenants.feature_flags 列与 idx_tenants_feature_flags_gin 索引已在 §2.1 声明,
|
||||
-- 此处用 IF NOT EXISTS 兜底,便于本节单独执行(如分阶段迁移):
|
||||
ALTER TABLE public.tenants
|
||||
ADD COLUMN IF NOT EXISTS feature_flags JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
-- 格式:{"flag_key": true|false, ...}
|
||||
-- 仅 platform_admin 通过本模块写入;业务代码只读
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tenants_feature_flags_gin
|
||||
ON public.tenants USING gin (feature_flags);
|
||||
|
||||
-- Flag 变更历史(append-only,与 platform_audit_logs 同等约束)
|
||||
CREATE TABLE public.feature_flag_change_log (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
flag_key VARCHAR(64) NOT NULL,
|
||||
-- 不加外键引用 feature_flag_definitions(key):归档/重命名时不应连带删除审计
|
||||
tenant_id UUID REFERENCES public.tenants(id) ON DELETE SET NULL,
|
||||
-- NULL 表示全局变更(如调整 rollout_strategy / percentage / archive)
|
||||
-- 非 NULL 表示该租户的覆盖值变更
|
||||
change_scope VARCHAR(20) NOT NULL
|
||||
CHECK (change_scope IN (
|
||||
'definition_create','definition_update','definition_archive',
|
||||
'tenant_override_set','tenant_override_clear'
|
||||
)),
|
||||
old_value JSONB, -- 变更前的完整值(NULL 表示首次创建)
|
||||
new_value JSONB NOT NULL, -- 变更后的完整值
|
||||
operator_id UUID NOT NULL REFERENCES public.platform_admins(id) ON DELETE RESTRICT,
|
||||
-- 强制保留操作人;账号停用不可级联删除审计
|
||||
operator_name VARCHAR(100) NOT NULL, -- 快照
|
||||
reason TEXT NOT NULL, -- 强制填写变更原因(业务流程要求)
|
||||
ip_address INET,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
-- 无 deleted_at,无 UPDATE,append-only
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ff_log_flag ON public.feature_flag_change_log(flag_key, created_at DESC);
|
||||
CREATE INDEX idx_ff_log_tenant ON public.feature_flag_change_log(tenant_id, created_at DESC)
|
||||
WHERE tenant_id IS NOT NULL;
|
||||
CREATE INDEX idx_ff_log_operator ON public.feature_flag_change_log(operator_id, created_at DESC);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、关键约束与禁止操作
|
||||
@@ -478,6 +634,11 @@ CREATE INDEX idx_client_releases_version ON public.client_releases(version);
|
||||
| `client_releases` 唯一 published | `idx_client_releases_published` 部分唯一索引保证同平台+架构下只有一条 `status='published'` |
|
||||
| `client_releases` 不可跨租户隔离 | 本表属于 public schema,所有租户共享;禁止在租户 schema 中创建副本 |
|
||||
| `client_releases.download_count` 原子递增 | 必须使用 `UPDATE ... SET download_count = download_count + 1`,禁止先读后写 |
|
||||
| `upgrade_events.gray_tenant_ids` 与 `upgrade_type` 一致性 | A_app 类型必须为空数组(CHECK 约束 `chk_app_upgrade_no_gray` 强制);只有 B_schema 类型才使用灰度名单与批次字段 |
|
||||
| `upgrade_events` 状态流转单向 | 状态机详见 §4.2;`succeeded` / `rolled_back` / `failed` 为终态,禁止再写回中间态 |
|
||||
| `feature_flag_change_log` append-only | 禁止 UPDATE / DELETE;任何 Flag 变更都必须经此表追溯,含 `reason` 强制非空 |
|
||||
| `feature_flag_definitions.key` 不可修改 | 创建后禁止 UPDATE 主键;废弃 Flag 走 `archived_at` 软归档 |
|
||||
| `tenants.feature_flags` 写入路径强约束 | 仅允许 `apps.admin_console.services.feature_flags` 写入;业务代码只读,且必须经 `is_enabled()` 服务接口(不得直读 JSONB) |
|
||||
|
||||
---
|
||||
|
||||
@@ -501,10 +662,50 @@ creating ──(初始化失败)──► failed
|
||||
### 4.2 升级事件状态
|
||||
|
||||
```
|
||||
pending → health_check → in_progress → success
|
||||
└─► failed → rolled_back
|
||||
draft ──提交──► pre_check ──健康检查通过──► pre_backup ──全局备份完成──► batch_running
|
||||
│
|
||||
┌───── 当前批全部租户成功 ───────┘
|
||||
▼
|
||||
batch_done
|
||||
│
|
||||
是否还有下一批 ◄┤
|
||||
↓ 否 │ 是
|
||||
succeeded 下一批 → batch_running
|
||||
│
|
||||
│ 任一批失败 / 健康门控不通过
|
||||
▼
|
||||
halted
|
||||
│
|
||||
超管选择 ◄────┤
|
||||
↓ 回滚 │ 继续下一批
|
||||
rollback_running batch_running
|
||||
↓
|
||||
rolled_back
|
||||
```
|
||||
|
||||
**字段映射**(详见技术文档 §8.6):
|
||||
- `upgrade_type ∈ {A_app, B_schema, C_feature}`:A_app 类型不参与本状态机(蓝绿全量切换由运维侧执行),仅记录元数据
|
||||
- `current_batch_no` / `total_batch_count`:批次进度,UI §4.6 据此渲染进度表
|
||||
- `halted_reason`:halted 状态时记录失败指标快照(健康门控不通过原因)
|
||||
- `tenant_progress[].status ∈ {pending, running, success, failed, rolled_back}`:单租户细粒度状态
|
||||
- 终态 `succeeded` / `rolled_back` / `failed` 一旦写入禁止再变更(应用层 + 审计日志双重保证)
|
||||
|
||||
### 4.3 Feature Flag 变更流程
|
||||
|
||||
```
|
||||
[admin 创建 Flag definition] ──► reason=必填 ──► 写 feature_flag_change_log(scope=definition_create)
|
||||
│
|
||||
├─► 调整 rollout_strategy / percentage ──► scope=definition_update
|
||||
│
|
||||
├─► 租户级覆盖开/关 ──► scope=tenant_override_set / tenant_override_clear
|
||||
│ 同时 UPDATE tenants.feature_flags
|
||||
│
|
||||
└─► 归档 ──► archived_at = NOW(), scope=definition_archive
|
||||
归档后 is_enabled() 永久返回 FALSE,但记录保留
|
||||
```
|
||||
|
||||
**强制约束**:所有变更必须由 `apps.admin_console` 服务层写入;任何写操作都必须同时落 `feature_flag_change_log`(含 `reason`)+ `platform_audit_logs`(双重审计)。
|
||||
|
||||
---
|
||||
|
||||
## 五、查询模式
|
||||
@@ -576,6 +777,69 @@ SELECT version, download_count
|
||||
FROM public.client_releases
|
||||
WHERE status IN ('published', 'archived')
|
||||
ORDER BY published_at DESC;
|
||||
|
||||
-- ============================================================
|
||||
-- 升级编排相关查询(B 类 Schema 迁移分批升级)
|
||||
-- ============================================================
|
||||
|
||||
-- 查询当前处于 halted 状态、需要超管处理的升级事件(实时告警查询)
|
||||
SELECT id, to_version_id, current_batch_no, total_batch_count,
|
||||
halted_reason, started_at, initiated_by
|
||||
FROM public.upgrade_events
|
||||
WHERE status = 'halted'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 查询某租户的升级历史(含每次升级的最终状态)
|
||||
SELECT ue.id, ue.to_version_id, ue.upgrade_type, ue.status,
|
||||
progress->>'status' AS tenant_status,
|
||||
progress->>'completed_at' AS tenant_completed_at,
|
||||
progress->>'error' AS tenant_error
|
||||
FROM public.upgrade_events ue,
|
||||
jsonb_array_elements(ue.tenant_progress) AS progress
|
||||
WHERE progress->>'tenant_id' = $1::text
|
||||
ORDER BY ue.created_at DESC;
|
||||
|
||||
-- 查询某次升级事件中失败的租户列表(用于人工排查)
|
||||
SELECT progress->>'tenant_id' AS tenant_id,
|
||||
progress->>'tenant_name' AS tenant_name,
|
||||
progress->>'error' AS error,
|
||||
progress->>'snapshot_id' AS snapshot_id
|
||||
FROM public.upgrade_events ue,
|
||||
jsonb_array_elements(ue.tenant_progress) AS progress
|
||||
WHERE ue.id = $1
|
||||
AND progress->>'status' = 'failed';
|
||||
|
||||
-- ============================================================
|
||||
-- Feature Flag 相关查询(C 类运行时灰度)
|
||||
-- ============================================================
|
||||
|
||||
-- 查询所有未归档的 Flag 定义(管理后台列表)
|
||||
SELECT key, description, default_value, rollout_strategy, rollout_config,
|
||||
owner_admin_id, created_at
|
||||
FROM public.feature_flag_definitions
|
||||
WHERE archived_at IS NULL
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 查询某 Flag 当前已显式开启的租户列表(GIN 索引加速)
|
||||
SELECT id, name, schema_name, feature_flags->$1 AS flag_value
|
||||
FROM public.tenants
|
||||
WHERE feature_flags ? $1
|
||||
AND status = 'active';
|
||||
|
||||
-- 查询某 Flag 近 90 天的所有变更(审计回溯)
|
||||
SELECT change_scope, tenant_id, old_value, new_value,
|
||||
operator_name, reason, created_at
|
||||
FROM public.feature_flag_change_log
|
||||
WHERE flag_key = $1
|
||||
AND created_at >= NOW() - INTERVAL '90 days'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 查询某管理员近 30 天的 Flag 变更操作(个人操作审计)
|
||||
SELECT flag_key, change_scope, tenant_id, reason, created_at
|
||||
FROM public.feature_flag_change_log
|
||||
WHERE operator_id = $1
|
||||
AND created_at >= NOW() - INTERVAL '30 days'
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### 5.2 禁止查询
|
||||
@@ -588,6 +852,11 @@ ORDER BY published_at DESC;
|
||||
| `UPDATE public.domains SET domain = ...` | 域名路由不可变 |
|
||||
| `UPDATE public.client_releases SET version = ...` | 版本号创建后不可修改,变更须新建记录 |
|
||||
| 在租户 schema 中创建 `client_releases` 副本 | 本表属于 public schema,多租户共享,禁止下沉到租户层 |
|
||||
| `UPDATE public.feature_flag_change_log` / `DELETE FROM ...` | append-only 审计表 |
|
||||
| `UPDATE public.feature_flag_definitions SET key = ...` | Flag key 是主键且为业务标识,禁止修改;废弃用 `archived_at` |
|
||||
| 在租户 schema 内重复定义 `feature_flag_definitions` | Flag 体系是平台级控制平面,必须存于 public schema |
|
||||
| 业务代码直接读 `tenants.feature_flags` JSONB | 必须经 `apps.admin_console.services.feature_flags.is_enabled()` 服务接口,绕过策略层会导致灰度策略失效 |
|
||||
| `UPDATE public.upgrade_events` 修改终态行 | `succeeded` / `rolled_back` / `failed` 状态的事件禁止再次修改,应用层 ORM Manager 强制保护 |
|
||||
|
||||
---
|
||||
|
||||
@@ -597,3 +866,4 @@ ORDER BY published_at DESC;
|
||||
|------|------|------|
|
||||
| v1.0 | 2026-04-24 | 从 `DATA_MODEL.md §三` 独立拆分;内容等价于 v1.2 DATA_MODEL.md §三 |
|
||||
| v1.1 | 2026-04-24 | 新增 §2.6 `client_releases` 表(客户端发布管理);同步更新表清单、约束规则、查询模式 |
|
||||
| v1.2 | 2026-04-26 | 配合系统管理技术文档 v1.2 升级分批专节:§2.5 `upgrade_events` 增加 `upgrade_type`、`gray_tenant_ids`、`batch_size`、`batch_concurrency`、`batch_interval_seconds`、`failure_policy`、`current_batch_no`、`total_batch_count`、`health_gate_config`、`pre_backup_record_id`、`halted_reason` 字段,状态机扩展为 10 态;新增 §2.7 Feature Flag 体系(`feature_flag_definitions` / `tenants.feature_flags` JSONB / `feature_flag_change_log`);同步更新表清单、§4.2 升级状态机、§4.3 Flag 流程、§5.1 查询模式、§5.2 禁止操作 |
|
||||
|
||||
Reference in New Issue
Block a user