-- +goose Up -- 项目追踪与阶段回溯账本。留存类别为 record:随项目保留。 -- 条目修订与边决议只追加。源文档依法清除时把条目标成 tombstone,不级联删边和决议。 CREATE TABLE IF NOT EXISTS project_trace_items ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, business_key TEXT NOT NULL, kind TEXT NOT NULL, lifecycle_state TEXT NOT NULL DEFAULT 'active', review_state TEXT NOT NULL DEFAULT 'confirmed', tombstone BOOLEAN NOT NULL DEFAULT false, statement TEXT NOT NULL DEFAULT '', source_doc_id TEXT NOT NULL DEFAULT '', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (project_id, kind, business_key) ); CREATE TABLE IF NOT EXISTS project_trace_item_revisions ( id BIGSERIAL PRIMARY KEY, item_id BIGINT NOT NULL REFERENCES project_trace_items (id), revision_no INT NOT NULL, source_doc_id TEXT NOT NULL DEFAULT '', source_snapshot_id BIGINT NOT NULL DEFAULT 0, content_hash TEXT NOT NULL DEFAULT '', statement TEXT NOT NULL DEFAULT '', extractor_version TEXT NOT NULL DEFAULT '', tombstone BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (item_id, revision_no), UNIQUE (item_id, source_snapshot_id, content_hash, extractor_version) ); CREATE TABLE IF NOT EXISTS project_trace_edges ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, from_item_id BIGINT NOT NULL, to_item_id BIGINT NOT NULL, relation_type TEXT NOT NULL, provenance TEXT NOT NULL, review_state TEXT NOT NULL, evidence_doc_id TEXT NOT NULL DEFAULT '', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (project_id, from_item_id, to_item_id, relation_type, provenance) ); CREATE TABLE IF NOT EXISTS project_trace_edge_decisions ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, edge_id BIGINT NOT NULL, decision TEXT NOT NULL, reason TEXT NOT NULL DEFAULT '', decided_by BIGINT NOT NULL, decided_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS project_trace_index_state ( project_id BIGINT NOT NULL, doc_id TEXT NOT NULL, source_snapshot_id BIGINT NOT NULL DEFAULT 0, status TEXT NOT NULL, extractor_version TEXT NOT NULL, item_count INT NOT NULL DEFAULT 0, error TEXT NOT NULL DEFAULT '', indexed_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (project_id, doc_id, extractor_version) ); CREATE TABLE IF NOT EXISTS stage_reopen_requests ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, instance_id BIGINT NOT NULL, stage_key TEXT NOT NULL, doc_task_keys TEXT[] NOT NULL, reason TEXT NOT NULL, requested_by BIGINT NOT NULL, status TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS stage_recheck_marks ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, stage_key TEXT NOT NULL, source_doc_id TEXT NOT NULL, status TEXT NOT NULL, reason TEXT NOT NULL DEFAULT '', acked_by BIGINT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS stage_recheck_marks_one_open ON stage_recheck_marks (project_id, stage_key, source_doc_id) WHERE status = 'open'; CREATE TABLE IF NOT EXISTS trace_revision_proposals ( id BIGSERIAL PRIMARY KEY, project_id BIGINT NOT NULL, author_id BIGINT NOT NULL, body TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending_author', created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- +goose Down -- 这些表是合规业务记录,不是可丢弃缓存。 -- Down 不删除 project_trace_edge_decisions,也不删除条目、修订、边、索引水位、再打开申请和待复核标记。 SELECT 1;