pycharter 0.0.22__py3-none-any.whl → 0.0.24__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 (404) hide show
  1. api/main.py +27 -1
  2. api/models/docs.py +68 -0
  3. api/models/evolution.py +117 -0
  4. api/models/tracking.py +111 -0
  5. api/models/validation.py +46 -6
  6. api/routes/v1/__init__.py +14 -1
  7. api/routes/v1/docs.py +187 -0
  8. api/routes/v1/evolution.py +337 -0
  9. api/routes/v1/templates.py +211 -27
  10. api/routes/v1/tracking.py +301 -0
  11. api/routes/v1/validation.py +68 -31
  12. pycharter/__init__.py +268 -58
  13. pycharter/data/templates/contract/template_coercion_rules.yaml +57 -0
  14. pycharter/data/templates/contract/template_contract.yaml +122 -0
  15. pycharter/data/templates/contract/template_metadata.yaml +68 -0
  16. pycharter/data/templates/contract/template_schema.yaml +100 -0
  17. pycharter/data/templates/contract/template_validation_rules.yaml +75 -0
  18. pycharter/data/templates/etl/README.md +224 -0
  19. pycharter/data/templates/etl/extract_cloud_azure.yaml +24 -0
  20. pycharter/data/templates/etl/extract_cloud_gcs.yaml +25 -0
  21. pycharter/data/templates/etl/extract_cloud_s3.yaml +30 -0
  22. pycharter/data/templates/etl/extract_database.yaml +34 -0
  23. pycharter/data/templates/etl/extract_database_ssh.yaml +40 -0
  24. pycharter/data/templates/etl/extract_file_csv.yaml +21 -0
  25. pycharter/data/templates/etl/extract_file_glob.yaml +25 -0
  26. pycharter/data/templates/etl/extract_file_json.yaml +24 -0
  27. pycharter/data/templates/etl/extract_file_parquet.yaml +20 -0
  28. pycharter/data/templates/etl/extract_http_paginated.yaml +79 -0
  29. pycharter/data/templates/etl/extract_http_path_params.yaml +38 -0
  30. pycharter/data/templates/etl/extract_http_simple.yaml +62 -0
  31. pycharter/data/templates/etl/load_cloud_azure.yaml +24 -0
  32. pycharter/data/templates/etl/load_cloud_gcs.yaml +22 -0
  33. pycharter/data/templates/etl/load_cloud_s3.yaml +27 -0
  34. pycharter/data/templates/etl/load_file.yaml +34 -0
  35. pycharter/data/templates/etl/load_insert.yaml +18 -0
  36. pycharter/data/templates/etl/load_postgresql.yaml +39 -0
  37. pycharter/data/templates/etl/load_sqlite.yaml +21 -0
  38. pycharter/data/templates/etl/load_truncate_and_load.yaml +20 -0
  39. pycharter/data/templates/etl/load_upsert.yaml +25 -0
  40. pycharter/data/templates/etl/load_with_dlq.yaml +34 -0
  41. pycharter/data/templates/etl/load_with_ssh_tunnel.yaml +35 -0
  42. pycharter/data/templates/etl/pipeline_http_to_db.yaml +75 -0
  43. pycharter/data/templates/etl/transform_combined.yaml +48 -0
  44. pycharter/data/templates/etl/transform_custom_function.yaml +58 -0
  45. pycharter/data/templates/etl/transform_jsonata.yaml +51 -0
  46. pycharter/data/templates/etl/transform_simple.yaml +59 -0
  47. pycharter/db/schemas/.ipynb_checkpoints/data_contract-checkpoint.py +160 -0
  48. pycharter/docs_generator/__init__.py +43 -0
  49. pycharter/docs_generator/generator.py +465 -0
  50. pycharter/docs_generator/renderers.py +247 -0
  51. pycharter/etl_generator/__init__.py +168 -80
  52. pycharter/etl_generator/builder.py +121 -0
  53. pycharter/etl_generator/config_loader.py +394 -0
  54. pycharter/etl_generator/config_validator.py +418 -0
  55. pycharter/etl_generator/context.py +132 -0
  56. pycharter/etl_generator/expression.py +499 -0
  57. pycharter/etl_generator/extractors/__init__.py +30 -0
  58. pycharter/etl_generator/extractors/base.py +70 -0
  59. pycharter/etl_generator/extractors/cloud_storage.py +530 -0
  60. pycharter/etl_generator/extractors/database.py +221 -0
  61. pycharter/etl_generator/extractors/factory.py +185 -0
  62. pycharter/etl_generator/extractors/file.py +475 -0
  63. pycharter/etl_generator/extractors/http.py +895 -0
  64. pycharter/etl_generator/extractors/streaming.py +57 -0
  65. pycharter/etl_generator/loaders/__init__.py +41 -0
  66. pycharter/etl_generator/loaders/base.py +35 -0
  67. pycharter/etl_generator/loaders/cloud.py +87 -0
  68. pycharter/etl_generator/loaders/cloud_storage_loader.py +275 -0
  69. pycharter/etl_generator/loaders/database.py +274 -0
  70. pycharter/etl_generator/loaders/factory.py +180 -0
  71. pycharter/etl_generator/loaders/file.py +72 -0
  72. pycharter/etl_generator/loaders/file_loader.py +130 -0
  73. pycharter/etl_generator/pipeline.py +743 -0
  74. pycharter/etl_generator/protocols.py +54 -0
  75. pycharter/etl_generator/result.py +63 -0
  76. pycharter/etl_generator/schemas/__init__.py +49 -0
  77. pycharter/etl_generator/transformers/__init__.py +49 -0
  78. pycharter/etl_generator/transformers/base.py +63 -0
  79. pycharter/etl_generator/transformers/config.py +45 -0
  80. pycharter/etl_generator/transformers/custom_function.py +101 -0
  81. pycharter/etl_generator/transformers/jsonata_transformer.py +56 -0
  82. pycharter/etl_generator/transformers/operations.py +218 -0
  83. pycharter/etl_generator/transformers/pipeline.py +54 -0
  84. pycharter/etl_generator/transformers/simple_operations.py +131 -0
  85. pycharter/quality/__init__.py +25 -0
  86. pycharter/quality/tracking/__init__.py +64 -0
  87. pycharter/quality/tracking/collector.py +318 -0
  88. pycharter/quality/tracking/exporters.py +238 -0
  89. pycharter/quality/tracking/models.py +194 -0
  90. pycharter/quality/tracking/store.py +385 -0
  91. pycharter/runtime_validator/__init__.py +20 -7
  92. pycharter/runtime_validator/builder.py +328 -0
  93. pycharter/runtime_validator/validator.py +311 -7
  94. pycharter/runtime_validator/validator_core.py +61 -0
  95. pycharter/schema_evolution/__init__.py +61 -0
  96. pycharter/schema_evolution/compatibility.py +270 -0
  97. pycharter/schema_evolution/diff.py +496 -0
  98. pycharter/schema_evolution/models.py +201 -0
  99. pycharter/shared/__init__.py +56 -0
  100. pycharter/shared/errors.py +296 -0
  101. pycharter/shared/protocols.py +234 -0
  102. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/METADATA +146 -26
  103. pycharter-0.0.24.dist-info/RECORD +543 -0
  104. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/WHEEL +1 -1
  105. ui/static/404/index.html +1 -1
  106. ui/static/404.html +1 -1
  107. ui/static/__next.__PAGE__.txt +1 -1
  108. ui/static/__next._full.txt +1 -1
  109. ui/static/__next._head.txt +1 -1
  110. ui/static/__next._index.txt +1 -1
  111. ui/static/__next._tree.txt +1 -1
  112. ui/static/_next/static/chunks/26dfc590f7714c03.js +1 -0
  113. ui/static/_next/static/chunks/34d289e6db2ef551.js +1 -0
  114. ui/static/_next/static/chunks/99508d9d5869cc27.js +1 -0
  115. ui/static/_next/static/chunks/b313c35a6ba76574.js +1 -0
  116. ui/static/_not-found/__next._full.txt +1 -1
  117. ui/static/_not-found/__next._head.txt +1 -1
  118. ui/static/_not-found/__next._index.txt +1 -1
  119. ui/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  120. ui/static/_not-found/__next._not-found.txt +1 -1
  121. ui/static/_not-found/__next._tree.txt +1 -1
  122. ui/static/_not-found/index.html +1 -1
  123. ui/static/_not-found/index.txt +1 -1
  124. ui/static/contracts/__next._full.txt +2 -2
  125. ui/static/contracts/__next._head.txt +1 -1
  126. ui/static/contracts/__next._index.txt +1 -1
  127. ui/static/contracts/__next._tree.txt +1 -1
  128. ui/static/contracts/__next.contracts.__PAGE__.txt +2 -2
  129. ui/static/contracts/__next.contracts.txt +1 -1
  130. ui/static/contracts/index.html +1 -1
  131. ui/static/contracts/index.txt +2 -2
  132. ui/static/documentation/__next._full.txt +1 -1
  133. ui/static/documentation/__next._head.txt +1 -1
  134. ui/static/documentation/__next._index.txt +1 -1
  135. ui/static/documentation/__next._tree.txt +1 -1
  136. ui/static/documentation/__next.documentation.__PAGE__.txt +1 -1
  137. ui/static/documentation/__next.documentation.txt +1 -1
  138. ui/static/documentation/index.html +2 -2
  139. ui/static/documentation/index.txt +1 -1
  140. ui/static/index.html +1 -1
  141. ui/static/index.txt +1 -1
  142. ui/static/metadata/__next._full.txt +1 -1
  143. ui/static/metadata/__next._head.txt +1 -1
  144. ui/static/metadata/__next._index.txt +1 -1
  145. ui/static/metadata/__next._tree.txt +1 -1
  146. ui/static/metadata/__next.metadata.__PAGE__.txt +1 -1
  147. ui/static/metadata/__next.metadata.txt +1 -1
  148. ui/static/metadata/index.html +1 -1
  149. ui/static/metadata/index.txt +1 -1
  150. ui/static/quality/__next._full.txt +2 -2
  151. ui/static/quality/__next._head.txt +1 -1
  152. ui/static/quality/__next._index.txt +1 -1
  153. ui/static/quality/__next._tree.txt +1 -1
  154. ui/static/quality/__next.quality.__PAGE__.txt +2 -2
  155. ui/static/quality/__next.quality.txt +1 -1
  156. ui/static/quality/index.html +2 -2
  157. ui/static/quality/index.txt +2 -2
  158. ui/static/rules/__next._full.txt +1 -1
  159. ui/static/rules/__next._head.txt +1 -1
  160. ui/static/rules/__next._index.txt +1 -1
  161. ui/static/rules/__next._tree.txt +1 -1
  162. ui/static/rules/__next.rules.__PAGE__.txt +1 -1
  163. ui/static/rules/__next.rules.txt +1 -1
  164. ui/static/rules/index.html +1 -1
  165. ui/static/rules/index.txt +1 -1
  166. ui/static/schemas/__next._full.txt +1 -1
  167. ui/static/schemas/__next._head.txt +1 -1
  168. ui/static/schemas/__next._index.txt +1 -1
  169. ui/static/schemas/__next._tree.txt +1 -1
  170. ui/static/schemas/__next.schemas.__PAGE__.txt +1 -1
  171. ui/static/schemas/__next.schemas.txt +1 -1
  172. ui/static/schemas/index.html +1 -1
  173. ui/static/schemas/index.txt +1 -1
  174. ui/static/settings/__next._full.txt +1 -1
  175. ui/static/settings/__next._head.txt +1 -1
  176. ui/static/settings/__next._index.txt +1 -1
  177. ui/static/settings/__next._tree.txt +1 -1
  178. ui/static/settings/__next.settings.__PAGE__.txt +1 -1
  179. ui/static/settings/__next.settings.txt +1 -1
  180. ui/static/settings/index.html +1 -1
  181. ui/static/settings/index.txt +1 -1
  182. ui/static/static/404/index.html +1 -1
  183. ui/static/static/404.html +1 -1
  184. ui/static/static/__next.__PAGE__.txt +1 -1
  185. ui/static/static/__next._full.txt +2 -2
  186. ui/static/static/__next._head.txt +1 -1
  187. ui/static/static/__next._index.txt +2 -2
  188. ui/static/static/__next._tree.txt +2 -2
  189. ui/static/static/_next/static/chunks/13d4a0fbd74c1ee4.js +1 -0
  190. ui/static/static/_next/static/chunks/2edb43b48432ac04.js +441 -0
  191. ui/static/static/_next/static/chunks/d2363397e1b2bcab.css +1 -0
  192. ui/static/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
  193. ui/static/static/_not-found/__next._full.txt +2 -2
  194. ui/static/static/_not-found/__next._head.txt +1 -1
  195. ui/static/static/_not-found/__next._index.txt +2 -2
  196. ui/static/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  197. ui/static/static/_not-found/__next._not-found.txt +1 -1
  198. ui/static/static/_not-found/__next._tree.txt +2 -2
  199. ui/static/static/_not-found/index.html +1 -1
  200. ui/static/static/_not-found/index.txt +2 -2
  201. ui/static/static/contracts/__next._full.txt +3 -3
  202. ui/static/static/contracts/__next._head.txt +1 -1
  203. ui/static/static/contracts/__next._index.txt +2 -2
  204. ui/static/static/contracts/__next._tree.txt +2 -2
  205. ui/static/static/contracts/__next.contracts.__PAGE__.txt +2 -2
  206. ui/static/static/contracts/__next.contracts.txt +1 -1
  207. ui/static/static/contracts/index.html +1 -1
  208. ui/static/static/contracts/index.txt +3 -3
  209. ui/static/static/documentation/__next._full.txt +3 -3
  210. ui/static/static/documentation/__next._head.txt +1 -1
  211. ui/static/static/documentation/__next._index.txt +2 -2
  212. ui/static/static/documentation/__next._tree.txt +2 -2
  213. ui/static/static/documentation/__next.documentation.__PAGE__.txt +2 -2
  214. ui/static/static/documentation/__next.documentation.txt +1 -1
  215. ui/static/static/documentation/index.html +2 -2
  216. ui/static/static/documentation/index.txt +3 -3
  217. ui/static/static/index.html +1 -1
  218. ui/static/static/index.txt +2 -2
  219. ui/static/static/metadata/__next._full.txt +2 -2
  220. ui/static/static/metadata/__next._head.txt +1 -1
  221. ui/static/static/metadata/__next._index.txt +2 -2
  222. ui/static/static/metadata/__next._tree.txt +2 -2
  223. ui/static/static/metadata/__next.metadata.__PAGE__.txt +1 -1
  224. ui/static/static/metadata/__next.metadata.txt +1 -1
  225. ui/static/static/metadata/index.html +1 -1
  226. ui/static/static/metadata/index.txt +2 -2
  227. ui/static/static/quality/__next._full.txt +2 -2
  228. ui/static/static/quality/__next._head.txt +1 -1
  229. ui/static/static/quality/__next._index.txt +2 -2
  230. ui/static/static/quality/__next._tree.txt +2 -2
  231. ui/static/static/quality/__next.quality.__PAGE__.txt +1 -1
  232. ui/static/static/quality/__next.quality.txt +1 -1
  233. ui/static/static/quality/index.html +2 -2
  234. ui/static/static/quality/index.txt +2 -2
  235. ui/static/static/rules/__next._full.txt +2 -2
  236. ui/static/static/rules/__next._head.txt +1 -1
  237. ui/static/static/rules/__next._index.txt +2 -2
  238. ui/static/static/rules/__next._tree.txt +2 -2
  239. ui/static/static/rules/__next.rules.__PAGE__.txt +1 -1
  240. ui/static/static/rules/__next.rules.txt +1 -1
  241. ui/static/static/rules/index.html +1 -1
  242. ui/static/static/rules/index.txt +2 -2
  243. ui/static/static/schemas/__next._full.txt +2 -2
  244. ui/static/static/schemas/__next._head.txt +1 -1
  245. ui/static/static/schemas/__next._index.txt +2 -2
  246. ui/static/static/schemas/__next._tree.txt +2 -2
  247. ui/static/static/schemas/__next.schemas.__PAGE__.txt +1 -1
  248. ui/static/static/schemas/__next.schemas.txt +1 -1
  249. ui/static/static/schemas/index.html +1 -1
  250. ui/static/static/schemas/index.txt +2 -2
  251. ui/static/static/settings/__next._full.txt +2 -2
  252. ui/static/static/settings/__next._head.txt +1 -1
  253. ui/static/static/settings/__next._index.txt +2 -2
  254. ui/static/static/settings/__next._tree.txt +2 -2
  255. ui/static/static/settings/__next.settings.__PAGE__.txt +1 -1
  256. ui/static/static/settings/__next.settings.txt +1 -1
  257. ui/static/static/settings/index.html +1 -1
  258. ui/static/static/settings/index.txt +2 -2
  259. ui/static/static/static/.gitkeep +0 -0
  260. ui/static/static/static/404/index.html +1 -0
  261. ui/static/static/static/404.html +1 -0
  262. ui/static/static/static/__next.__PAGE__.txt +10 -0
  263. ui/static/static/static/__next._full.txt +30 -0
  264. ui/static/static/static/__next._head.txt +7 -0
  265. ui/static/static/static/__next._index.txt +9 -0
  266. ui/static/static/static/__next._tree.txt +2 -0
  267. ui/static/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
  268. ui/static/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
  269. ui/static/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
  270. ui/static/static/static/_next/static/chunks/2ab439ce003cd691.js +1 -0
  271. ui/static/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
  272. ui/static/static/static/_next/static/chunks/49ca65abd26ae49e.js +1 -0
  273. ui/static/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
  274. ui/static/static/static/_next/static/chunks/9667e7a3d359eb39.js +1 -0
  275. ui/static/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
  276. ui/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  277. ui/static/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
  278. ui/static/static/static/_next/static/chunks/c69f6cba366bd988.js +1 -0
  279. ui/static/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
  280. ui/static/static/static/_next/static/chunks/f061a4be97bfc3b3.js +1 -0
  281. ui/static/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
  282. ui/static/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
  283. ui/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
  284. ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
  285. ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
  286. ui/static/static/static/_not-found/__next._full.txt +17 -0
  287. ui/static/static/static/_not-found/__next._head.txt +7 -0
  288. ui/static/static/static/_not-found/__next._index.txt +9 -0
  289. ui/static/static/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
  290. ui/static/static/static/_not-found/__next._not-found.txt +4 -0
  291. ui/static/static/static/_not-found/__next._tree.txt +2 -0
  292. ui/static/static/static/_not-found/index.html +1 -0
  293. ui/static/static/static/_not-found/index.txt +17 -0
  294. ui/static/static/static/contracts/__next._full.txt +21 -0
  295. ui/static/static/static/contracts/__next._head.txt +7 -0
  296. ui/static/static/static/contracts/__next._index.txt +9 -0
  297. ui/static/static/static/contracts/__next._tree.txt +2 -0
  298. ui/static/static/static/contracts/__next.contracts.__PAGE__.txt +9 -0
  299. ui/static/static/static/contracts/__next.contracts.txt +4 -0
  300. ui/static/static/static/contracts/index.html +1 -0
  301. ui/static/static/static/contracts/index.txt +21 -0
  302. ui/static/static/static/documentation/__next._full.txt +21 -0
  303. ui/static/static/static/documentation/__next._head.txt +7 -0
  304. ui/static/static/static/documentation/__next._index.txt +9 -0
  305. ui/static/static/static/documentation/__next._tree.txt +2 -0
  306. ui/static/static/static/documentation/__next.documentation.__PAGE__.txt +9 -0
  307. ui/static/static/static/documentation/__next.documentation.txt +4 -0
  308. ui/static/static/static/documentation/index.html +93 -0
  309. ui/static/static/static/documentation/index.txt +21 -0
  310. ui/static/static/static/index.html +1 -0
  311. ui/static/static/static/index.txt +30 -0
  312. ui/static/static/static/metadata/__next._full.txt +21 -0
  313. ui/static/static/static/metadata/__next._head.txt +7 -0
  314. ui/static/static/static/metadata/__next._index.txt +9 -0
  315. ui/static/static/static/metadata/__next._tree.txt +2 -0
  316. ui/static/static/static/metadata/__next.metadata.__PAGE__.txt +9 -0
  317. ui/static/static/static/metadata/__next.metadata.txt +4 -0
  318. ui/static/static/static/metadata/index.html +1 -0
  319. ui/static/static/static/metadata/index.txt +21 -0
  320. ui/static/static/static/quality/__next._full.txt +21 -0
  321. ui/static/static/static/quality/__next._head.txt +7 -0
  322. ui/static/static/static/quality/__next._index.txt +9 -0
  323. ui/static/static/static/quality/__next._tree.txt +2 -0
  324. ui/static/static/static/quality/__next.quality.__PAGE__.txt +9 -0
  325. ui/static/static/static/quality/__next.quality.txt +4 -0
  326. ui/static/static/static/quality/index.html +2 -0
  327. ui/static/static/static/quality/index.txt +21 -0
  328. ui/static/static/static/rules/__next._full.txt +21 -0
  329. ui/static/static/static/rules/__next._head.txt +7 -0
  330. ui/static/static/static/rules/__next._index.txt +9 -0
  331. ui/static/static/static/rules/__next._tree.txt +2 -0
  332. ui/static/static/static/rules/__next.rules.__PAGE__.txt +9 -0
  333. ui/static/static/static/rules/__next.rules.txt +4 -0
  334. ui/static/static/static/rules/index.html +1 -0
  335. ui/static/static/static/rules/index.txt +21 -0
  336. ui/static/static/static/schemas/__next._full.txt +21 -0
  337. ui/static/static/static/schemas/__next._head.txt +7 -0
  338. ui/static/static/static/schemas/__next._index.txt +9 -0
  339. ui/static/static/static/schemas/__next._tree.txt +2 -0
  340. ui/static/static/static/schemas/__next.schemas.__PAGE__.txt +9 -0
  341. ui/static/static/static/schemas/__next.schemas.txt +4 -0
  342. ui/static/static/static/schemas/index.html +1 -0
  343. ui/static/static/static/schemas/index.txt +21 -0
  344. ui/static/static/static/settings/__next._full.txt +21 -0
  345. ui/static/static/static/settings/__next._head.txt +7 -0
  346. ui/static/static/static/settings/__next._index.txt +9 -0
  347. ui/static/static/static/settings/__next._tree.txt +2 -0
  348. ui/static/static/static/settings/__next.settings.__PAGE__.txt +9 -0
  349. ui/static/static/static/settings/__next.settings.txt +4 -0
  350. ui/static/static/static/settings/index.html +1 -0
  351. ui/static/static/static/settings/index.txt +21 -0
  352. ui/static/static/static/validation/__next._full.txt +21 -0
  353. ui/static/static/static/validation/__next._head.txt +7 -0
  354. ui/static/static/static/validation/__next._index.txt +9 -0
  355. ui/static/static/static/validation/__next._tree.txt +2 -0
  356. ui/static/static/static/validation/__next.validation.__PAGE__.txt +9 -0
  357. ui/static/static/static/validation/__next.validation.txt +4 -0
  358. ui/static/static/static/validation/index.html +1 -0
  359. ui/static/static/static/validation/index.txt +21 -0
  360. ui/static/static/validation/__next._full.txt +2 -2
  361. ui/static/static/validation/__next._head.txt +1 -1
  362. ui/static/static/validation/__next._index.txt +2 -2
  363. ui/static/static/validation/__next._tree.txt +2 -2
  364. ui/static/static/validation/__next.validation.__PAGE__.txt +1 -1
  365. ui/static/static/validation/__next.validation.txt +1 -1
  366. ui/static/static/validation/index.html +1 -1
  367. ui/static/static/validation/index.txt +2 -2
  368. ui/static/validation/__next._full.txt +2 -2
  369. ui/static/validation/__next._head.txt +1 -1
  370. ui/static/validation/__next._index.txt +1 -1
  371. ui/static/validation/__next._tree.txt +1 -1
  372. ui/static/validation/__next.validation.__PAGE__.txt +2 -2
  373. ui/static/validation/__next.validation.txt +1 -1
  374. ui/static/validation/index.html +1 -1
  375. ui/static/validation/index.txt +2 -2
  376. pycharter/data/templates/template_coercion_rules.yaml +0 -15
  377. pycharter/data/templates/template_contract.yaml +0 -587
  378. pycharter/data/templates/template_metadata.yaml +0 -38
  379. pycharter/data/templates/template_schema.yaml +0 -22
  380. pycharter/data/templates/template_transform_advanced.yaml +0 -50
  381. pycharter/data/templates/template_transform_simple.yaml +0 -59
  382. pycharter/data/templates/template_validation_rules.yaml +0 -29
  383. pycharter/etl_generator/extraction.py +0 -916
  384. pycharter/etl_generator/factory.py +0 -174
  385. pycharter/etl_generator/orchestrator.py +0 -1650
  386. pycharter/integrations/__init__.py +0 -19
  387. pycharter/integrations/kafka.py +0 -178
  388. pycharter/integrations/streaming.py +0 -100
  389. pycharter-0.0.22.dist-info/RECORD +0 -358
  390. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/entry_points.txt +0 -0
  391. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/licenses/LICENSE +0 -0
  392. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/top_level.txt +0 -0
  393. /ui/static/_next/static/{0rYA78L88aUyD2Uh38hhX → 2gKjNv6YvE6BcIdFthBLs}/_buildManifest.js +0 -0
  394. /ui/static/_next/static/{0rYA78L88aUyD2Uh38hhX → 2gKjNv6YvE6BcIdFthBLs}/_ssgManifest.js +0 -0
  395. /ui/static/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_buildManifest.js +0 -0
  396. /ui/static/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_ssgManifest.js +0 -0
  397. /ui/static/{_next → static/_next}/static/chunks/c4fa4f4114b7c352.js +0 -0
  398. /ui/static/static/{_next → static/_next}/static/chunks/4e310fe5005770a3.css +0 -0
  399. /ui/static/{_next → static/static/_next}/static/chunks/5e04d10c4a7b58a3.js +0 -0
  400. /ui/static/static/{_next → static/_next}/static/chunks/5fc14c00a2779dc5.js +0 -0
  401. /ui/static/{_next → static/static/_next}/static/chunks/75d88a058d8ffaa6.js +0 -0
  402. /ui/static/{_next → static/static/_next}/static/chunks/8c89634cf6bad76f.js +0 -0
  403. /ui/static/static/{_next → static/_next}/static/chunks/b584574fdc8ab13e.js +0 -0
  404. /ui/static/static/{_next → static/_next}/static/chunks/d5989c94d3614b3a.js +0 -0
pycharter/__init__.py CHANGED
@@ -1,22 +1,97 @@
1
1
  """
2
- PyCharter - Data Contract Management and Validation
2
+ PyCharter - Data Contract Management, ETL Pipelines, and Validation
3
3
 
4
4
  Core Services:
5
- 1. Contract Parser - Reads and decomposes data contract files
6
- 2. Contract Builder - Constructs consolidated contracts from separate artifacts
7
- 3. Metadata Store - Database operations for metadata storage
8
- 4. Pydantic Generator - Generates Pydantic models from JSON Schema
9
- 5. JSON Schema Converter - Converts Pydantic models to JSON Schema
10
- 6. Runtime Validator - Validation utilities
11
- 7. Quality Assurance - Data quality checking and monitoring
12
-
13
- API Organization:
14
- - Tier 1: Primary Interfaces (Classes - Use these for best performance)
15
- - Tier 2: Convenience Functions (Quick start - one-off use cases)
16
- - Tier 3: Low-Level Utilities (When you already have models/schemas)
5
+ 1. ETL Pipelines - Build and run ETL pipelines with | operator
6
+ 2. Contract Parser - Reads and decomposes data contract files
7
+ 3. Contract Builder - Constructs consolidated contracts from separate artifacts
8
+ 4. Metadata Store - Database operations for metadata storage
9
+ 5. Pydantic Generator - Generates Pydantic models from JSON Schema
10
+ 6. JSON Schema Converter - Converts Pydantic models to JSON Schema
11
+ 7. Runtime Validator - Validation utilities
12
+ 8. Quality Assurance - Data quality checking and monitoring
13
+
14
+ ETL API:
15
+ >>> from pycharter import Pipeline, HTTPExtractor, PostgresLoader, Rename, AddField
16
+ >>>
17
+ >>> # Programmatic pipeline with | operator
18
+ >>> pipeline = (
19
+ ... Pipeline(HTTPExtractor(url="https://api.example.com/data"))
20
+ ... | Rename({"old": "new"})
21
+ ... | AddField("processed_at", "now()")
22
+ ... | PostgresLoader(connection_string="...", table="users")
23
+ ... )
24
+ >>> result = await pipeline.run() # run() is async; use asyncio.run() from scripts
25
+ >>>
26
+ >>> # Config-driven (explicit files)
27
+ >>> pipeline = Pipeline.from_config_files(
28
+ ... extract="configs/extract.yaml",
29
+ ... load="configs/load.yaml",
30
+ ... variables={"API_KEY": "secret"}
31
+ ... )
32
+ >>>
33
+ >>> # Config-driven (directory with extract.yaml, transform.yaml, load.yaml)
34
+ >>> pipeline = Pipeline.from_config_dir("pipelines/users/")
35
+ >>>
36
+ >>> # Config-driven (single file)
37
+ >>> pipeline = Pipeline.from_config_file("pipelines/users/pipeline.yaml")
38
+
39
+ Validator API:
40
+ >>> from pycharter import Validator
41
+ >>>
42
+ >>> # From explicit files
43
+ >>> validator = Validator.from_files(schema="schema.yaml")
44
+ >>>
45
+ >>> # From directory
46
+ >>> validator = Validator.from_dir("contracts/users/")
47
+ >>>
48
+ >>> result = validator.validate({"name": "Alice", "age": 30})
17
49
  """
18
50
 
19
- __version__ = "0.0.22"
51
+ __version__ = "0.1.0"
52
+
53
+ # ============================================================================
54
+ # ETL PIPELINES
55
+ # ============================================================================
56
+
57
+ from pycharter.etl_generator import (
58
+ # Core
59
+ Pipeline,
60
+ PipelineBuilder,
61
+ PipelineContext,
62
+ PipelineResult,
63
+ BatchResult,
64
+ LoadResult,
65
+ # Protocols
66
+ Extractor,
67
+ Transformer,
68
+ Loader,
69
+ # Extractors
70
+ BaseExtractor,
71
+ HTTPExtractor,
72
+ FileExtractor,
73
+ DatabaseExtractor,
74
+ CloudStorageExtractor,
75
+ # Transformers
76
+ BaseTransformer,
77
+ TransformerChain,
78
+ Rename,
79
+ AddField,
80
+ Drop,
81
+ Select,
82
+ Filter,
83
+ Convert,
84
+ Default,
85
+ Map,
86
+ FlatMap,
87
+ CustomFunction,
88
+ # Loaders
89
+ BaseLoader,
90
+ PostgresLoader,
91
+ DatabaseLoader,
92
+ FileLoader,
93
+ CloudStorageLoader,
94
+ )
20
95
 
21
96
  # ============================================================================
22
97
  # TIER 1: PRIMARY INTERFACES (Classes - Use these for best performance)
@@ -25,7 +100,9 @@ __version__ = "0.0.22"
25
100
  # Runtime Validator (PRIMARY INTERFACE)
26
101
  from pycharter.runtime_validator import (
27
102
  Validator, # ⭐ PRIMARY: Use this for validation
103
+ ValidatorBuilder, # Fluent API for building validators
28
104
  create_validator,
105
+ QualityMetrics as ValidationQualityMetrics, # Quality metrics from validation
29
106
  )
30
107
 
31
108
  # Quality Assurance (PRIMARY INTERFACE)
@@ -140,22 +217,145 @@ from pycharter.quality import (
140
217
  ViolationTracker,
141
218
  ViolationRecord,
142
219
  DataProfiler,
220
+ # Tracking submodule
221
+ MetricsCollector,
222
+ ValidationMetric,
223
+ MetricsSummary,
224
+ InMemoryMetricsStore,
225
+ SQLiteMetricsStore,
226
+ )
227
+
228
+ # ============================================================================
229
+ # DOCUMENTATION GENERATION
230
+ # ============================================================================
231
+
232
+ from pycharter.docs_generator import (
233
+ DocsGenerator,
234
+ generate_docs,
235
+ MarkdownRenderer,
236
+ HTMLRenderer,
237
+ )
238
+
239
+ # ============================================================================
240
+ # SCHEMA EVOLUTION
241
+ # ============================================================================
242
+
243
+ from pycharter.schema_evolution import (
244
+ check_compatibility,
245
+ compute_diff,
246
+ CompatibilityResult,
247
+ SchemaDiff,
248
+ SchemaChange,
249
+ ChangeType,
250
+ CompatibilityMode,
251
+ )
252
+
253
+ # ============================================================================
254
+ # PROTOCOLS AND ERROR HANDLING
255
+ # ============================================================================
256
+
257
+ from pycharter.shared import (
258
+ # Protocols for extensibility
259
+ MetadataStore,
260
+ CoercionRegistry,
261
+ ValidationRegistry,
262
+ DataValidator,
263
+ # Exception hierarchy (catch PyCharterError for any pycharter failure)
264
+ PyCharterError,
265
+ ConfigError,
266
+ ConfigValidationError,
267
+ ConfigLoadError,
268
+ ExpressionError,
269
+ # Error handling
270
+ ErrorMode,
271
+ ErrorContext,
272
+ StrictMode,
273
+ LenientMode,
274
+ set_error_mode,
143
275
  )
144
276
 
145
277
  __all__ = [
146
278
  # ========================================================================
147
- # TIER 1: PRIMARY INTERFACES
279
+ # ETL PIPELINES
280
+ # ========================================================================
281
+ # Core
282
+ "Pipeline",
283
+ "PipelineBuilder",
284
+ "PipelineContext",
285
+ "PipelineResult",
286
+ "BatchResult",
287
+ "LoadResult",
288
+ # Protocols
289
+ "Extractor",
290
+ "Transformer",
291
+ "Loader",
292
+ # Extractors
293
+ "BaseExtractor",
294
+ "HTTPExtractor",
295
+ "FileExtractor",
296
+ "DatabaseExtractor",
297
+ "CloudStorageExtractor",
298
+ # Transformers
299
+ "BaseTransformer",
300
+ "TransformerChain",
301
+ "Rename",
302
+ "AddField",
303
+ "Drop",
304
+ "Select",
305
+ "Filter",
306
+ "Convert",
307
+ "Default",
308
+ "Map",
309
+ "FlatMap",
310
+ "CustomFunction",
311
+ # Loaders
312
+ "BaseLoader",
313
+ "PostgresLoader",
314
+ "DatabaseLoader",
315
+ "FileLoader",
316
+ "CloudStorageLoader",
317
+ # Exceptions and error handling
318
+ "PyCharterError",
319
+ "ConfigError",
320
+ "ConfigValidationError",
321
+ "ConfigLoadError",
322
+ "ExpressionError",
323
+ "ErrorMode",
324
+ "ErrorContext",
325
+ "StrictMode",
326
+ "LenientMode",
327
+ "set_error_mode",
148
328
  # ========================================================================
149
- "Validator", # PRIMARY: Use for validation
329
+ # DATA CONTRACT SERVICES
330
+ # ========================================================================
331
+ # Validation
332
+ "Validator",
333
+ "ValidatorBuilder",
150
334
  "create_validator",
151
- "QualityCheck", # ⭐ PRIMARY: Use for quality checks
335
+ "ValidationResult",
336
+ "ValidationQualityMetrics",
337
+ "validate_with_store",
338
+ "validate_batch_with_store",
339
+ "validate_with_contract",
340
+ "validate_batch_with_contract",
341
+ "get_model_from_store",
342
+ "get_model_from_contract",
343
+ "validate",
344
+ "validate_batch",
345
+ "validate_input",
346
+ "validate_output",
347
+ "validate_with_contract_decorator",
348
+ # Quality
349
+ "QualityCheck",
152
350
  "QualityCheckOptions",
153
351
  "QualityReport",
154
352
  "QualityThresholds",
155
- "MetadataStoreClient",
156
- # ========================================================================
157
- # TIER 2: CONVENIENCE FUNCTIONS
158
- # ========================================================================
353
+ "QualityMetrics",
354
+ "QualityScore",
355
+ "FieldQualityMetrics",
356
+ "ViolationTracker",
357
+ "ViolationRecord",
358
+ "DataProfiler",
159
359
  # Contract Management
160
360
  "parse_contract",
161
361
  "parse_contract_file",
@@ -163,49 +363,59 @@ __all__ = [
163
363
  "build_contract",
164
364
  "build_contract_from_store",
165
365
  "ContractArtifacts",
166
- # Pydantic Generator (input type helpers)
167
- "from_dict", # Quick: dict → model
168
- "from_file", # Quick: file → model
169
- "from_json", # Quick: JSON string → model
170
- "from_url", # Quick: URL → model
171
- "generate_model", # Advanced: more control
366
+ # Pydantic Generator
367
+ "from_dict",
368
+ "from_file",
369
+ "from_json",
370
+ "from_url",
371
+ "generate_model",
172
372
  "generate_model_file",
173
- # JSON Schema Converter (output type helpers)
174
- "to_dict", # Quick: model → dict
175
- "to_file", # Quick: model → file
176
- "to_json", # Quick: model → JSON string
177
- "model_to_schema", # Advanced: core conversion
178
- # Runtime Validator (data source helpers)
179
- "ValidationResult",
180
- "validate_with_store", # Quick: store → validate
181
- "validate_batch_with_store", # Quick: batch validate with store
182
- "validate_with_contract", # Quick: contract → validate
183
- "validate_batch_with_contract", # Quick: batch validate with contract
184
- "get_model_from_store", # Quick: store → model
185
- "get_model_from_contract", # Quick: contract → model
186
- "validate_input", # Decorator
187
- "validate_output", # Decorator
188
- "validate_with_contract_decorator",
189
- # ========================================================================
190
- # TIER 3: LOW-LEVEL UTILITIES
191
- # ========================================================================
192
- "validate", # Low-level: model → validate
193
- "validate_batch", # Low-level: model → batch validate
194
- # ========================================================================
195
- # METADATA STORE IMPLEMENTATIONS
196
- # ========================================================================
373
+ # JSON Schema Converter
374
+ "to_dict",
375
+ "to_file",
376
+ "to_json",
377
+ "model_to_schema",
378
+ # Metadata Store
379
+ "MetadataStoreClient",
197
380
  "InMemoryMetadataStore",
198
381
  "MongoDBMetadataStore",
199
382
  "PostgresMetadataStore",
200
383
  "RedisMetadataStore",
201
384
  "SQLiteMetadataStore",
385
+ # Protocols
386
+ "MetadataStore",
387
+ "CoercionRegistry",
388
+ "ValidationRegistry",
389
+ "DataValidator",
390
+ # Error handling
391
+ "ErrorMode",
392
+ "ErrorContext",
393
+ "StrictMode",
394
+ "LenientMode",
395
+ "set_error_mode",
202
396
  # ========================================================================
203
- # QUALITY ASSURANCE - Additional utilities
397
+ # QUALITY TRACKING
204
398
  # ========================================================================
205
- "QualityMetrics",
206
- "QualityScore",
207
- "FieldQualityMetrics",
208
- "ViolationTracker",
209
- "ViolationRecord",
210
- "DataProfiler",
399
+ "MetricsCollector",
400
+ "ValidationMetric",
401
+ "MetricsSummary",
402
+ "InMemoryMetricsStore",
403
+ "SQLiteMetricsStore",
404
+ # ========================================================================
405
+ # DOCUMENTATION GENERATION
406
+ # ========================================================================
407
+ "DocsGenerator",
408
+ "generate_docs",
409
+ "MarkdownRenderer",
410
+ "HTMLRenderer",
411
+ # ========================================================================
412
+ # SCHEMA EVOLUTION
413
+ # ========================================================================
414
+ "check_compatibility",
415
+ "compute_diff",
416
+ "CompatibilityResult",
417
+ "SchemaDiff",
418
+ "SchemaChange",
419
+ "ChangeType",
420
+ "CompatibilityMode",
211
421
  ]
@@ -0,0 +1,57 @@
1
+ # Coercion Rules Template
2
+ # Pre-validation data type transformations
3
+ #
4
+ # Usage:
5
+ # Coercion rules transform input data BEFORE Pydantic validation.
6
+ # Useful for handling messy data from external sources.
7
+ #
8
+ # Available coercions:
9
+ # - coerce_to_string : Convert to string
10
+ # - coerce_to_integer : Convert to int (handles "123", 123.0)
11
+ # - coerce_to_float : Convert to float
12
+ # - coerce_to_boolean : Convert to bool ("true"/"false", 0/1)
13
+ # - coerce_to_datetime : Parse datetime strings (ISO format)
14
+ # - coerce_to_date : Parse date strings
15
+ # - coerce_to_uuid : Parse UUID strings
16
+ # - coerce_to_lowercase : Convert string to lowercase
17
+ # - coerce_to_uppercase : Convert string to uppercase
18
+ # - coerce_to_stripped_string : Trim whitespace
19
+ # - coerce_to_list : Wrap single value in list
20
+ # - coerce_to_json : Parse JSON string
21
+ # - coerce_empty_to_null : Convert "" to None
22
+ # - coerce_to_none : Always return None
23
+ #
24
+ # Nullable variants (preserve None values):
25
+ # - coerce_to_nullable_string
26
+ # - coerce_to_nullable_integer
27
+ # - coerce_to_nullable_float
28
+ # - coerce_to_nullable_datetime
29
+ # - coerce_to_nullable_uuid
30
+ # - coerce_to_nullable_json
31
+
32
+ title: my_coercion_rules
33
+ description: Coercion rules for data transformation
34
+ version: "1.0.0"
35
+
36
+ rules:
37
+ # String fields
38
+ id: coerce_to_string
39
+ name: coerce_to_stripped_string
40
+ status: coerce_to_lowercase
41
+
42
+ # Numeric fields
43
+ count: coerce_to_integer
44
+ amount: coerce_to_float
45
+
46
+ # Boolean
47
+ is_active: coerce_to_boolean
48
+
49
+ # Datetime
50
+ created_at: coerce_to_datetime
51
+
52
+ # Nullable fields (use nullable variants)
53
+ notes: coerce_to_nullable_string
54
+ email: coerce_to_nullable_string
55
+
56
+ # UUID
57
+ uuid: coerce_to_uuid
@@ -0,0 +1,122 @@
1
+ # Complete Data Contract Template
2
+ # Combines schema, coercion rules, validation rules, and metadata
3
+ #
4
+ # Usage:
5
+ # from pycharter import parse_contract, validate_with_contract
6
+ #
7
+ # contract = parse_contract(contract_dict) # or parse_contract_file("contract.yaml")
8
+ # result = validate_with_contract(contract_dict, data)
9
+
10
+ schema:
11
+ type: object
12
+ title: User
13
+ version: "1.0.0"
14
+
15
+ properties:
16
+ user_id:
17
+ type: string
18
+ description: Unique user identifier
19
+ minLength: 1
20
+ # PyCharter extension: coercion
21
+ coercion: coerce_to_string
22
+ # PyCharter extension: validations
23
+ validations:
24
+ non_empty_string: null
25
+
26
+ name:
27
+ type: string
28
+ description: User's full name
29
+ minLength: 1
30
+ maxLength: 100
31
+ coercion: coerce_to_stripped_string
32
+ validations:
33
+ non_empty_string: null
34
+ max_length:
35
+ threshold: 100
36
+
37
+ email:
38
+ type: string
39
+ format: email
40
+ description: User email address
41
+ coercion: coerce_to_lowercase
42
+ validations:
43
+ is_email: null
44
+
45
+ age:
46
+ type: integer
47
+ description: User age
48
+ minimum: 0
49
+ maximum: 150
50
+ coercion: coerce_to_integer
51
+ validations:
52
+ greater_than_or_equal_to:
53
+ threshold: 0
54
+ less_than_or_equal_to:
55
+ threshold: 150
56
+
57
+ status:
58
+ type: string
59
+ description: Account status
60
+ enum: [active, inactive, pending]
61
+ coercion: coerce_to_lowercase
62
+ validations:
63
+ only_allow:
64
+ allowed_values: [active, inactive, pending]
65
+
66
+ created_at:
67
+ type: string
68
+ format: date-time
69
+ description: Account creation timestamp
70
+ coercion: coerce_to_datetime
71
+
72
+ # Nullable field example
73
+ notes:
74
+ anyOf:
75
+ - type: string
76
+ maxLength: 500
77
+ - type: "null"
78
+ default: null
79
+ description: Optional notes
80
+ coercion: coerce_to_nullable_string
81
+ validations:
82
+ max_length:
83
+ threshold: 500
84
+
85
+ required:
86
+ - user_id
87
+ - name
88
+ - email
89
+ - status
90
+ - created_at
91
+
92
+ # Contract metadata (ownership and governance nested inside)
93
+ metadata:
94
+ version: "1.0.0"
95
+ description: User data contract
96
+ status: active
97
+ created_at: "2025-01-01T00:00:00Z"
98
+ created_by: data-team
99
+
100
+ # Ownership information (nested in metadata)
101
+ ownership:
102
+ owner: data-team
103
+ team: engineering
104
+
105
+ # Governance rules (nested in metadata)
106
+ governance_rules:
107
+ data_retention:
108
+ days: 365
109
+ reason: Standard user data retention
110
+ pii_fields:
111
+ fields: [email, name]
112
+ sensitivity: confidential
113
+ access_control:
114
+ read: [analytics-team, data-team]
115
+ write: [data-team]
116
+
117
+ # Version tracking (optional - for build_contract_from_store)
118
+ versions:
119
+ schema: "1.0.0"
120
+ coercion_rules: "1.0.0"
121
+ validation_rules: "1.0.0"
122
+ metadata: "1.0.0"
@@ -0,0 +1,68 @@
1
+ # Metadata Template
2
+ # Business and governance metadata for your data contract
3
+ #
4
+ # Usage:
5
+ # Metadata provides context, ownership, and governance information
6
+ # about your data asset. This is separate from the schema itself.
7
+
8
+ # Basic Information
9
+ title: my_entity
10
+ version: "1.0.0"
11
+ status: active
12
+ description: Description of what this data represents
13
+
14
+ # Audit Trail
15
+ created_at: "2025-01-01T00:00:00Z"
16
+ updated_at: "2025-01-01T00:00:00Z"
17
+ created_by: your_username
18
+ updated_by: your_username
19
+
20
+ # Ownership
21
+ business_owners:
22
+ - team-name
23
+ - owner-email@company.com
24
+
25
+ # Domain Classification
26
+ domain: domain_name
27
+ # domains: [domain1, domain2] # Alternative: multiple domains
28
+
29
+ # Data Lineage
30
+ pulls_from:
31
+ - source_system_1
32
+ - source_system_2
33
+ pushes_to:
34
+ - destination_system_1
35
+ system_sources:
36
+ - origin_system
37
+
38
+ # Data Quality
39
+ data_quality:
40
+ accuracy: 0.0
41
+ monitoring_enabled: false
42
+ sla: null
43
+ total_records: 0
44
+ last_updated: "2025-01-01T00:00:00Z"
45
+
46
+ # Governance Rules
47
+ governance_rules:
48
+ data_retention:
49
+ days: 365
50
+ reason: Standard retention policy
51
+ pii_fields:
52
+ fields: []
53
+ sensitivity: internal # internal, confidential, restricted, public
54
+ access_control:
55
+ read:
56
+ - data-team
57
+ - analytics-team
58
+ write:
59
+ - data-team
60
+
61
+ # Changelog
62
+ changelog:
63
+ - version: "1.0.0"
64
+ date: "2025-01-01T00:00:00Z"
65
+ author: your_username
66
+ type: initial
67
+ changes:
68
+ - Initial contract creation