Isolate cloud model access before enabling product RAG workflows
Some checks failed
verify / verify (push) Has been cancelled

The API and ingestion tools now use a fixed internal model gateway while
governed profiles, embedding cache assignments, traceable citations, and
stable API errors establish the boundaries required by later workflows.

Constraint: The current Alibaba Cloud workspace rejects all three live model calls with authentication failures
Rejected: Give the API or seed tools the Bailian key and direct egress | combines database access, cloud credentials, and public network access
Rejected: Mix offline and Bailian vectors in one demo namespace | makes profile activation and retrieval ambiguous
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep Bailian credentials and egress exclusive to model-gateway and create a new immutable profile hash for any embedding identity change
Tested: make verify; 121 backend tests; 14 frontend tests; fresh and populated Alembic upgrade-downgrade-upgrade; two idempotent offline seeds; Docker health and HTTP retrieval; isolated provider smoke
Not-tested: Successful live Bailian responses because the supplied workspace credential currently fails authentication
This commit is contained in:
2026-07-13 04:09:06 +08:00
parent 99b7df64ea
commit 75592af33a
28 changed files with 3932 additions and 254 deletions

View File

@@ -0,0 +1,223 @@
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
MIGRATION_PATH = ROOT / "backend/migrations/versions/0002_model_profiles_and_invocations.py"
MIGRATION = MIGRATION_PATH.read_text(encoding="utf-8")
NORMALIZED = " ".join(MIGRATION.lower().split())
def _table_definition(name: str) -> str:
pattern = re.compile(rf"(?ms)create table rag\.{re.escape(name)} \((.*?)^ \);")
match = pattern.search(MIGRATION.lower())
assert match is not None, f"missing table definition: rag.{name}"
return " ".join(match.group(1).split())
def test_revision_is_additive_after_initial_schema() -> None:
assert 'revision: str = "0002_model_profiles"' in MIGRATION
assert 'down_revision: str | none = "0001_initial_schema"' in MIGRATION.lower()
revision_match = re.search(r'^revision: str = "([^"]+)"$', MIGRATION, re.MULTILINE)
assert revision_match is not None
assert len(revision_match.group(1)) <= 32
assert "alter table rag.chunks" in NORMALIZED
assert "alter table rag.knowledge_bases" in NORMALIZED
assert "drop table if exists rag.chunks" not in NORMALIZED
assert "drop table if exists rag.knowledge_bases" not in NORMALIZED
def test_model_profiles_have_governed_identity_and_dimension_contract() -> None:
table = _table_definition("model_profiles")
for column in (
"profile_hash char(64) primary key",
"alias text not null",
"kind text not null",
"provider text not null",
"model text not null",
"api_mode text not null",
"dimension smallint",
"endpoint_identity_hash char(64) not null",
"config_snapshot jsonb not null default '{}'::jsonb",
"synthetic boolean not null default false",
"enabled boolean not null default true",
"created_at timestamptz not null default now()",
"updated_at timestamptz not null default now()",
):
assert column in table
assert "model_profiles_alias_key unique (alias)" in table
assert "model_profiles_hash_kind_key unique (profile_hash, kind)" in table
assert "kind in ('embedding', 'rerank', 'chat')" in table
assert "kind = 'embedding' and dimension = 1024" in table
assert "kind in ('rerank', 'chat') and dimension is null" in table
assert "profile_hash ~ '^[0-9a-f]{64}$'" in table
assert "endpoint_identity_hash ~ '^[0-9a-f]{64}$'" in table
assert "jsonb_typeof(config_snapshot) = 'object'" in table
assert "model_profiles_config_snapshot_has_no_credentials" in table
for credential_name in (
"api[_-]?key",
"secret",
"password",
"token",
"authorization",
"credential",
):
assert credential_name in table
def test_knowledge_base_active_profile_is_nullable_and_restrictive() -> None:
assert "add column active_embedding_profile_hash char(64)" in NORMALIZED
assert (
"add column active_embedding_profile_kind text not null default 'embedding'" in NORMALIZED
)
assert "knowledge_bases_active_embedding_profile_hash_format" in NORMALIZED
assert "knowledge_bases_active_embedding_profile_kind" in NORMALIZED
assert "check (active_embedding_profile_kind = 'embedding')" in NORMALIZED
assert "knowledge_bases_active_embedding_profile_fk" in NORMALIZED
assert (
"foreign key ( active_embedding_profile_hash, active_embedding_profile_kind )" in NORMALIZED
)
assert "references rag.model_profiles (profile_hash, kind) on delete restrict" in NORMALIZED
assert "active_embedding_profile_hash is null" in NORMALIZED
def test_legacy_backfill_only_activates_one_unambiguous_searchable_fake_profile() -> None:
assert "insert into rag.model_profiles" in NORMALIZED
assert "chunk.searchable is true" in NORMALIZED
assert "lower(chunk.embedding_model) like 'fake-%'" in NORMALIZED
assert "chunk.embedding_dimension = 1024" in NORMALIZED
assert "having count(distinct chunk.embedding_model) = 1" in NORMALIZED
assert "'local-synthetic'" in NORMALIZED
assert "'deterministic-offline'" in NORMALIZED
assert "sha256(convert_to('local-fake', 'utf8'))" in NORMALIZED
assert "'existing_searchable_fake_chunks'" in NORMALIZED
assert "on conflict (profile_hash) do nothing" in NORMALIZED
activation_start = NORMALIZED.index("with unique_searchable_fake_profile as")
activation_end = NORMALIZED.index(") update rag.knowledge_bases", activation_start)
candidate_query = NORMALIZED[activation_start:activation_end]
assert "group by chunk.knowledge_base_id" in candidate_query
assert "having count(distinct chunk.embedding_profile_hash) = 1" in candidate_query
assert "limit 1" not in candidate_query
assert "active_embedding_profile_hash is null" in NORMALIZED[activation_start:]
def test_embedding_cache_is_profile_and_exact_text_keyed() -> None:
table = _table_definition("embedding_cache")
assert "profile_hash char(64) not null" in table
assert "profile_kind text not null default 'embedding'" in table
assert "embedding_text_sha256 char(64) not null" in table
assert "embedding vector(1024) not null" in table
assert "resolved_model text not null" in table
assert "provider_request_id text" in table
assert "usage jsonb not null default '{}'::jsonb" in table
assert "elapsed_ms integer not null" in table
assert "primary key (profile_hash, embedding_text_sha256)" in table
assert "references rag.model_profiles (profile_hash, kind) on delete restrict" in table
assert "profile_kind = 'embedding'" in table
assert "vector_dims(embedding) = 1024" in table
assert "jsonb_typeof(usage) = 'object'" in table
def test_chunk_assignments_bind_chunk_text_profile_cache_and_state() -> None:
table = _table_definition("chunk_embedding_assignments")
assert "primary key (chunk_id, profile_hash)" in table
assert "profile_kind text not null default 'embedding'" in table
assert "foreign key (chunk_id, embedding_text_sha256)" in table
assert "references rag.chunks (id, embedding_text_sha256) on delete cascade" in table
assert "foreign key (profile_hash, profile_kind)" in table
assert "references rag.model_profiles (profile_hash, kind) on delete restrict" in table
assert "profile_kind = 'embedding'" in table
assert "foreign key (cache_profile_hash, cache_embedding_text_sha256)" in table
assert "references rag.embedding_cache (profile_hash, embedding_text_sha256)" in table
assert "status in ('pending', 'embedding', 'ready', 'failed', 'stale')" in table
assert "status = 'ready' and cache_profile_hash = profile_hash" in table
assert "cache_embedding_text_sha256 = embedding_text_sha256" in table
assert "status <> 'ready' and cache_profile_hash is null" in table
assert "chunks_id_embedding_text_sha256_key" in NORMALIZED
def test_invocation_audit_table_is_metadata_only() -> None:
table = _table_definition("model_invocations")
for field in (
"trace_id uuid not null",
"caller text not null",
"operation text not null",
"profile_hash char(64) not null",
"model text not null",
"provider_request_id text",
"status text not null",
"item_count integer not null default 0",
"prompt_tokens integer not null default 0",
"completion_tokens integer not null default 0",
"total_tokens integer not null default 0",
"elapsed_ms integer",
"error_code text",
"started_at timestamptz not null default now()",
"finished_at timestamptz",
"created_at timestamptz not null default now()",
):
assert field in table
for forbidden_field in (
"api_key",
"secret",
"authorization",
"credential",
"endpoint",
"url",
"payload",
"request_body",
"response_body",
"prompt_text",
"query_text",
"input_text",
"output_text",
"content",
):
assert forbidden_field not in table
assert "total_tokens = prompt_tokens + completion_tokens" in table
assert "foreign key (profile_hash, operation)" in table
assert "references rag.model_profiles (profile_hash, kind)" in table
assert "status = 'succeeded' and error_code is null" in table
assert "status = 'failed' and error_code is not null" in table
assert "status = 'unknown' and error_code is not null" in table
assert "status = 'started' and elapsed_ms is null" in table
assert "status = 'started' and finished_at is null" in table
def test_chunks_get_stable_citations_and_active_profile_filter_index() -> None:
assert "add column citation_id uuid not null default gen_random_uuid()" in NORMALIZED
assert "chunks_citation_id_key unique (citation_id)" in NORMALIZED
assert "create index chunks_active_embedding_profile_filter" in NORMALIZED
assert (
"on rag.chunks ( knowledge_base_id, embedding_profile_hash, access_scope_id ) "
"where searchable"
) in NORMALIZED
def test_downgrade_removes_dependents_before_profiles_and_added_columns() -> None:
invocation_drop = NORMALIZED.index("drop table if exists rag.model_invocations")
assignment_drop = NORMALIZED.index("drop table if exists rag.chunk_embedding_assignments")
cache_drop = NORMALIZED.index("drop table if exists rag.embedding_cache")
chunk_binding_drop = NORMALIZED.index(
"drop constraint if exists chunks_id_embedding_text_sha256_key"
)
knowledge_base_fk_drop = NORMALIZED.index(
"drop constraint if exists knowledge_bases_active_embedding_profile_fk"
)
profile_drop = NORMALIZED.index("drop table if exists rag.model_profiles")
assert invocation_drop < profile_drop
assert assignment_drop < cache_drop < chunk_binding_drop < profile_drop
assert knowledge_base_fk_drop < profile_drop
assert "drop column if exists citation_id" in NORMALIZED
assert "drop column if exists active_embedding_profile_hash" in NORMALIZED
assert "drop column if exists active_embedding_profile_kind" in NORMALIZED