dcdc8d1ddd
全栈知识治理平台首次入库(P1-P10 + 发布链路模拟验证闭环): - 治理核心:源目录/变更集/人工审核/发布批次/发布执行(fail-closed 闸口) - 测试通道:WeKnora 测试 KB 上传/轮询/验收;poll 完成时写入 parser_generation/index_generation,修复 manual/seed 路径发布闸口永久拦截 - 发布适配器 v071(本地 source=测试角色 / 云端 target=生产角色 模拟验证通过): * ES 导出/导入 mapping 自适应(.keyword 子字段、可选 tenant_id) * OSS locator 支持嵌套 scheme;chunks.seq_id 由目标序列分配 * bundle 归档同身份重试原子替换;verifier 按 bundle chunk_type 计数 * 回滚 job payload 支持 prior_execution_id(strict 解码) - 三通道发布+回滚演练实测:publish 4/4 verified,检索命中, rollback 4/4 rolled_back,目标端 PG is_enabled=false、ES is_enabled=false - 前端 A·Data-console 风格全站统一,120 用例通过 - 门禁:go vet / go test 全包通过,gofmt 干净
115 lines
5.2 KiB
SQL
115 lines
5.2 KiB
SQL
CREATE TABLE IF NOT EXISTS source_connections (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
source_type VARCHAR(20) NOT NULL
|
|
CHECK (source_type IN ('pp', 'alist', 'dingtalk')),
|
|
name VARCHAR(255) NOT NULL,
|
|
base_url TEXT NOT NULL DEFAULT '',
|
|
secret_ref VARCHAR(255) NOT NULL DEFAULT '',
|
|
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
|
schedule JSONB NOT NULL DEFAULT '{}'::jsonb
|
|
CHECK (jsonb_typeof(schedule) = 'object'),
|
|
last_health JSONB NOT NULL DEFAULT '{}'::jsonb
|
|
CHECK (jsonb_typeof(last_health) = 'object'),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (name)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS source_items (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
source_connection_id VARCHAR(36) NOT NULL
|
|
REFERENCES source_connections(id) ON DELETE RESTRICT,
|
|
stable_external_id TEXT NOT NULL,
|
|
canonical_uri_hash CHAR(64) NOT NULL
|
|
CHECK (canonical_uri_hash ~ '^[0-9a-f]{64}$'),
|
|
parent_external_id TEXT NOT NULL DEFAULT '',
|
|
normalized_path TEXT NOT NULL DEFAULT '',
|
|
title TEXT NOT NULL,
|
|
item_type VARCHAR(20) NOT NULL
|
|
CHECK (item_type IN ('document', 'file', 'link', 'video')),
|
|
size_bytes BIGINT CHECK (size_bytes IS NULL OR size_bytes >= 0),
|
|
mime TEXT NOT NULL DEFAULT '',
|
|
revision TEXT NOT NULL DEFAULT '',
|
|
updated_at_source TIMESTAMPTZ,
|
|
visibility VARCHAR(20) NOT NULL DEFAULT 'internal'
|
|
CHECK (visibility IN ('internal', 'external')),
|
|
visibility_origin VARCHAR(30) NOT NULL DEFAULT 'manual'
|
|
CHECK (visibility_origin IN ('pp_public_tag', 'configured_scope', 'manual')),
|
|
last_seen_scan_id VARCHAR(36) NOT NULL DEFAULT '',
|
|
source_change VARCHAR(20) NOT NULL DEFAULT 'unchanged'
|
|
CHECK (source_change IN ('unchanged', 'added', 'updated', 'deleted', 'unavailable')),
|
|
absence_streak INTEGER NOT NULL DEFAULT 0 CHECK (absence_streak >= 0),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (source_connection_id, stable_external_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS content_objects (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
sha256 CHAR(64) NOT NULL
|
|
CHECK (sha256 ~ '^[0-9a-f]{64}$'),
|
|
size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0),
|
|
mime TEXT NOT NULL DEFAULT '',
|
|
validated_format VARCHAR(50) NOT NULL DEFAULT '',
|
|
local_spool_ref TEXT NOT NULL DEFAULT '',
|
|
content_state VARCHAR(20) NOT NULL DEFAULT 'unknown'
|
|
CHECK (content_state IN ('unknown', 'downloading', 'verified', 'invalid', 'over_limit', 'failed')),
|
|
first_discovered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
last_discovered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (sha256)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS source_item_versions (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
source_item_id VARCHAR(36) NOT NULL
|
|
REFERENCES source_items(id) ON DELETE RESTRICT,
|
|
revision TEXT NOT NULL,
|
|
content_object_id VARCHAR(36)
|
|
REFERENCES content_objects(id) ON DELETE RESTRICT,
|
|
content_state VARCHAR(20) NOT NULL DEFAULT 'unknown'
|
|
CHECK (content_state IN ('unknown', 'downloading', 'verified', 'invalid', 'over_limit', 'failed')),
|
|
download_error TEXT NOT NULL DEFAULT '',
|
|
raw_record_summary JSONB NOT NULL DEFAULT '{}'::jsonb
|
|
CHECK (jsonb_typeof(raw_record_summary) = 'object'),
|
|
source_updated_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (source_item_id, revision)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS test_publications (
|
|
id VARCHAR(36) PRIMARY KEY,
|
|
source_item_version_id VARCHAR(36) NOT NULL
|
|
REFERENCES source_item_versions(id) ON DELETE RESTRICT,
|
|
test_kb_id VARCHAR(255) NOT NULL,
|
|
knowledge_id VARCHAR(255) NOT NULL DEFAULT '',
|
|
ingest_state VARCHAR(20) NOT NULL DEFAULT 'pending'
|
|
CHECK (ingest_state IN ('pending', 'uploading', 'uploaded', 'failed')),
|
|
processing_state VARCHAR(20) NOT NULL DEFAULT 'pending'
|
|
CHECK (processing_state IN ('pending', 'processing', 'finalizing', 'completed', 'failed', 'stalled')),
|
|
retrieval_state VARCHAR(20) NOT NULL DEFAULT 'unpublished'
|
|
CHECK (retrieval_state IN ('unpublished', 'enabled', 'disabling', 'disabled', 'enabling', 'failed')),
|
|
parser_generation VARCHAR(255) NOT NULL DEFAULT '',
|
|
index_generation VARCHAR(255) NOT NULL DEFAULT '',
|
|
last_error TEXT NOT NULL DEFAULT '',
|
|
retry_count INTEGER NOT NULL DEFAULT 0 CHECK (retry_count >= 0),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE (source_item_version_id, test_kb_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_source_items_change
|
|
ON source_items (source_connection_id, source_change, updated_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_source_items_visibility
|
|
ON source_items (visibility, updated_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_source_item_versions_content
|
|
ON source_item_versions (content_object_id)
|
|
WHERE content_object_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_test_publications_state
|
|
ON test_publications (processing_state, retrieval_state, updated_at DESC);
|