Make the governed RAG evidence path executable end to end
Some checks failed
verify / verify (push) Has been cancelled

Separate local parsing from model indexing, bind review decisions to immutable manifests, persist vectors behind active profiles, and expose retrieval, chat, evaluation, and document workflows through the React workbench.

Constraint: Live Bailian authentication currently fails for all three configured capabilities

Rejected: Direct upload-to-embedding flow | bypasses local review and manifest binding

Confidence: high

Scope-risk: broad

Directive: Keep private-data deployment blocked until authentication, RBAC, and separate database roles land

Tested: make verify; fresh and replay Docker document smoke; worker recovery smoke; frozen synthetic evaluation; migration 0003-0004 roundtrip

Not-tested: Successful live Bailian calls, OCR, real multi-user authorization
This commit is contained in:
2026-07-13 05:58:11 +08:00
parent 75592af33a
commit ecdb10c37a
111 changed files with 25457 additions and 152 deletions

View File

@@ -0,0 +1,123 @@
"""Add optimistic document review decisions and immutable review audit.
Revision ID: 0004_document_review
Revises: 0003_document_ingestion
Create Date: 2026-07-13
"""
from collections.abc import Sequence
from alembic import op
revision: str = "0004_document_review"
down_revision: str | None = "0003_document_ingestion"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.execute(
"""
ALTER TABLE rag.document_versions
ADD COLUMN review_revision integer NOT NULL DEFAULT 0,
ADD CONSTRAINT document_versions_review_revision_valid
CHECK (review_revision >= 0);
"""
)
op.execute(
"""
CREATE TABLE rag.document_review_events (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
document_id uuid NOT NULL,
document_version_id uuid NOT NULL,
actor_subject text NOT NULL,
decision text NOT NULL,
reason_code text NOT NULL,
previous_revision integer NOT NULL,
resulting_revision integer NOT NULL,
outbound_manifest_sha256 char(64),
embedding_profile_hash char(64),
trace_id uuid NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT document_review_events_document_fk
FOREIGN KEY (document_id, document_version_id)
REFERENCES rag.document_versions (document_id, id)
ON DELETE CASCADE,
CONSTRAINT document_review_events_actor_nonempty
CHECK (btrim(actor_subject) <> '' AND length(actor_subject) <= 200),
CONSTRAINT document_review_events_decision_valid
CHECK (decision IN ('APPROVE', 'REJECT')),
CONSTRAINT document_review_events_reason_valid
CHECK (reason_code IN (
'SYNTHETIC_REVIEW_APPROVED',
'RIGHTS_NOT_VERIFIED',
'CONTENT_QUALITY_REJECTED',
'CLOUD_PROCESSING_REJECTED'
)),
CONSTRAINT document_review_events_revision_valid
CHECK (
previous_revision >= 0
AND resulting_revision = previous_revision + 1
),
CONSTRAINT document_review_events_hashes_valid
CHECK (
(
decision = 'APPROVE'
AND outbound_manifest_sha256 ~ '^[0-9a-f]{64}$'
AND embedding_profile_hash ~ '^[0-9a-f]{64}$'
)
OR (
decision = 'REJECT'
AND embedding_profile_hash IS NULL
)
),
CONSTRAINT document_review_events_version_revision_key
UNIQUE (document_version_id, resulting_revision)
);
"""
)
op.execute(
"""
CREATE INDEX document_review_events_document_timeline
ON rag.document_review_events (document_id, created_at, id);
"""
)
op.execute(
"""
CREATE FUNCTION rag.reject_document_review_event_mutation()
RETURNS trigger
LANGUAGE plpgsql
SECURITY INVOKER
SET search_path = pg_catalog, rag
AS $function$
BEGIN
RAISE EXCEPTION 'document review events are append-only'
USING ERRCODE = '23514';
END
$function$;
"""
)
op.execute(
"""
CREATE TRIGGER document_review_events_append_only
BEFORE UPDATE OR DELETE
ON rag.document_review_events
FOR EACH ROW
EXECUTE FUNCTION rag.reject_document_review_event_mutation();
"""
)
def downgrade() -> None:
op.execute(
"DROP TRIGGER IF EXISTS document_review_events_append_only ON rag.document_review_events;"
)
op.execute("DROP FUNCTION IF EXISTS rag.reject_document_review_event_mutation();")
op.execute("DROP TABLE IF EXISTS rag.document_review_events;")
op.execute(
"""
ALTER TABLE rag.document_versions
DROP CONSTRAINT IF EXISTS document_versions_review_revision_valid,
DROP COLUMN IF EXISTS review_revision;
"""
)