mainsequence-metatable 0.1.4.dev5__py3-none-any.whl → 0.1.5.dev6__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 (282) hide show
  1. api/app/configuration.py +1 -2
  2. api/app/main.py +0 -2
  3. api/app/routes/managed_finalize.py +1 -1
  4. api/app/routes/migration_connection.py +71 -19
  5. api/app/routes/run_logs.py +34 -1
  6. api/app/routes/runtime_context.py +0 -1
  7. api/app/routes/update_crud.py +7 -3
  8. api/backend/backends/catalog.py +0 -24
  9. api/backend/backends/contracts.py +0 -2
  10. api/backend/backends/hosted.py +0 -13
  11. api/backend/backends/migration_connection.py +62 -0
  12. api/backend/integrations/run_logs.py +3 -3
  13. api/backend/persistence/run_graphs.py +15 -4
  14. api/metatables/configuration.yaml +0 -2
  15. examples/README.md +1 -1
  16. examples/local_app/README.md +5 -7
  17. examples/local_app/migrations/__init__.py +1 -1
  18. examples/scripts/setup_metatables.py +2 -12
  19. examples/tutorial/README.md +67 -20
  20. examples/tutorial/__main__.py +12 -6
  21. examples/tutorial/frames.py +32 -1
  22. examples/tutorial/migrations/registry.py +5 -3
  23. examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  24. examples/tutorial/operations.py +9 -1
  25. examples/tutorial/tables.py +37 -1
  26. examples/tutorial/updaters.py +86 -9
  27. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/METADATA +1 -1
  28. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/RECORD +279 -188
  29. metatables/_client_skills/metatables-local-development/SKILL.md +7 -8
  30. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
  31. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
  32. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
  33. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
  34. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
  35. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0009-shared-credential-store.md +7 -0
  36. metatables/_client_skills/metatables-local-development/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
  37. metatables/_client_skills/metatables-local-development/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
  38. metatables/_client_skills/metatables-local-development/references/docs/adr/index.md +3 -2
  39. metatables/_client_skills/metatables-local-development/references/docs/api/openapi.json +164 -63
  40. metatables/_client_skills/metatables-local-development/references/docs/api/reference.md +1 -1
  41. metatables/_client_skills/metatables-local-development/references/docs/api/time-index-and-updates.md +11 -4
  42. metatables/_client_skills/metatables-local-development/references/docs/client/define-and-migrate-tables.md +39 -25
  43. metatables/_client_skills/metatables-local-development/references/docs/client/installation-and-connection.md +12 -6
  44. metatables/_client_skills/metatables-local-development/references/docs/client/query-and-mutate.md +4 -0
  45. metatables/_client_skills/metatables-local-development/references/docs/client/tutorial.md +86 -36
  46. metatables/_client_skills/metatables-local-development/references/docs/client/upgrade-legacy-app.md +157 -0
  47. metatables/_client_skills/metatables-local-development/references/docs/concepts/architecture.md +6 -4
  48. metatables/_client_skills/metatables-local-development/references/docs/concepts/runs-and-execution-graphs.md +37 -18
  49. metatables/_client_skills/metatables-local-development/references/docs/contributing/releasing.md +3 -3
  50. metatables/_client_skills/metatables-local-development/references/docs/examples/README.md +1 -1
  51. metatables/_client_skills/metatables-local-development/references/docs/examples/local_app/README.md +5 -7
  52. metatables/_client_skills/metatables-local-development/references/docs/examples/local_app/migrations/__init__.py +1 -1
  53. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/README.md +67 -20
  54. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/frames.py +32 -1
  55. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/migrations/registry.py +5 -3
  56. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  57. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/operations.py +9 -1
  58. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/tables.py +37 -1
  59. metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/updaters.py +86 -9
  60. metatables/_client_skills/metatables-local-development/references/docs/operations/catalog-migrations.md +2 -2
  61. metatables/_client_skills/metatables-local-development/references/docs/operations/configuration.md +6 -12
  62. metatables/_client_skills/metatables-local-development/references/docs/operations/local-runtime.md +4 -3
  63. metatables/_client_skills/metatables-local-development/references/docs/operations/run-history.md +30 -17
  64. metatables/_client_skills/metatables-local-development/references/docs/operations/run-logs.md +4 -1
  65. metatables/_client_skills/metatables-local-development/references/docs/reference/capabilities.md +8 -8
  66. metatables/_client_skills/metatables-local-development/references/docs/security/index.md +15 -13
  67. metatables/_client_skills/metatables-local-development/references/docs/security/permissions.md +8 -6
  68. metatables/_client_skills/metatables-local-development/references/examples/local_app/README.md +5 -7
  69. metatables/_client_skills/metatables-local-development/references/examples/local_app/migrations/__init__.py +1 -1
  70. metatables/_client_skills/metatables-meta-tables/SKILL.md +20 -5
  71. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
  72. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
  73. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
  74. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
  75. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
  76. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0009-shared-credential-store.md +7 -0
  77. metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
  78. metatables/_client_skills/metatables-meta-tables/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
  79. metatables/_client_skills/metatables-meta-tables/references/docs/adr/index.md +3 -2
  80. metatables/_client_skills/metatables-meta-tables/references/docs/api/openapi.json +164 -63
  81. metatables/_client_skills/metatables-meta-tables/references/docs/api/reference.md +1 -1
  82. metatables/_client_skills/metatables-meta-tables/references/docs/api/time-index-and-updates.md +11 -4
  83. metatables/_client_skills/metatables-meta-tables/references/docs/client/define-and-migrate-tables.md +39 -25
  84. metatables/_client_skills/metatables-meta-tables/references/docs/client/installation-and-connection.md +12 -6
  85. metatables/_client_skills/metatables-meta-tables/references/docs/client/query-and-mutate.md +4 -0
  86. metatables/_client_skills/metatables-meta-tables/references/docs/client/tutorial.md +86 -36
  87. metatables/_client_skills/metatables-meta-tables/references/docs/client/upgrade-legacy-app.md +157 -0
  88. metatables/_client_skills/metatables-meta-tables/references/docs/concepts/architecture.md +6 -4
  89. metatables/_client_skills/metatables-meta-tables/references/docs/concepts/runs-and-execution-graphs.md +37 -18
  90. metatables/_client_skills/metatables-meta-tables/references/docs/contributing/releasing.md +3 -3
  91. metatables/_client_skills/metatables-meta-tables/references/docs/examples/README.md +1 -1
  92. metatables/_client_skills/metatables-meta-tables/references/docs/examples/local_app/README.md +5 -7
  93. metatables/_client_skills/metatables-meta-tables/references/docs/examples/local_app/migrations/__init__.py +1 -1
  94. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/README.md +67 -20
  95. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/frames.py +32 -1
  96. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/migrations/registry.py +5 -3
  97. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  98. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/operations.py +9 -1
  99. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/tables.py +37 -1
  100. metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/updaters.py +86 -9
  101. metatables/_client_skills/metatables-meta-tables/references/docs/operations/catalog-migrations.md +2 -2
  102. metatables/_client_skills/metatables-meta-tables/references/docs/operations/configuration.md +6 -12
  103. metatables/_client_skills/metatables-meta-tables/references/docs/operations/local-runtime.md +4 -3
  104. metatables/_client_skills/metatables-meta-tables/references/docs/operations/run-history.md +30 -17
  105. metatables/_client_skills/metatables-meta-tables/references/docs/operations/run-logs.md +4 -1
  106. metatables/_client_skills/metatables-meta-tables/references/docs/reference/capabilities.md +8 -8
  107. metatables/_client_skills/metatables-meta-tables/references/docs/security/index.md +15 -13
  108. metatables/_client_skills/metatables-meta-tables/references/docs/security/permissions.md +8 -6
  109. metatables/_client_skills/metatables-migrations/SKILL.md +36 -32
  110. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
  111. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
  112. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
  113. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
  114. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
  115. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0009-shared-credential-store.md +7 -0
  116. metatables/_client_skills/metatables-migrations/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
  117. metatables/_client_skills/metatables-migrations/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
  118. metatables/_client_skills/metatables-migrations/references/docs/adr/index.md +3 -2
  119. metatables/_client_skills/metatables-migrations/references/docs/api/openapi.json +164 -63
  120. metatables/_client_skills/metatables-migrations/references/docs/api/reference.md +1 -1
  121. metatables/_client_skills/metatables-migrations/references/docs/api/time-index-and-updates.md +11 -4
  122. metatables/_client_skills/metatables-migrations/references/docs/client/define-and-migrate-tables.md +39 -25
  123. metatables/_client_skills/metatables-migrations/references/docs/client/installation-and-connection.md +12 -6
  124. metatables/_client_skills/metatables-migrations/references/docs/client/query-and-mutate.md +4 -0
  125. metatables/_client_skills/metatables-migrations/references/docs/client/tutorial.md +86 -36
  126. metatables/_client_skills/metatables-migrations/references/docs/client/upgrade-legacy-app.md +157 -0
  127. metatables/_client_skills/metatables-migrations/references/docs/concepts/architecture.md +6 -4
  128. metatables/_client_skills/metatables-migrations/references/docs/concepts/runs-and-execution-graphs.md +37 -18
  129. metatables/_client_skills/metatables-migrations/references/docs/contributing/releasing.md +3 -3
  130. metatables/_client_skills/metatables-migrations/references/docs/examples/README.md +1 -1
  131. metatables/_client_skills/metatables-migrations/references/docs/examples/local_app/README.md +5 -7
  132. metatables/_client_skills/metatables-migrations/references/docs/examples/local_app/migrations/__init__.py +1 -1
  133. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/README.md +67 -20
  134. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/frames.py +32 -1
  135. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/migrations/registry.py +5 -3
  136. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  137. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/operations.py +9 -1
  138. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/tables.py +37 -1
  139. metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/updaters.py +86 -9
  140. metatables/_client_skills/metatables-migrations/references/docs/operations/catalog-migrations.md +2 -2
  141. metatables/_client_skills/metatables-migrations/references/docs/operations/configuration.md +6 -12
  142. metatables/_client_skills/metatables-migrations/references/docs/operations/local-runtime.md +4 -3
  143. metatables/_client_skills/metatables-migrations/references/docs/operations/run-history.md +30 -17
  144. metatables/_client_skills/metatables-migrations/references/docs/operations/run-logs.md +4 -1
  145. metatables/_client_skills/metatables-migrations/references/docs/reference/capabilities.md +8 -8
  146. metatables/_client_skills/metatables-migrations/references/docs/security/index.md +15 -13
  147. metatables/_client_skills/metatables-migrations/references/docs/security/permissions.md +8 -6
  148. metatables/_client_skills/metatables-migrations/references/examples/scripts/setup_metatables.py +2 -12
  149. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
  150. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
  151. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
  152. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
  153. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
  154. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0009-shared-credential-store.md +7 -0
  155. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
  156. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
  157. metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/index.md +3 -2
  158. metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/openapi.json +164 -63
  159. metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/reference.md +1 -1
  160. metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/time-index-and-updates.md +11 -4
  161. metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/define-and-migrate-tables.md +39 -25
  162. metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/installation-and-connection.md +12 -6
  163. metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/query-and-mutate.md +4 -0
  164. metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/tutorial.md +86 -36
  165. metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/upgrade-legacy-app.md +157 -0
  166. metatables/_client_skills/metatables-time-index-table-updates/references/docs/concepts/architecture.md +6 -4
  167. metatables/_client_skills/metatables-time-index-table-updates/references/docs/concepts/runs-and-execution-graphs.md +37 -18
  168. metatables/_client_skills/metatables-time-index-table-updates/references/docs/contributing/releasing.md +3 -3
  169. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/README.md +1 -1
  170. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/local_app/README.md +5 -7
  171. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/local_app/migrations/__init__.py +1 -1
  172. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/README.md +67 -20
  173. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/frames.py +32 -1
  174. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/migrations/registry.py +5 -3
  175. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  176. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/operations.py +9 -1
  177. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/tables.py +37 -1
  178. metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/updaters.py +86 -9
  179. metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/catalog-migrations.md +2 -2
  180. metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/configuration.md +6 -12
  181. metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/local-runtime.md +4 -3
  182. metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/run-history.md +30 -17
  183. metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/run-logs.md +4 -1
  184. metatables/_client_skills/metatables-time-index-table-updates/references/docs/reference/capabilities.md +8 -8
  185. metatables/_client_skills/metatables-time-index-table-updates/references/docs/security/index.md +15 -13
  186. metatables/_client_skills/metatables-time-index-table-updates/references/docs/security/permissions.md +8 -6
  187. metatables/_client_skills/metatables-upgrade-legacy-app/SKILL.md +91 -0
  188. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +656 -0
  189. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0002-application-administration-and-table-ownership.md +374 -0
  190. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0004-approved-application-migrations.md +66 -0
  191. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0005-run-logs-and-local-file-capture.md +237 -0
  192. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0006-historical-run-graphs.md +288 -0
  193. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-database-enforced-table-access.md +294 -0
  194. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-database-roles-and-privileges.svg +120 -0
  195. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-query-enforcement-path.svg +76 -0
  196. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +430 -0
  197. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0009-shared-credential-store.md +196 -0
  198. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0010-import-external-tables-and-views.md +605 -0
  199. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0012-bounded-data-transfer-and-safe-retries.md +428 -0
  200. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
  201. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/client/0003-api-endpoint-resolution.md +236 -0
  202. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +301 -0
  203. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/index.md +36 -0
  204. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/authentication-and-errors.md +75 -0
  205. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/data-sources.md +198 -0
  206. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/openapi.json +9853 -0
  207. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/reference.md +118 -0
  208. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/time-index-and-updates.md +110 -0
  209. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/assets/diagrams/local-client-experience.svg +91 -0
  210. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/bounded-transfers.md +153 -0
  211. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/build-an-updater.md +58 -0
  212. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/define-and-migrate-tables.md +102 -0
  213. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/installation-and-connection.md +177 -0
  214. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/query-and-mutate.md +86 -0
  215. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/read-existing-time-index-tables.md +36 -0
  216. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/tutorial.md +235 -0
  217. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/upgrade-legacy-app.md +157 -0
  218. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/architecture.md +92 -0
  219. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/data-sources.md +162 -0
  220. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/permissions-namespaces-labels.md +41 -0
  221. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/runs-and-execution-graphs.md +134 -0
  222. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/table-contracts-and-lifecycle.md +58 -0
  223. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/time-index-tables-and-updates.md +60 -0
  224. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/database-backends.md +82 -0
  225. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/documentation.md +76 -0
  226. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/releasing.md +155 -0
  227. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/testing.md +136 -0
  228. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/README.md +34 -0
  229. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/bounded_reader.py +12 -0
  230. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/README.md +27 -0
  231. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/mssql.json +16 -0
  232. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/mysql.json +16 -0
  233. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/postgresql.json +15 -0
  234. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/external_table.py +20 -0
  235. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/README.md +53 -0
  236. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/migrations/__init__.py +21 -0
  237. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/tables.py +20 -0
  238. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/query.py +19 -0
  239. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/quickstart.py +17 -0
  240. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/reader.py +12 -0
  241. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tables.py +49 -0
  242. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/README.md +129 -0
  243. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/data/README.md +13 -0
  244. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/data/yahoo_spy_qqq_iwm_2026-06-15_2026-07-17.csv +70 -0
  245. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/frames.py +79 -0
  246. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/__init__.py +29 -0
  247. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/registry.py +11 -0
  248. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0001_create_market_tutorial_tables.py +81 -0
  249. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
  250. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/operations.py +75 -0
  251. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/tables.py +150 -0
  252. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/updaters.py +172 -0
  253. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/updater.py +42 -0
  254. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/catalog-migrations.md +150 -0
  255. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/configuration.md +56 -0
  256. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/hosted-runtime.md +100 -0
  257. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/local-runtime.md +192 -0
  258. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/recovery-and-observability.md +66 -0
  259. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/run-history.md +144 -0
  260. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/run-logs.md +131 -0
  261. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/reference/capabilities.md +307 -0
  262. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/index.md +174 -0
  263. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/ownership-and-sharing.md +145 -0
  264. metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/permissions.md +107 -0
  265. metatables/cli/app.py +2 -3
  266. metatables/cli/migrations.py +51 -88
  267. metatables/cli/project.py +1 -11
  268. metatables/migrations/__init__.py +14 -3
  269. metatables/migrations/connection.py +75 -0
  270. metatables/migrations/env.py +7 -33
  271. metatables/migrations/runner.py +152 -0
  272. metatables/migrations/tls.py +25 -7
  273. metatables/models.py +7 -2
  274. metatables/runtime.py +6 -6
  275. metatables/runtime_contract.py +0 -1
  276. api/app/routes/application_migrations.py +0 -170
  277. metatables/_client_skills/metatables-migrations/references/docs/api/tables-and-migrations.md +0 -156
  278. metatables/_client_skills/metatables-migrations/references/docs/client/register-existing-tables.md +0 -109
  279. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/WHEEL +0 -0
  280. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/entry_points.txt +0 -0
  281. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/licenses/LICENSE +0 -0
  282. {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/top_level.txt +0 -0
api/app/configuration.py CHANGED
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from typing import Literal
5
5
 
6
6
  import yaml
7
- from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
7
+ from pydantic import BaseModel, ConfigDict, Field, StrictBool
8
8
 
9
9
 
10
10
  class LocalCredentialConfiguration(BaseModel):
@@ -16,7 +16,6 @@ class LocalCredentialConfiguration(BaseModel):
16
16
  class DeploymentConfiguration(BaseModel):
17
17
  model_config = ConfigDict(extra="forbid", frozen=True)
18
18
  local_mode_available: StrictBool = False
19
- application_migration_providers: dict[StrictStr, StrictStr] = Field(default_factory=dict)
20
19
  local_credentials: LocalCredentialConfiguration = Field(default_factory=LocalCredentialConfiguration)
21
20
 
22
21
  @classmethod
api/app/main.py CHANGED
@@ -10,7 +10,6 @@ from sqlalchemy.orm import Session
10
10
 
11
11
  from api.app.auth.boundary import trusted_actor_facts
12
12
  from api.app.auth.local_actor import catalog_session
13
- from api.app.routes.application_migrations import router as application_migrations_router
14
13
  from api.app.routes.column_search import router as column_search_router
15
14
  from api.app.routes.contract_validation import router as contract_validation_router
16
15
  from api.app.routes.data_sources import router as data_sources_router
@@ -189,7 +188,6 @@ def create_app(config: RuntimeConfig | None = None) -> FastAPI:
189
188
  service.include_router(managed_finalize_router)
190
189
  service.include_router(table_sql_router)
191
190
  service.include_router(migration_connection_router)
192
- service.include_router(application_migrations_router)
193
191
  service.include_router(table_import_router)
194
192
  service.include_router(source_relations_router)
195
193
  service.include_router(table_registration_router)
@@ -203,7 +203,7 @@ def finalize_managed(
203
203
  table.introspection_snapshot = snapshot
204
204
  table.provisioning_status = "active"
205
205
  table.protect_from_deletion = True
206
- if payload.alembic_revision:
206
+ if "alembic_revision" in payload.model_fields_set:
207
207
  table.alembic_revision = payload.alembic_revision
208
208
  if version_root is not None and uid != version_root:
209
209
  table.alembic_version_meta_table_uid = version_root
@@ -1,41 +1,93 @@
1
- """Direct database migration connections are disabled by the security boundary."""
1
+ """Resolve the selected environment connection for application-owned migrations."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import Any, Literal
5
6
  from uuid import UUID
6
7
 
7
- from fastapi import APIRouter, Depends, HTTPException
8
+ from fastapi import APIRouter, Depends, HTTPException, Request, Response
8
9
  from pydantic import BaseModel, ConfigDict, Field
10
+ from sqlalchemy import select
9
11
  from sqlalchemy.orm import Session
10
12
 
11
13
  from api.app.auth.boundary import trusted_actor_facts
12
14
  from api.app.auth.local_actor import catalog_session
15
+ from api.app.routes.table_introspection import data_source_provider
13
16
  from api.app.routes.table_sql import authorized_table
17
+ from api.backend.backends.migration_connection import migration_connection_description
18
+ from api.backend.domain.data_source_rules import (
19
+ DataSourceAdmissionError,
20
+ require_data_source_access,
21
+ )
14
22
  from api.backend.domain.permission_rules import TrustedActorFacts
23
+ from api.backend.integrations.runtime_data_sources import DataSourceIntegrationError
24
+ from api.backend.persistence.grants import GrantRepository
15
25
  from api.backend.persistence.locking import lock_catalog
26
+ from api.backend.persistence.models import MetaTable
16
27
 
17
- router = APIRouter(prefix='/meta-tables', tags=['MetaTables'])
28
+ router = APIRouter(prefix="/meta-tables", tags=["MetaTables"])
18
29
 
19
30
 
20
31
  class MigrationRequest(BaseModel):
21
- model_config = ConfigDict(extra='forbid')
22
- purpose: Literal['schema_migration'] = 'schema_migration'
23
- package: str = ''
24
- migration_namespace: str = ''
25
- migration_provider_key: str = ''
32
+ model_config = ConfigDict(extra="forbid")
33
+ purpose: Literal["schema_migration"] = "schema_migration"
34
+ package: str = ""
35
+ migration_namespace: str = ""
36
+ migration_provider_key: str = ""
26
37
  ttl_seconds: int = Field(default=900, ge=60, le=3600)
27
38
  code_repository_context: dict[str, Any] | None = None
28
39
 
29
40
 
30
- @router.post('/{table_uid}/migration-connection/', responses={409: {
31
- 'description': 'Direct connections are disabled pending API-mediated migrations.'}})
32
- def migration_connection(table_uid: UUID, payload: MigrationRequest,
33
- actor: TrustedActorFacts = Depends(trusted_actor_facts),
34
- session: Session = Depends(catalog_session)):
41
+ @router.post("/{table_uid}/migration-connection/")
42
+ def migration_connection(
43
+ table_uid: UUID,
44
+ payload: MigrationRequest,
45
+ request: Request,
46
+ response: Response,
47
+ actor: TrustedActorFacts = Depends(trusted_actor_facts),
48
+ session: Session = Depends(catalog_session),
49
+ sources=Depends(data_source_provider),
50
+ ):
35
51
  lock_catalog(session)
36
- authorized_table(session, actor, table_uid, edit=True, reserved_policy='reconcile')
37
- # No role issuance, Secret lookup, SQLite path, DSN, or local-mode exception.
38
- raise HTTPException(409, {
39
- 'code': 'direct_migration_connections_disabled',
40
- 'detail': 'Application-table migrations require API-mediated execution, which is not available yet. Direct database connections are disabled.',
41
- })
52
+ table = authorized_table(session, actor, table_uid, edit=True, reserved_policy="reconcile")
53
+ if (
54
+ table.management_mode != "platform_managed"
55
+ or table.schema_management_mode != "alembic_managed"
56
+ ):
57
+ raise HTTPException(409, "MetaTable is not Alembic managed.")
58
+ for field, value in [
59
+ ("migration_package", payload.package),
60
+ ("migration_namespace", payload.migration_namespace),
61
+ ("migration_provider_key", payload.migration_provider_key),
62
+ ]:
63
+ if value and value != getattr(table, field):
64
+ raise HTTPException(409, "Migration provider identity does not match.")
65
+ root_uid = table.alembic_version_meta_table_uid or table.uid
66
+ tables = list(
67
+ session.scalars(
68
+ select(MetaTable).where(
69
+ (MetaTable.uid == root_uid) | (MetaTable.alembic_version_meta_table_uid == root_uid)
70
+ )
71
+ )
72
+ )
73
+ if any(
74
+ not GrantRepository(session).may_access_table(table_uid=item.uid, actor=actor, edit=True)
75
+ for item in tables
76
+ ):
77
+ raise HTTPException(403, "Writer access is required for every provider catalog table.")
78
+ try:
79
+ source = sources.get(table.data_source_uid)
80
+ require_data_source_access(source, access="write")
81
+ result = migration_connection_description(source)
82
+ except DataSourceAdmissionError as exc:
83
+ raise HTTPException(exc.status_code, exc.code) from exc
84
+ except DataSourceIntegrationError as exc:
85
+ raise HTTPException(503, "DataSource is unavailable.") from exc
86
+ # Include removed provider models so finalization reconciles dropped tables.
87
+ result["meta_table_uids"] = [str(item.uid) for item in tables if item.uid != root_uid]
88
+ control = getattr(request.app.state, "runtime_control", None)
89
+ if control is not None:
90
+ result.update(control.hold_migration(actor.user_uid))
91
+ response.headers["Cache-Control"] = "no-store"
92
+ response.headers["Pragma"] = "no-cache"
93
+ return result
@@ -14,7 +14,9 @@ from api.app.auth.local_actor import catalog_session
14
14
  from api.app.routes.update_crud import admitted_update
15
15
  from api.backend.domain.permission_rules import TrustedActorFacts
16
16
  from api.backend.integrations.run_logs import _query, read_logs
17
- from api.backend.persistence.models import UpdateRun
17
+ from api.backend.persistence.grants import GrantRepository
18
+ from api.backend.persistence.models import MetaTable, UpdateNode, UpdateRun
19
+ from api.backend.persistence.run_graphs import MAX_NODES
18
20
  from metatables.log_contract import LogPage
19
21
 
20
22
  router = APIRouter(tags=["TimeIndexTableUpdates"])
@@ -49,6 +51,37 @@ def run_logs(
49
51
  return read_logs(state, state.log_snapshots, [run], request.query_params, scope=str(run_uid))
50
52
 
51
53
 
54
+ @router.get("/table-update-runs/{run_uid}/invocation-logs/", response_model=LogPage)
55
+ def invocation_logs(
56
+ run_uid: UUID,
57
+ request: Request,
58
+ query: Annotated[LogQuery, Query()],
59
+ actor: TrustedActorFacts = Depends(trusted_actor_facts),
60
+ session: Session = Depends(catalog_session),
61
+ ):
62
+ """One time-ordered page across the readable attempts of the selected run's invocation.
63
+
64
+ `run_uid` narrows the page to one attempt of that invocation. A run without a
65
+ saved graph is its own invocation.
66
+ """
67
+ run = session.get(UpdateRun, run_uid)
68
+ if run is None:
69
+ raise HTTPException(404, "Run not found.")
70
+ admitted_update(session, actor, run.update_uid)
71
+ member = UpdateRun.root_run_uid == run.root_run_uid if run.root_run_uid else UpdateRun.uid == run.uid
72
+ statement = select(UpdateRun).join(UpdateNode, UpdateNode.uid == UpdateRun.update_uid).join(
73
+ MetaTable, MetaTable.uid == UpdateNode.output_table_uid
74
+ ).where(member, GrantRepository.table_access_predicate(actor))
75
+ if query.run_uid is not None:
76
+ statement = statement.where(UpdateRun.uid == query.run_uid)
77
+ runs = list(session.scalars(statement.order_by(UpdateRun.started_at, UpdateRun.uid)))
78
+ if not runs:
79
+ raise HTTPException(422, "Run filter is not a readable attempt of this invocation.")
80
+ state = request.app.state.runtime
81
+ return read_logs(state, state.log_snapshots, runs, request.query_params,
82
+ scope=f"invocation:{run.root_run_uid or run.uid}", max_runs=MAX_NODES)
83
+
84
+
52
85
  @router.get("/time-index-table-updates/{update_uid}/logs/", response_model=LogPage)
53
86
  def update_logs(
54
87
  update_uid: UUID,
@@ -74,7 +74,6 @@ def runtime_context(
74
74
 
75
75
  result = {
76
76
  "credential_store": state.credential_store.descriptor(),
77
- "application_migrations_available": bool(getattr(deployment, "application_migration_providers", {})),
78
77
  "is_admin": caller.is_admin,
79
78
  "user_uid": str(caller.user_uid),
80
79
  "local_mode": state.config.local_mode,
@@ -16,6 +16,7 @@ from api.app.auth.local_actor import catalog_session
16
16
  from api.app.routes.table_response import project_table_response
17
17
  from api.app.routes.update_runs import _run_payload
18
18
  from api.backend.domain.permission_rules import TrustedActorFacts
19
+ from api.backend.persistence import run_graphs
19
20
  from api.backend.persistence.grants import GrantRepository
20
21
  from api.backend.persistence.labels import LabelRepository
21
22
  from api.backend.persistence.models import (
@@ -207,7 +208,7 @@ def list_runs(request: Request, actor: TrustedActorFacts = Depends(trusted_actor
207
208
  item = _run_payload(row)
208
209
  graph = session.get(UpdateRunGraph, row.root_run_uid) if row.root_run_uid else None
209
210
  saved = next((node for node in graph.snapshot['nodes'] if node['id'] == f'update:{row.update_uid}'), None) if graph else None
210
- item['updater_label'] = saved['label'] if saved else session.get(UpdateNode, row.update_uid).update_hash
211
+ item['updater_label'] = saved['label'] if saved else run_graphs.updater_label(session.get(UpdateNode, row.update_uid))
211
212
  item['graph_availability'] = 'available' if graph else 'unavailable'
212
213
  if graph is None:
213
214
  item['root_run_uid'] = None
@@ -220,9 +221,12 @@ def get_run(run_uid: UUID, actor: TrustedActorFacts = Depends(trusted_actor_fact
220
221
  run = session.get(UpdateRun, run_uid)
221
222
  if run is None:
222
223
  raise HTTPException(404, 'Run not found.')
223
- admitted_update(session, actor, run.update_uid)
224
+ update = admitted_update(session, actor, run.update_uid)
224
225
  result = _run_payload(run)
225
- if run.root_run_uid is None or session.get(UpdateRunGraph, run.root_run_uid) is None:
226
+ graph = session.get(UpdateRunGraph, run.root_run_uid) if run.root_run_uid else None
227
+ saved = next((node for node in graph.snapshot['nodes'] if node['id'] == f'update:{run.update_uid}'), None) if graph else None
228
+ result['updater_label'] = saved['label'] if saved else run_graphs.updater_label(update)
229
+ if graph is None:
226
230
  result.update(root_run_uid=None, graph_availability='unavailable')
227
231
  return result
228
232
 
@@ -167,24 +167,11 @@ class PostgreSQLCatalog:
167
167
  "SELECT pg_advisory_unlock(hashtext('metatables:bootstrap'))"
168
168
  )
169
169
 
170
- @contextmanager
171
- def migration_guard(self, connection):
172
- from sqlalchemy.orm import Session
173
-
174
- with Session(bind=connection.engine) as session:
175
- yield session
176
-
177
170
  @contextmanager
178
171
  def migration_connection(self, engine):
179
172
  with engine.connect() as connection, connection.begin():
180
173
  yield connection
181
174
 
182
- @contextmanager
183
- def application_migration_connection(self, engine):
184
- with self.migration_connection(engine) as connection:
185
- connection.exec_driver_sql("SET LOCAL search_path TO public")
186
- yield connection
187
-
188
175
 
189
176
  class SQLiteCatalog(PostgreSQLCatalog):
190
177
  default_schema = None
@@ -192,17 +179,6 @@ class SQLiteCatalog(PostgreSQLCatalog):
192
179
  def initialize_namespace(self, connection):
193
180
  pass
194
181
 
195
- @contextmanager
196
- def migration_guard(self, connection):
197
- from sqlalchemy.orm import Session
198
- with Session(bind=connection) as session:
199
- yield session
200
-
201
- @contextmanager
202
- def application_migration_connection(self, engine):
203
- with self.migration_connection(engine) as connection:
204
- yield connection
205
-
206
182
  def create_engine(self, url, *, native_values=False):
207
183
  options = {"timeout": 30, "check_same_thread": False}
208
184
  if native_values:
@@ -173,8 +173,6 @@ class CatalogBackend(Protocol):
173
173
  def schema(self, name: str | None) -> str | None: ...
174
174
  def bootstrap_lock(self, engine: Engine) -> AbstractContextManager[None]: ...
175
175
  def migration_connection(self, engine: Engine) -> AbstractContextManager[Connection]: ...
176
- def application_migration_connection(self, engine: Engine) -> AbstractContextManager[Connection]: ...
177
- def migration_guard(self, connection: Connection) -> AbstractContextManager[Session]: ...
178
176
  def schema_object_state(self, connection: Connection, name: str) -> Any: ...
179
177
  def column_type_matches(self, expected: Any, actual: Any, dialect: Any) -> bool: ...
180
178
  def index_names(self, inspector: Any, table: str) -> set[str]: ...
@@ -21,11 +21,6 @@ class HostedCatalog(PostgreSQLCatalog):
21
21
  def initialize_namespace(self, connection):
22
22
  pass
23
23
 
24
- @contextmanager
25
- def application_migration_connection(self, engine):
26
- with self.migration_connection(engine) as connection:
27
- yield connection
28
-
29
24
  def registration_schema(self, source, name):
30
25
  return self.physical_schema(source, name)
31
26
 
@@ -126,14 +121,6 @@ class MySQLCatalog(HostedCatalog):
126
121
  ]:
127
122
  raise CatalogConfigurationError("catalog_index_definition_drift")
128
123
 
129
- @contextmanager
130
- def migration_guard(self, connection):
131
- from sqlalchemy.orm import Session
132
-
133
- # Hold catalog admission while implicit DDL commits use a separate connection.
134
- with Session(connection.engine) as session:
135
- yield session
136
-
137
124
  @contextmanager
138
125
  def migration_connection(self, engine):
139
126
  # DDL implicitly commits on MySQL. The shared bootstrap journal records
@@ -0,0 +1,62 @@
1
+ """Describe the configured runtime connection for application-owned Alembic.
2
+
3
+ DDL authority belongs to the configured database login. This does not create a
4
+ role or claim that a direct database connection enforces catalog table grants.
5
+ """
6
+
7
+ from sqlalchemy.engine import URL
8
+
9
+ from api.backend.backends.registry import engine_descriptor
10
+
11
+
12
+ def migration_connection_description(source):
13
+ settings = source.connection
14
+ dialect = engine_descriptor(source.class_type).dialect
15
+ tls = {}
16
+ if dialect == "sqlite":
17
+ url = URL.create("sqlite", database=str(settings.path))
18
+ else:
19
+ query = {}
20
+ driver = {
21
+ "postgresql": "postgresql+psycopg2",
22
+ "mysql": "mysql+pymysql",
23
+ "mssql": "mssql+pyodbc",
24
+ }[dialect]
25
+ if dialect == "postgresql":
26
+ query = {"sslmode": settings.ssl_mode, "connect_timeout": "10"}
27
+ elif dialect == "mysql":
28
+ query = {"charset": settings.default_charset or "utf8mb4"}
29
+ else:
30
+ query = {
31
+ "driver": "ODBC Driver 18 for SQL Server",
32
+ "Encrypt": "yes" if settings.encrypt else "no",
33
+ "TrustServerCertificate": "yes" if settings.trust_server_certificate else "no",
34
+ }
35
+ if dialect in {"postgresql", "mysql"}:
36
+ tls = {
37
+ "ssl_mode": settings.ssl_mode,
38
+ "ca_certificate": settings.tls_ca_certificate,
39
+ "client_certificate": settings.tls_client_certificate,
40
+ "client_key": settings.tls_client_key,
41
+ }
42
+ url = URL.create(
43
+ driver,
44
+ username=settings.database_user,
45
+ password=settings.password,
46
+ host=settings.host,
47
+ port=settings.port,
48
+ database=settings.database_name,
49
+ query=query,
50
+ )
51
+ return {
52
+ "ok": True,
53
+ "data_source_uid": str(source.uid),
54
+ "dialect": dialect,
55
+ "credential_kind": "configured_runtime_connection",
56
+ "role_name": None,
57
+ "owner_role_name": None,
58
+ "expires_at": None,
59
+ "uri": url.render_as_string(hide_password=False),
60
+ "tls": tls,
61
+ "default_schema": settings.default_schema,
62
+ }
@@ -151,7 +151,7 @@ def _hosted(run, capture, query, start, end, budget, jobs):
151
151
  return rows, "error", bool(rows)
152
152
 
153
153
 
154
- def read_logs(state, cache, runs, params, *, scope):
154
+ def read_logs(state, cache, runs, params, *, scope, max_runs=MAX_RUNS):
155
155
  query = _query(params)
156
156
  token = params.get("cursor")
157
157
  signature = (storage_key(state), scope, query)
@@ -192,9 +192,9 @@ def read_logs(state, cache, runs, params, *, scope):
192
192
  )
193
193
 
194
194
  rows, statuses, segments, captures = [], {}, [], []
195
- budget, hosted_budget, truncated = [0], [0], len(runs) > MAX_RUNS
195
+ budget, hosted_budget, truncated = [0], [0], len(runs) > max_runs
196
196
  jobs = {}
197
- for run in runs[:MAX_RUNS]:
197
+ for run in runs[:max_runs]:
198
198
  capture = LogCapture.model_validate(run.log_capture or {"mode": "unavailable"})
199
199
  status, found, more = "unavailable", [], False
200
200
  if state.config.local_mode and capture.mode == "local":
@@ -32,6 +32,13 @@ def fingerprint(update_uid, actor, payload):
32
32
  return sha256(json.dumps(body, sort_keys=True, separators=(",", ":")).encode()).hexdigest()
33
33
 
34
34
 
35
+ def updater_label(update):
36
+ """The updater's class name, as graphs and run history label it; its hash otherwise."""
37
+ path = update.build_configuration.get("table_updater_class_import_path", {})
38
+ label = path.get("qualname") if isinstance(path, dict) else None
39
+ return label if isinstance(label, str) else update.update_hash
40
+
41
+
35
42
  def _require(condition, message):
36
43
  if not condition:
37
44
  raise CatalogInvariantError(message)
@@ -107,10 +114,7 @@ def build_snapshot(session, actor, root_uid, plan):
107
114
  for uid, update in sorted(updates.items()):
108
115
  _require(grants.may_access_table(table_uid=update.output_table_uid, actor=actor, edit=True),
109
116
  "Run updater is unavailable")
110
- path = update.build_configuration.get("table_updater_class_import_path", {})
111
- label = path.get("qualname") if isinstance(path, dict) else None
112
- nodes.append({"id": f"update:{uid}", "uid": uid, "kind": "update",
113
- "label": label if isinstance(label, str) else update.update_hash,
117
+ nodes.append({"id": f"update:{uid}", "uid": uid, "kind": "update", "label": updater_label(update),
114
118
  "update_hash": update.update_hash, "output_table_uid": str(update.output_table_uid),
115
119
  "namespace": tables[str(update.output_table_uid)][1]})
116
120
  edges.append({"source": f"update:{uid}", "target": f"table:{update.output_table_uid}", "kind": "writes"})
@@ -265,6 +269,10 @@ def read_graph(session, actor, selected):
265
269
  grants = GrantRepository(session)
266
270
  if root_node is None or not grants.may_access_table(table_uid=root_node.output_table_uid, actor=actor):
267
271
  return None
272
+ # Attempt records bound each node's timeline: admission to completion around the
273
+ # calculation window that node_states records.
274
+ attempts = {str(row.uid): row for row in session.scalars(select(UpdateRun).where(UpdateRun.uid.in_(
275
+ [UUID(state["run_uid"]) for state in graph.node_states.values() if state["run_uid"]])))}
268
276
  nodes = []
269
277
  for saved in graph.snapshot["nodes"]:
270
278
  table_uid = UUID(saved.get("output_table_uid") or saved["uid"])
@@ -276,6 +284,9 @@ def read_graph(session, actor, selected):
276
284
  if node["kind"] == "update":
277
285
  node.update(graph.node_states[node["id"]])
278
286
  node["status"] = node["state"]
287
+ attempt = attempts.get(node["run_uid"])
288
+ node["attempt_started_at"] = attempt.started_at if attempt else None
289
+ node["attempt_ended_at"] = attempt.ended_at if attempt else None
279
290
  nodes.append(node)
280
291
  ids = {node["id"] for node in nodes}
281
292
  return {"availability": "available", "run_uid": str(selected.uid), "root_run_uid": str(root.uid),
@@ -1,3 +1 @@
1
1
  local_mode_available: false
2
- application_migration_providers:
3
- market-tutorial: examples.tutorial.migrations:migration
examples/README.md CHANGED
@@ -8,7 +8,7 @@ For one connected walkthrough, start with the [market tutorial](tutorial/README.
8
8
 
9
9
  | Asset | What it demonstrates | Required environment |
10
10
  | --- | --- | --- |
11
- | [Local application](local_app/README.md) | Setup, API/Admin launch, explicit bootstrap, approved migrations and persistent write/read | Installed package, application Git checkout, SDK login; Node/npm for Admin. |
11
+ | [Local application](local_app/README.md) | Setup, API/Admin launch, explicit bootstrap, application-owned migrations and persistent write/read | Installed package, application Git checkout, SDK login; Node/npm for Admin. |
12
12
  | [tables.py](tables.py) | Related account and time-index balance contracts | Import/contract checks are offline. |
13
13
  | [quickstart.py](quickstart.py) | Retrieve and validate a visible table | Configured API, SDK session, table grant. |
14
14
  | [external_table.py](external_table.py) | Register an existing physical relation | API, source access, pre-existing matching table. |
@@ -7,7 +7,7 @@ needs a commit and an `origin` remote. Use Python 3.13+ on macOS or Linux.
7
7
  ```bash
8
8
  python -m pip install mainsequence-metatable
9
9
  mainsequence login
10
- metatables init --local --provider local-example=examples.local_app.migrations:migration
10
+ metatables init --local
11
11
  metatables serve --local --admin
12
12
  ```
13
13
 
@@ -22,7 +22,7 @@ In another terminal in the same project and Python environment:
22
22
  ```bash
23
23
  metatables --local runtime status
24
24
  metatables --local runtime initialize
25
- metatables --local migrations upgrade --provider local-example
25
+ metatables --local migrations upgrade --provider examples.local_app.migrations:migration
26
26
  python -m examples.local_app
27
27
  metatables --local meta-table list
28
28
  ```
@@ -33,10 +33,9 @@ Expected example output:
33
33
  [{"key": "hello", "message": "My local MetaTables application"}]
34
34
  ```
35
35
 
36
- The provider creates the table and finalizes its catalog binding through the API.
36
+ The client runs the provider to create the table, then finalizes its catalog binding through the API.
37
37
  The example resolves that table by identifier, compiles bound SQL for the API's
38
- selected dialect, upserts one note, and reads it back. It never opens SQLite from
39
- the client. Repeating it keeps one row. Stop and restart the launcher, then inspect
38
+ selected dialect, upserts one note, and reads it back. Ordinary reads and writes use the API; only migrations open the environment database. Repeating it keeps one row. Stop and restart the launcher, then inspect
40
39
  the existing row before any write:
41
40
 
42
41
  ```bash
@@ -49,5 +48,4 @@ Native keyring credentials are the default; for a headless machine, configure th
49
48
  file credential provider as described in the [local runtime guide](../../docs/operations/local-runtime.md#local-credentials).
50
49
 
51
50
  For your own application, define tables like [Note](tables.py), install the package
52
- containing your [migration provider](migrations/__init__.py), and explicitly approve
53
- its alias in `configuration.yaml`. See [migration authoring](../../docs/client/define-and-migrate-tables.md).
51
+ containing your [migration provider](migrations/__init__.py) in the application process. See [migration authoring](../../docs/client/define-and-migrate-tables.md).
@@ -1,4 +1,4 @@
1
- """Only this application's note table belongs to this approved provider."""
1
+ """Only this application's note table belongs to this application-owned provider."""
2
2
 
3
3
  from examples.local_app.tables import Base, Note
4
4
  from metatables.migrations import (
@@ -5,22 +5,12 @@ from pathlib import Path
5
5
 
6
6
 
7
7
  def setup_metatables():
8
- from mainsequence.client.exceptions import raise_for_response
9
- from mainsequence.client.utils import make_request
10
-
11
8
  from metatables.endpoint import api_endpoint_scope, resolve_api_endpoint
12
- from metatables.models import _MetaTablesBaseObjectOrm
13
-
14
- class MigrationResource(_MetaTablesBaseObjectOrm):
15
- ENDPOINT = "application-migrations/upgrade/"
9
+ from metatables.runtime import upgrade_application
16
10
 
17
11
  with api_endpoint_scope():
18
12
  print(f"Preparing tutorial on MetaTables API: {resolve_api_endpoint().url}", flush=True)
19
- response = make_request(s=MigrationResource.build_session(), loaders=MigrationResource.LOADERS,
20
- r_type="POST", url=MigrationResource.get_object_url(),
21
- payload={"json": {"provider": "market-tutorial"}}, time_out=(5, 120))
22
- raise_for_response(response)
23
- result = response.json()
13
+ result = upgrade_application('examples.tutorial.migrations:migration', timeout=120)
24
14
  print(f"Tutorial DataSource: {result['data_source_uid']}; revision: {result['revision']} "
25
15
  f"({'migrated' if result['migrated'] else 'already current'})", flush=True)
26
16
  return result