test_schema_registry_v4_contract.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import json
  2. from pathlib import Path
  3. from content_agent.integrations.database_runtime import JSON_COLUMNS_BY_TABLE, TABLE_COLUMNS
  4. from scripts.count_schema_registry import parse_sql_schema
  5. ROOT = Path(__file__).resolve().parents[1]
  6. REGISTRY_PATH = ROOT / "tech_documents/数据库字段总览/content_agent_schema_registry.json"
  7. LEGACY_REGISTRY_FIELDS = {
  8. "content_agent_discovered_content_items.content_audience_profile",
  9. "content_agent_rule_decisions.age_50_plus_level",
  10. "content_agent_pattern_recall_evidence.decode_status",
  11. "content_agent_pattern_recall_evidence.decode_task_id",
  12. "content_agent_pattern_recall_evidence.matched_terms",
  13. "content_agent_pattern_recall_evidence.matched_category_paths",
  14. "content_agent_pattern_recall_evidence.decode_elements",
  15. "content_agent_pattern_recall_evidence.match_paths_request",
  16. "content_agent_pattern_recall_evidence.match_paths_response",
  17. }
  18. V4_TOUCHED_TABLES = {
  19. "content_agent_queries",
  20. "content_agent_pattern_recall_evidence",
  21. "content_agent_rule_decisions",
  22. "content_agent_walk_actions",
  23. "content_agent_source_path_records",
  24. "content_agent_author_assets",
  25. "content_agent_discovered_content_items",
  26. "content_agent_search_clue_assets",
  27. }
  28. def test_schema_registry_counts_match_sql_v4_baseline():
  29. registry = _registry()
  30. sql_tables = parse_sql_schema()
  31. assert len(sql_tables) == 25
  32. assert sum(len(table.columns) for table in sql_tables.values()) == 418
  33. assert sum(1 for table in sql_tables.values() for column in table.columns if column.is_json) == 63
  34. assert registry["database"]["sql_column_count"] == 418
  35. assert registry["database"]["json_column_count"] == 63
  36. assert registry["coverage_targets"]["sql_column_count"] == 418
  37. assert registry["coverage_targets"]["json_column_count"] == 63
  38. def test_v4_touched_tables_match_sql_runtime_and_json_column_whitelist():
  39. registry = _registry()
  40. sql_tables = parse_sql_schema()
  41. for table_name in V4_TOUCHED_TABLES:
  42. sql_columns = {column.name for column in sql_tables[table_name].columns}
  43. registry_columns = {
  44. column["field_name"]
  45. for column in registry["tables"][table_name]["columns"]
  46. }
  47. assert registry_columns == sql_columns
  48. if table_name in TABLE_COLUMNS:
  49. assert TABLE_COLUMNS[table_name] <= sql_columns
  50. json_columns = {column.name for column in sql_tables[table_name].columns if column.is_json}
  51. assert JSON_COLUMNS_BY_TABLE.get(table_name, set()) == json_columns
  52. def test_registry_no_longer_registers_sql_missing_legacy_fields():
  53. registry = _registry()
  54. registry_refs = {
  55. f"{table_name}.{column['field_name']}"
  56. for table_name, table in registry["tables"].items()
  57. for column in table["columns"]
  58. }
  59. indexed_refs = {
  60. ref
  61. for refs in registry["field_index"].values()
  62. for ref in refs
  63. }
  64. assert not (LEGACY_REGISTRY_FIELDS & registry_refs)
  65. assert not (LEGACY_REGISTRY_FIELDS & indexed_refs)
  66. def test_raw_payload_policy_matches_runtime_v4_tables():
  67. policy = _registry()["raw_payload_policy"]
  68. assert {
  69. "access_token",
  70. "refresh_token",
  71. "apikey",
  72. "authorization",
  73. "cookie",
  74. "session",
  75. "credential",
  76. } <= set(policy["forbidden_keys"])
  77. assert {
  78. "content_agent_pattern_recall_evidence",
  79. "content_agent_walk_actions",
  80. } <= set(policy["required_tables"])
  81. def _registry():
  82. return json.loads(REGISTRY_PATH.read_text(encoding="utf-8"))