pycharter 0.0.20__py3-none-any.whl → 0.0.22__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. api/dependencies/__init__.py +2 -1
  2. api/dependencies/database.py +71 -5
  3. api/main.py +47 -8
  4. api/models/contracts.py +6 -4
  5. api/models/metadata.py +11 -7
  6. api/models/schemas.py +16 -10
  7. api/routes/v1/contracts.py +498 -226
  8. api/routes/v1/metadata.py +52 -211
  9. api/routes/v1/schemas.py +1 -1
  10. api/routes/v1/settings.py +88 -1
  11. api/utils.py +224 -0
  12. pycharter/__init__.py +149 -93
  13. pycharter/data/templates/template_transform_advanced.yaml +50 -0
  14. pycharter/data/templates/template_transform_simple.yaml +59 -0
  15. pycharter/db/models/base.py +1 -2
  16. pycharter/etl_generator/orchestrator.py +463 -487
  17. pycharter/metadata_store/postgres.py +16 -191
  18. pycharter/metadata_store/sqlite.py +12 -41
  19. {pycharter-0.0.20.dist-info → pycharter-0.0.22.dist-info}/METADATA +284 -62
  20. pycharter-0.0.22.dist-info/RECORD +358 -0
  21. ui/static/404/index.html +1 -1
  22. ui/static/404.html +1 -1
  23. ui/static/__next.__PAGE__.txt +1 -1
  24. ui/static/__next._full.txt +2 -2
  25. ui/static/__next._head.txt +1 -1
  26. ui/static/__next._index.txt +2 -2
  27. ui/static/__next._tree.txt +2 -2
  28. ui/static/_next/static/chunks/13d4a0fbd74c1ee4.js +1 -0
  29. ui/static/_next/static/chunks/2edb43b48432ac04.js +441 -0
  30. ui/static/_next/static/chunks/c4fa4f4114b7c352.js +1 -0
  31. ui/static/_next/static/chunks/d2363397e1b2bcab.css +1 -0
  32. ui/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
  33. ui/static/_not-found/__next._full.txt +2 -2
  34. ui/static/_not-found/__next._head.txt +1 -1
  35. ui/static/_not-found/__next._index.txt +2 -2
  36. ui/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  37. ui/static/_not-found/__next._not-found.txt +1 -1
  38. ui/static/_not-found/__next._tree.txt +2 -2
  39. ui/static/_not-found/index.html +1 -1
  40. ui/static/_not-found/index.txt +2 -2
  41. ui/static/contracts/__next._full.txt +3 -3
  42. ui/static/contracts/__next._head.txt +1 -1
  43. ui/static/contracts/__next._index.txt +2 -2
  44. ui/static/contracts/__next._tree.txt +2 -2
  45. ui/static/contracts/__next.contracts.__PAGE__.txt +2 -2
  46. ui/static/contracts/__next.contracts.txt +1 -1
  47. ui/static/contracts/index.html +1 -1
  48. ui/static/contracts/index.txt +3 -3
  49. ui/static/documentation/__next._full.txt +3 -3
  50. ui/static/documentation/__next._head.txt +1 -1
  51. ui/static/documentation/__next._index.txt +2 -2
  52. ui/static/documentation/__next._tree.txt +2 -2
  53. ui/static/documentation/__next.documentation.__PAGE__.txt +2 -2
  54. ui/static/documentation/__next.documentation.txt +1 -1
  55. ui/static/documentation/index.html +2 -2
  56. ui/static/documentation/index.txt +3 -3
  57. ui/static/index.html +1 -1
  58. ui/static/index.txt +2 -2
  59. ui/static/metadata/__next._full.txt +2 -2
  60. ui/static/metadata/__next._head.txt +1 -1
  61. ui/static/metadata/__next._index.txt +2 -2
  62. ui/static/metadata/__next._tree.txt +2 -2
  63. ui/static/metadata/__next.metadata.__PAGE__.txt +1 -1
  64. ui/static/metadata/__next.metadata.txt +1 -1
  65. ui/static/metadata/index.html +1 -1
  66. ui/static/metadata/index.txt +2 -2
  67. ui/static/quality/__next._full.txt +2 -2
  68. ui/static/quality/__next._head.txt +1 -1
  69. ui/static/quality/__next._index.txt +2 -2
  70. ui/static/quality/__next._tree.txt +2 -2
  71. ui/static/quality/__next.quality.__PAGE__.txt +1 -1
  72. ui/static/quality/__next.quality.txt +1 -1
  73. ui/static/quality/index.html +2 -2
  74. ui/static/quality/index.txt +2 -2
  75. ui/static/rules/__next._full.txt +2 -2
  76. ui/static/rules/__next._head.txt +1 -1
  77. ui/static/rules/__next._index.txt +2 -2
  78. ui/static/rules/__next._tree.txt +2 -2
  79. ui/static/rules/__next.rules.__PAGE__.txt +1 -1
  80. ui/static/rules/__next.rules.txt +1 -1
  81. ui/static/rules/index.html +1 -1
  82. ui/static/rules/index.txt +2 -2
  83. ui/static/schemas/__next._full.txt +2 -2
  84. ui/static/schemas/__next._head.txt +1 -1
  85. ui/static/schemas/__next._index.txt +2 -2
  86. ui/static/schemas/__next._tree.txt +2 -2
  87. ui/static/schemas/__next.schemas.__PAGE__.txt +1 -1
  88. ui/static/schemas/__next.schemas.txt +1 -1
  89. ui/static/schemas/index.html +1 -1
  90. ui/static/schemas/index.txt +2 -2
  91. ui/static/settings/__next._full.txt +2 -2
  92. ui/static/settings/__next._head.txt +1 -1
  93. ui/static/settings/__next._index.txt +2 -2
  94. ui/static/settings/__next._tree.txt +2 -2
  95. ui/static/settings/__next.settings.__PAGE__.txt +1 -1
  96. ui/static/settings/__next.settings.txt +1 -1
  97. ui/static/settings/index.html +1 -1
  98. ui/static/settings/index.txt +2 -2
  99. ui/static/static/.gitkeep +0 -0
  100. ui/static/static/404/index.html +1 -0
  101. ui/static/static/404.html +1 -0
  102. ui/static/static/__next.__PAGE__.txt +10 -0
  103. ui/static/static/__next._full.txt +30 -0
  104. ui/static/static/__next._head.txt +7 -0
  105. ui/static/static/__next._index.txt +9 -0
  106. ui/static/static/__next._tree.txt +2 -0
  107. ui/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
  108. ui/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
  109. ui/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
  110. ui/static/static/_next/static/chunks/2ab439ce003cd691.js +1 -0
  111. ui/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
  112. ui/static/static/_next/static/chunks/49ca65abd26ae49e.js +1 -0
  113. ui/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +1 -0
  114. ui/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
  115. ui/static/static/_next/static/chunks/75d88a058d8ffaa6.js +1 -0
  116. ui/static/static/_next/static/chunks/8c89634cf6bad76f.js +1 -0
  117. ui/static/static/_next/static/chunks/9667e7a3d359eb39.js +1 -0
  118. ui/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
  119. ui/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  120. ui/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
  121. ui/static/static/_next/static/chunks/c69f6cba366bd988.js +1 -0
  122. ui/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
  123. ui/static/static/_next/static/chunks/f061a4be97bfc3b3.js +1 -0
  124. ui/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
  125. ui/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
  126. ui/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
  127. ui/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
  128. ui/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
  129. ui/static/static/_not-found/__next._full.txt +17 -0
  130. ui/static/static/_not-found/__next._head.txt +7 -0
  131. ui/static/static/_not-found/__next._index.txt +9 -0
  132. ui/static/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
  133. ui/static/static/_not-found/__next._not-found.txt +4 -0
  134. ui/static/static/_not-found/__next._tree.txt +2 -0
  135. ui/static/static/_not-found/index.html +1 -0
  136. ui/static/static/_not-found/index.txt +17 -0
  137. ui/static/static/contracts/__next._full.txt +21 -0
  138. ui/static/static/contracts/__next._head.txt +7 -0
  139. ui/static/static/contracts/__next._index.txt +9 -0
  140. ui/static/static/contracts/__next._tree.txt +2 -0
  141. ui/static/static/contracts/__next.contracts.__PAGE__.txt +9 -0
  142. ui/static/static/contracts/__next.contracts.txt +4 -0
  143. ui/static/static/contracts/index.html +1 -0
  144. ui/static/static/contracts/index.txt +21 -0
  145. ui/static/static/documentation/__next._full.txt +21 -0
  146. ui/static/static/documentation/__next._head.txt +7 -0
  147. ui/static/static/documentation/__next._index.txt +9 -0
  148. ui/static/static/documentation/__next._tree.txt +2 -0
  149. ui/static/static/documentation/__next.documentation.__PAGE__.txt +9 -0
  150. ui/static/static/documentation/__next.documentation.txt +4 -0
  151. ui/static/static/documentation/index.html +93 -0
  152. ui/static/static/documentation/index.txt +21 -0
  153. ui/static/static/index.html +1 -0
  154. ui/static/static/index.txt +30 -0
  155. ui/static/static/metadata/__next._full.txt +21 -0
  156. ui/static/static/metadata/__next._head.txt +7 -0
  157. ui/static/static/metadata/__next._index.txt +9 -0
  158. ui/static/static/metadata/__next._tree.txt +2 -0
  159. ui/static/static/metadata/__next.metadata.__PAGE__.txt +9 -0
  160. ui/static/static/metadata/__next.metadata.txt +4 -0
  161. ui/static/static/metadata/index.html +1 -0
  162. ui/static/static/metadata/index.txt +21 -0
  163. ui/static/static/quality/__next._full.txt +21 -0
  164. ui/static/static/quality/__next._head.txt +7 -0
  165. ui/static/static/quality/__next._index.txt +9 -0
  166. ui/static/static/quality/__next._tree.txt +2 -0
  167. ui/static/static/quality/__next.quality.__PAGE__.txt +9 -0
  168. ui/static/static/quality/__next.quality.txt +4 -0
  169. ui/static/static/quality/index.html +2 -0
  170. ui/static/static/quality/index.txt +21 -0
  171. ui/static/static/rules/__next._full.txt +21 -0
  172. ui/static/static/rules/__next._head.txt +7 -0
  173. ui/static/static/rules/__next._index.txt +9 -0
  174. ui/static/static/rules/__next._tree.txt +2 -0
  175. ui/static/static/rules/__next.rules.__PAGE__.txt +9 -0
  176. ui/static/static/rules/__next.rules.txt +4 -0
  177. ui/static/static/rules/index.html +1 -0
  178. ui/static/static/rules/index.txt +21 -0
  179. ui/static/static/schemas/__next._full.txt +21 -0
  180. ui/static/static/schemas/__next._head.txt +7 -0
  181. ui/static/static/schemas/__next._index.txt +9 -0
  182. ui/static/static/schemas/__next._tree.txt +2 -0
  183. ui/static/static/schemas/__next.schemas.__PAGE__.txt +9 -0
  184. ui/static/static/schemas/__next.schemas.txt +4 -0
  185. ui/static/static/schemas/index.html +1 -0
  186. ui/static/static/schemas/index.txt +21 -0
  187. ui/static/static/settings/__next._full.txt +21 -0
  188. ui/static/static/settings/__next._head.txt +7 -0
  189. ui/static/static/settings/__next._index.txt +9 -0
  190. ui/static/static/settings/__next._tree.txt +2 -0
  191. ui/static/static/settings/__next.settings.__PAGE__.txt +9 -0
  192. ui/static/static/settings/__next.settings.txt +4 -0
  193. ui/static/static/settings/index.html +1 -0
  194. ui/static/static/settings/index.txt +21 -0
  195. ui/static/static/validation/__next._full.txt +21 -0
  196. ui/static/static/validation/__next._head.txt +7 -0
  197. ui/static/static/validation/__next._index.txt +9 -0
  198. ui/static/static/validation/__next._tree.txt +2 -0
  199. ui/static/static/validation/__next.validation.__PAGE__.txt +9 -0
  200. ui/static/static/validation/__next.validation.txt +4 -0
  201. ui/static/static/validation/index.html +1 -0
  202. ui/static/static/validation/index.txt +21 -0
  203. ui/static/validation/__next._full.txt +2 -2
  204. ui/static/validation/__next._head.txt +1 -1
  205. ui/static/validation/__next._index.txt +2 -2
  206. ui/static/validation/__next._tree.txt +2 -2
  207. ui/static/validation/__next.validation.__PAGE__.txt +1 -1
  208. ui/static/validation/__next.validation.txt +1 -1
  209. ui/static/validation/index.html +1 -1
  210. ui/static/validation/index.txt +2 -2
  211. pycharter/db/schemas/.ipynb_checkpoints/data_contract-checkpoint.py +0 -160
  212. pycharter-0.0.20.dist-info/RECORD +0 -247
  213. {pycharter-0.0.20.dist-info → pycharter-0.0.22.dist-info}/WHEEL +0 -0
  214. {pycharter-0.0.20.dist-info → pycharter-0.0.22.dist-info}/entry_points.txt +0 -0
  215. {pycharter-0.0.20.dist-info → pycharter-0.0.22.dist-info}/licenses/LICENSE +0 -0
  216. {pycharter-0.0.20.dist-info → pycharter-0.0.22.dist-info}/top_level.txt +0 -0
  217. /ui/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_buildManifest.js +0 -0
  218. /ui/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_ssgManifest.js +0 -0
  219. /ui/static/{_next → static/_next}/static/chunks/4e310fe5005770a3.css +0 -0
  220. /ui/static/{_next → static/_next}/static/chunks/5fc14c00a2779dc5.js +0 -0
  221. /ui/static/{_next → static/_next}/static/chunks/b584574fdc8ab13e.js +0 -0
  222. /ui/static/{_next → static/_next}/static/chunks/d5989c94d3614b3a.js +0 -0
@@ -889,25 +889,10 @@ class PostgresMetadataStore(MetadataStoreClient):
889
889
  existing = cur.fetchone()
890
890
 
891
891
  if existing:
892
- # Update existing metadata_record
893
- metadata_id = existing[0]
894
- cur.execute(
895
- f"""
896
- UPDATE {self._table_name("metadata_records")}
897
- SET title = %s,
898
- status = %s,
899
- description = %s,
900
- governance_rules = %s,
901
- updated_at = CURRENT_TIMESTAMP
902
- WHERE id = %s
903
- """,
904
- (
905
- title,
906
- status,
907
- description,
908
- json.dumps(governance_rules) if governance_rules else None,
909
- metadata_id,
910
- ),
892
+ # Prevent overwriting existing metadata - raise error instead
893
+ raise ValueError(
894
+ f"Metadata with title '{title}' and version '{version}' already exists. "
895
+ f"Cannot create duplicate artifacts. Use a different version number."
911
896
  )
912
897
  else:
913
898
  # Insert new metadata_record
@@ -1103,23 +1088,10 @@ class PostgresMetadataStore(MetadataStoreClient):
1103
1088
  existing = cur.fetchone()
1104
1089
 
1105
1090
  if existing:
1106
- # Update existing coercion_rules
1107
- rule_id = existing[0]
1108
- cur.execute(
1109
- f"""
1110
- UPDATE {self._table_name("coercion_rules")}
1111
- SET rules = %s,
1112
- title = %s,
1113
- schema_id = %s,
1114
- updated_at = CURRENT_TIMESTAMP
1115
- WHERE id = %s
1116
- """,
1117
- (
1118
- json.dumps(coercion_rules),
1119
- title,
1120
- schema_id,
1121
- rule_id,
1122
- ),
1091
+ # Prevent overwriting existing coercion rules - raise error instead
1092
+ raise ValueError(
1093
+ f"Coercion rules with title '{title}' and version '{version}' already exists. "
1094
+ f"Cannot create duplicate artifacts. Use a different version number."
1123
1095
  )
1124
1096
  else:
1125
1097
  # Insert new coercion_rules
@@ -1141,7 +1113,7 @@ class PostgresMetadataStore(MetadataStoreClient):
1141
1113
  )
1142
1114
  rule_id = cur.fetchone()[0]
1143
1115
 
1144
- # Update data_contract with coercion_rules_id (no version field - UUID is sufficient)
1116
+ # Update data_contract with coercion_rules_id
1145
1117
  cur.execute(
1146
1118
  f"""
1147
1119
  UPDATE {self._table_name("data_contracts")}
@@ -1151,9 +1123,7 @@ class PostgresMetadataStore(MetadataStoreClient):
1151
1123
  (rule_id, data_contract_id),
1152
1124
  )
1153
1125
  conn.commit()
1154
-
1155
- conn.commit()
1156
- return f"coercion:{schema_id}" + (f":{version}" if version else "")
1126
+ return str(rule_id)
1157
1127
 
1158
1128
  def get_coercion_rules(
1159
1129
  self, schema_id: str, version: Optional[str] = None
@@ -1214,136 +1184,6 @@ class PostgresMetadataStore(MetadataStoreClient):
1214
1184
  conn.rollback()
1215
1185
  raise
1216
1186
 
1217
- def get_coercion_rules_by_id(
1218
- self, coercion_rules_id: str
1219
- ) -> Optional[Dict[str, Any]]:
1220
- """
1221
- Retrieve coercion rules directly by their UUID.
1222
-
1223
- Args:
1224
- coercion_rules_id: Coercion rules UUID
1225
-
1226
- Returns:
1227
- Coercion rules dictionary or None if not found
1228
- """
1229
- self._require_connection()
1230
- conn = self._get_connection()
1231
-
1232
- try:
1233
- with conn.cursor(cursor_factory=RealDictCursor) as cur:
1234
- cur.execute(
1235
- f"""
1236
- SELECT rules
1237
- FROM {self._table_name("coercion_rules")}
1238
- WHERE id = %s
1239
- """,
1240
- (coercion_rules_id,),
1241
- )
1242
-
1243
- row = cur.fetchone()
1244
- if not row:
1245
- return None
1246
-
1247
- return self._parse_jsonb(row["rules"])
1248
- except Exception as e:
1249
- conn.rollback()
1250
- raise
1251
-
1252
- def get_validation_rules_by_id(
1253
- self, validation_rules_id: str
1254
- ) -> Optional[Dict[str, Any]]:
1255
- """
1256
- Retrieve validation rules directly by their UUID.
1257
-
1258
- Args:
1259
- validation_rules_id: Validation rules UUID
1260
-
1261
- Returns:
1262
- Validation rules dictionary or None if not found
1263
- """
1264
- self._require_connection()
1265
- conn = self._get_connection()
1266
-
1267
- try:
1268
- with conn.cursor(cursor_factory=RealDictCursor) as cur:
1269
- cur.execute(
1270
- f"""
1271
- SELECT rules
1272
- FROM {self._table_name("validation_rules")}
1273
- WHERE id = %s
1274
- """,
1275
- (validation_rules_id,),
1276
- )
1277
-
1278
- row = cur.fetchone()
1279
- if not row:
1280
- return None
1281
-
1282
- return self._parse_jsonb(row["rules"])
1283
- except Exception as e:
1284
- conn.rollback()
1285
- raise
1286
-
1287
- def get_metadata_by_id(
1288
- self, metadata_id: str
1289
- ) -> Optional[Dict[str, Any]]:
1290
- """
1291
- Retrieve metadata directly by its UUID.
1292
-
1293
- Args:
1294
- metadata_id: Metadata record UUID
1295
-
1296
- Returns:
1297
- Metadata dictionary or None if not found
1298
- """
1299
- self._require_connection()
1300
- conn = self._get_connection()
1301
-
1302
- try:
1303
- with conn.cursor(cursor_factory=RealDictCursor) as cur:
1304
- cur.execute(
1305
- f"""
1306
- SELECT *
1307
- FROM {self._table_name("metadata_records")}
1308
- WHERE id = %s
1309
- """,
1310
- (metadata_id,),
1311
- )
1312
-
1313
- row = cur.fetchone()
1314
- if not row:
1315
- return None
1316
-
1317
- metadata_record_id = row["id"]
1318
-
1319
- # Reconstruct metadata dictionary with all basic fields
1320
- metadata = {
1321
- "title": row.get("title"),
1322
- "status": row.get("status"),
1323
- "type": row.get("type"),
1324
- "description": row.get("description"),
1325
- "version": row.get("version"),
1326
- "created_at": row.get("created_at").isoformat() if row.get("created_at") else None,
1327
- "updated_at": row.get("updated_at").isoformat() if row.get("updated_at") else None,
1328
- "created_by": row.get("created_by"),
1329
- "updated_by": row.get("updated_by"),
1330
- }
1331
-
1332
- # Add JSON fields
1333
- if row.get("governance_rules"):
1334
- metadata["governance_rules"] = self._parse_jsonb(
1335
- row["governance_rules"]
1336
- )
1337
-
1338
- # Get all relationships
1339
- relationships = self._get_metadata_relationships(cur, metadata_record_id)
1340
- metadata.update(relationships)
1341
-
1342
- return metadata
1343
- except Exception as e:
1344
- conn.rollback()
1345
- raise
1346
-
1347
1187
  # ============================================================================
1348
1188
  # Validation Rules Operations
1349
1189
  # ============================================================================
@@ -1418,23 +1258,10 @@ class PostgresMetadataStore(MetadataStoreClient):
1418
1258
  existing = cur.fetchone()
1419
1259
 
1420
1260
  if existing:
1421
- # Update existing validation_rules
1422
- rule_id = existing[0]
1423
- cur.execute(
1424
- f"""
1425
- UPDATE {self._table_name("validation_rules")}
1426
- SET rules = %s,
1427
- title = %s,
1428
- schema_id = %s,
1429
- updated_at = CURRENT_TIMESTAMP
1430
- WHERE id = %s
1431
- """,
1432
- (
1433
- json.dumps(validation_rules),
1434
- title,
1435
- schema_id,
1436
- rule_id,
1437
- ),
1261
+ # Prevent overwriting existing validation rules - raise error instead
1262
+ raise ValueError(
1263
+ f"Validation rules with title '{title}' and version '{version}' already exists. "
1264
+ f"Cannot create duplicate artifacts. Use a different version number."
1438
1265
  )
1439
1266
  else:
1440
1267
  # Insert new validation_rules
@@ -1456,7 +1283,7 @@ class PostgresMetadataStore(MetadataStoreClient):
1456
1283
  )
1457
1284
  rule_id = cur.fetchone()[0]
1458
1285
 
1459
- # Update data_contract with validation_rules_id (no version field - UUID is sufficient)
1286
+ # Update data_contract with validation_rules_id
1460
1287
  cur.execute(
1461
1288
  f"""
1462
1289
  UPDATE {self._table_name("data_contracts")}
@@ -1466,9 +1293,7 @@ class PostgresMetadataStore(MetadataStoreClient):
1466
1293
  (rule_id, data_contract_id),
1467
1294
  )
1468
1295
  conn.commit()
1469
-
1470
- conn.commit()
1471
- return f"validation:{schema_id}" + (f":{version}" if version else "")
1296
+ return str(rule_id)
1472
1297
 
1473
1298
  def get_validation_rules(
1474
1299
  self, schema_id: str, version: Optional[str] = None
@@ -562,25 +562,10 @@ class SQLiteMetadataStore(MetadataStoreClient):
562
562
  existing = cursor.fetchone()
563
563
 
564
564
  if existing:
565
- # Update existing metadata_record
566
- metadata_id = existing[0]
567
- cursor.execute(
568
- """
569
- UPDATE metadata_records
570
- SET title = ?,
571
- status = ?,
572
- description = ?,
573
- governance_rules = ?,
574
- updated_at = CURRENT_TIMESTAMP
575
- WHERE id = ?
576
- """,
577
- (
578
- title,
579
- status,
580
- description,
581
- json.dumps(governance_rules) if governance_rules else None,
582
- metadata_id,
583
- ),
565
+ # Prevent overwriting existing metadata - raise error instead
566
+ raise ValueError(
567
+ f"Metadata with title '{title}' and version '{version}' already exists. "
568
+ f"Cannot create duplicate artifacts. Use a different version number."
584
569
  )
585
570
  else:
586
571
  # Generate UUID for new metadata_record
@@ -755,17 +740,10 @@ class SQLiteMetadataStore(MetadataStoreClient):
755
740
  existing = cursor.fetchone()
756
741
 
757
742
  if existing:
758
- # Update existing coercion_rules
759
- rule_id = existing[0]
760
- cursor.execute(
761
- """
762
- UPDATE coercion_rules
763
- SET rules = ?,
764
- title = ?,
765
- schema_id = ?
766
- WHERE id = ?
767
- """,
768
- (json.dumps(coercion_rules), title, schema_id, rule_id),
743
+ # Prevent overwriting existing coercion rules - raise error instead
744
+ raise ValueError(
745
+ f"Coercion rules with title '{title}' and version '{version}' already exists. "
746
+ f"Cannot create duplicate artifacts. Use a different version number."
769
747
  )
770
748
  else:
771
749
  # Generate UUID for new coercion_rules
@@ -1027,17 +1005,10 @@ class SQLiteMetadataStore(MetadataStoreClient):
1027
1005
  existing = cursor.fetchone()
1028
1006
 
1029
1007
  if existing:
1030
- # Update existing validation_rules
1031
- rule_id = existing[0]
1032
- cursor.execute(
1033
- """
1034
- UPDATE validation_rules
1035
- SET rules = ?,
1036
- title = ?,
1037
- schema_id = ?
1038
- WHERE id = ?
1039
- """,
1040
- (json.dumps(validation_rules), title, schema_id, rule_id),
1008
+ # Prevent overwriting existing validation rules - raise error instead
1009
+ raise ValueError(
1010
+ f"Validation rules with title '{title}' and version '{version}' already exists. "
1011
+ f"Cannot create duplicate artifacts. Use a different version number."
1041
1012
  )
1042
1013
  else:
1043
1014
  # Generate UUID for new validation_rules