mainsequence-metatable 0.1.28.dev48__tar.gz → 0.1.28.dev50__tar.gz

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 (585) hide show
  1. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/PKG-INFO +1 -1
  2. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0007-database-enforced-table-access.md +23 -0
  3. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0022-concurrent-requests-and-connection-reuse.md +4 -3
  4. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/index.md +1 -1
  5. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/pyproject.toml +1 -1
  6. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/PKG-INFO +1 -1
  7. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/SOURCES.txt +1 -0
  8. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/access.py +159 -14
  9. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/hosted_access.py +2 -2
  10. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/postgresql_access.py +133 -68
  11. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/sqlite_access.py +3 -1
  12. mainsequence_metatable-0.1.28.dev50/tests/permissions/test_incremental_security.py +198 -0
  13. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/analyze-with-sql/SKILL.md +0 -0
  14. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-local-development/SKILL.md +0 -0
  15. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-meta-tables/SKILL.md +0 -0
  16. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-migrations/SKILL.md +0 -0
  17. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-table-discovery/SKILL.md +0 -0
  18. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-time-index-table-updates/SKILL.md +0 -0
  19. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/client/metatables-upgrade-legacy-app/SKILL.md +0 -0
  20. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/discover-tables/SKILL.md +0 -0
  21. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/PINNED_FROM.txt +0 -0
  22. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/tau_a2a_runtime_adapter/SKILL.md +0 -0
  23. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/tau_local_development/SKILL.md +0 -0
  24. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/tau_project_customization/SKILL.md +0 -0
  25. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/tau_repository_integration/SKILL.md +0 -0
  26. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.agents/skills/ms_tau_sdk/tau_security_and_access/SKILL.md +0 -0
  27. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/.mainsequence/workflows/metatables-api.yaml +0 -0
  28. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/LICENSE +0 -0
  29. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/MANIFEST.in +0 -0
  30. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/README.md +0 -0
  31. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/alembic.ini +0 -0
  32. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/api/metatables/main.py +0 -0
  33. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/compose.database-tests.yml +0 -0
  34. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/agent/0019-metatables-analyst-agent.md +0 -0
  35. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/agent/0020-analyst-reads-as-its-requester.md +0 -0
  36. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/agent/0021-api-serves-the-analyst-tools-over-mcp.md +0 -0
  37. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +0 -0
  38. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0002-application-administration-and-table-ownership.md +0 -0
  39. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0004-approved-application-migrations.md +0 -0
  40. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0005-run-logs-and-local-file-capture.md +0 -0
  41. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0006-historical-run-graphs.md +0 -0
  42. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0007-database-roles-and-privileges.svg +0 -0
  43. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0007-query-enforcement-path.svg +0 -0
  44. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0008-mysql-mssql-table-workflows.md +0 -0
  45. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0009-shared-credential-store.md +0 -0
  46. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0010-import-external-tables-and-views.md +0 -0
  47. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0012-bounded-data-transfer-and-safe-retries.md +0 -0
  48. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0013-application-owned-migrations.md +0 -0
  49. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0014-main-sequence-release-jobs-and-production-migrations.md +0 -0
  50. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0015-timescale-compression-and-retention-policies.md +0 -0
  51. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0016-impact-preflight.md +0 -0
  52. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0017-hosted-request-identity.md +0 -0
  53. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0018-search-document-pipeline.svg +0 -0
  54. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/api/0018-table-search.md +0 -0
  55. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/client/0003-api-endpoint-resolution.md +0 -0
  56. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/adr/client/0011-cli-local-development-with-managed-admin.md +0 -0
  57. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/authentication-and-errors.md +0 -0
  58. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/data-sources.md +0 -0
  59. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/openapi.json +0 -0
  60. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/overview.md +0 -0
  61. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/reference.md +0 -0
  62. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/tables-and-migrations.md +0 -0
  63. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/api/time-index-and-updates.md +0 -0
  64. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/assets/branding/metatables.svg +0 -0
  65. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/assets/diagrams/local-client-experience.svg +0 -0
  66. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/assets/diagrams/namespace-access.svg +0 -0
  67. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/bounded-transfers.md +0 -0
  68. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/build-an-updater.md +0 -0
  69. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/define-and-migrate-tables.md +0 -0
  70. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/deploy-application-migrations.md +0 -0
  71. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/installation-and-connection.md +0 -0
  72. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/local-storage.md +0 -0
  73. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/query-and-mutate.md +0 -0
  74. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/quickstart.md +0 -0
  75. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/read-existing-time-index-tables.md +0 -0
  76. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/register-existing-tables.md +0 -0
  77. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/tutorial.md +0 -0
  78. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/client/upgrade-legacy-app.md +0 -0
  79. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/architecture.md +0 -0
  80. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/data-sources.md +0 -0
  81. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/identity-and-scope.md +0 -0
  82. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/permissions-namespaces-labels.md +0 -0
  83. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/runs-and-execution-graphs.md +0 -0
  84. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/table-contracts-and-lifecycle.md +0 -0
  85. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/concepts/time-index-tables-and-updates.md +0 -0
  86. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/contributing/architecture-and-boundaries.md +0 -0
  87. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/contributing/database-backends.md +0 -0
  88. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/contributing/documentation.md +0 -0
  89. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/contributing/releasing.md +0 -0
  90. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/contributing/testing.md +0 -0
  91. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/README.md +0 -0
  92. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/__init__.py +0 -0
  93. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/bounded_reader.py +0 -0
  94. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/data_sources/README.md +0 -0
  95. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/data_sources/mssql.json +0 -0
  96. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/data_sources/mysql.json +0 -0
  97. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/data_sources/postgresql.json +0 -0
  98. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/data_sources/register.py +0 -0
  99. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/external_table.py +0 -0
  100. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/README.md +0 -0
  101. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/__init__.py +0 -0
  102. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/__main__.py +0 -0
  103. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/migrations/__init__.py +0 -0
  104. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/migrations/env.py +0 -0
  105. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/migrations/script.py.mako +0 -0
  106. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/migrations/versions/metatables_local_example/0001.py +0 -0
  107. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/local_app/tables.py +0 -0
  108. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/query.py +0 -0
  109. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/quickstart.py +0 -0
  110. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/reader.py +0 -0
  111. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/scripts/__init__.py +0 -0
  112. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/scripts/setup_metatables.py +0 -0
  113. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tables.py +0 -0
  114. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/README.md +0 -0
  115. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/__init__.py +0 -0
  116. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/__main__.py +0 -0
  117. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/data/README.md +0 -0
  118. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/data/yahoo_spy_qqq_iwm_2026-06-15_2026-07-17.csv +0 -0
  119. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/frames.py +0 -0
  120. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/__init__.py +0 -0
  121. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/env.py +0 -0
  122. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/registry.py +0 -0
  123. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/script.py.mako +0 -0
  124. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/versions/__init__.py +0 -0
  125. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0001_create_market_tutorial_tables.py +0 -0
  126. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +0 -0
  127. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/__init__.py +0 -0
  128. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/operations.py +0 -0
  129. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/tables.py +0 -0
  130. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/tutorial/updaters.py +0 -0
  131. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/examples/updater.py +0 -0
  132. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/index.md +0 -0
  133. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/catalog-migrations.md +0 -0
  134. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/configuration.md +0 -0
  135. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/hosted-runtime.md +0 -0
  136. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/local-runtime.md +0 -0
  137. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/recovery-and-observability.md +0 -0
  138. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/run-history.md +0 -0
  139. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/operations/run-logs.md +0 -0
  140. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/reference/capabilities.md +0 -0
  141. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/reference/cli.md +0 -0
  142. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/reference/python.md +0 -0
  143. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/security/index.md +0 -0
  144. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/security/ownership-and-sharing.md +0 -0
  145. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/docs/security/permissions.md +0 -0
  146. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/mkdocs.yml +0 -0
  147. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/__init__.py +0 -0
  148. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/build_reference.py +0 -0
  149. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_boundaries.py +0 -0
  150. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_client_api_coverage.py +0 -0
  151. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_distribution_sources.py +0 -0
  152. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_docs.py +0 -0
  153. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_examples_debug.py +0 -0
  154. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/check_project.py +0 -0
  155. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/dev_release_version.py +0 -0
  156. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/test_databases.py +0 -0
  157. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/scripts/test_postgresql.py +0 -0
  158. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/setup.cfg +0 -0
  159. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/dependency_links.txt +0 -0
  160. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/entry_points.txt +0 -0
  161. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/requires.txt +0 -0
  162. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/mainsequence_metatable.egg-info/top_level.txt +0 -0
  163. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/__init__.py +0 -0
  164. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/_admin_source.json +0 -0
  165. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/_build.py +0 -0
  166. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/_skill_bundle.py +0 -0
  167. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/analysis.py +0 -0
  168. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/analyst/__init__.py +0 -0
  169. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/__init__.py +0 -0
  170. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/__init__.py +0 -0
  171. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/auth/__init__.py +0 -0
  172. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/auth/boundary.py +0 -0
  173. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/auth/local_actor.py +0 -0
  174. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/bootstrap.py +0 -0
  175. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/configuration.py +0 -0
  176. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/connection_count.py +0 -0
  177. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/credential_admin.py +0 -0
  178. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/development.py +0 -0
  179. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/development_client.py +0 -0
  180. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/error_logging.py +0 -0
  181. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/main.py +0 -0
  182. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/mcp.py +0 -0
  183. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/platform_cache.py +0 -0
  184. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/__init__.py +0 -0
  185. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/access_map.py +0 -0
  186. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/caller.py +0 -0
  187. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/column_search.py +0 -0
  188. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/contract_validation.py +0 -0
  189. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/data_sources.py +0 -0
  190. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/managed_finalize.py +0 -0
  191. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/migration_connection.py +0 -0
  192. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/namespaces.py +0 -0
  193. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/run_logs.py +0 -0
  194. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/runtime_context.py +0 -0
  195. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/schema_graph.py +0 -0
  196. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/security.py +0 -0
  197. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_cascade.py +0 -0
  198. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_crud.py +0 -0
  199. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_delete.py +0 -0
  200. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_filter.py +0 -0
  201. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_import.py +0 -0
  202. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_introspection.py +0 -0
  203. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_patch.py +0 -0
  204. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_registration.py +0 -0
  205. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_response.py +0 -0
  206. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_search.py +0 -0
  207. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_search_document.py +0 -0
  208. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_sql.py +0 -0
  209. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/table_update_pipeline.py +0 -0
  210. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/time_index_delete.py +0 -0
  211. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/time_index_reads.py +0 -0
  212. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/time_index_stats.py +0 -0
  213. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/timescale_policies.py +0 -0
  214. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_batch.py +0 -0
  215. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_chunk_insert.py +0 -0
  216. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_constants.py +0 -0
  217. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_crud.py +0 -0
  218. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_details.py +0 -0
  219. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_graph.py +0 -0
  220. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_index_statistics.py +0 -0
  221. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_registration.py +0 -0
  222. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_runs.py +0 -0
  223. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/routes/update_statistics.py +0 -0
  224. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/runtime.py +0 -0
  225. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/runtime_control.py +0 -0
  226. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/runtime_database.py +0 -0
  227. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/source_passwords.py +0 -0
  228. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/app/transfer.py +0 -0
  229. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/__init__.py +0 -0
  230. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/__init__.py +0 -0
  231. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/__init__.py +0 -0
  232. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/__init__.py +0 -0
  233. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/postgresql.py +0 -0
  234. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/runtime.py +0 -0
  235. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/temporal.py +0 -0
  236. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/timescaledb.py +0 -0
  237. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/maintenance/validation.py +0 -0
  238. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_cascade_delete.py +0 -0
  239. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_connection.py +0 -0
  240. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_introspection.py +0 -0
  241. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_table_delete.py +0 -0
  242. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_tables.py +0 -0
  243. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_time_index.py +0 -0
  244. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_time_index_delete.py +0 -0
  245. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_time_index_queries.py +0 -0
  246. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_time_index_stats.py +0 -0
  247. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/postgresql_time_index_write.py +0 -0
  248. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/source_validation.py +0 -0
  249. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/sqlite_connection.py +0 -0
  250. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/sqlite_introspection.py +0 -0
  251. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/adapters/table_cursor.py +0 -0
  252. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/catalog.py +0 -0
  253. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/catalog_ddl.py +0 -0
  254. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/catalog_types.py +0 -0
  255. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/connection_pool.py +0 -0
  256. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/contracts.py +0 -0
  257. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/hosted.py +0 -0
  258. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/migration_connection.py +0 -0
  259. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/native.py +0 -0
  260. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/operations.py +0 -0
  261. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/pages.py +0 -0
  262. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/registry.py +0 -0
  263. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/relation_tables.py +0 -0
  264. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/relational.py +0 -0
  265. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/restricted_sql.py +0 -0
  266. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/streaming.py +0 -0
  267. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/backends/timescale.py +0 -0
  268. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/contracts/__init__.py +0 -0
  269. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/contracts/relation_import.py +0 -0
  270. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/contracts/storage_layouts.py +0 -0
  271. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/contracts/table_contracts.py +0 -0
  272. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/contracts/values.py +0 -0
  273. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/__init__.py +0 -0
  274. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/catalog_rules.py +0 -0
  275. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/data_source_rules.py +0 -0
  276. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/index_statistics.py +0 -0
  277. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/label_rules.py +0 -0
  278. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/permission_rules.py +0 -0
  279. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/domain/update_constants.py +0 -0
  280. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/__init__.py +0 -0
  281. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/catalog_data_sources.py +0 -0
  282. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/credential_keys.py +0 -0
  283. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/credential_store.py +0 -0
  284. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/data_source_provider.py +0 -0
  285. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/local_credentials.py +0 -0
  286. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/local_workspace.py +0 -0
  287. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/platform_principals.py +0 -0
  288. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/run_logs.py +0 -0
  289. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/runtime_binding.py +0 -0
  290. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/runtime_data_sources.py +0 -0
  291. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/integrations/source_validation.py +0 -0
  292. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/__init__.py +0 -0
  293. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/env.py +0 -0
  294. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/script.py.mako +0 -0
  295. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0001_initial.py +0 -0
  296. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0002_security_model.py +0 -0
  297. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0003_run_log_capture.py +0 -0
  298. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0004_historical_run_graphs.py +0 -0
  299. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0005_database_access.py +0 -0
  300. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0006_local_credentials.py +0 -0
  301. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0007_external_relation_names.py +0 -0
  302. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0008_upload_receipts.py +0 -0
  303. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0009_timescale_policies.py +0 -0
  304. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0010_cascade_targets.py +0 -0
  305. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0011_table_search.py +0 -0
  306. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/0012_table_creator.py +0 -0
  307. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/migrations/versions/__init__.py +0 -0
  308. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/__init__.py +0 -0
  309. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/bootstrap_migrations.py +0 -0
  310. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/catalog_schema.py +0 -0
  311. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/create_table.py +0 -0
  312. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/finalize_managed.py +0 -0
  313. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/import_relations.py +0 -0
  314. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/introspect_table.py +0 -0
  315. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/read_time_index.py +0 -0
  316. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/operations/register_catalog.py +0 -0
  317. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/__init__.py +0 -0
  318. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/cascade.py +0 -0
  319. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/catalog.py +0 -0
  320. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/database.py +0 -0
  321. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/grants.py +0 -0
  322. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/impact.py +0 -0
  323. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/labels.py +0 -0
  324. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/locking.py +0 -0
  325. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/models.py +0 -0
  326. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/physical_operations.py +0 -0
  327. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/projections.py +0 -0
  328. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/run_graphs.py +0 -0
  329. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/schema_graph.py +0 -0
  330. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/sqlite_types.py +0 -0
  331. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/table_body_filter.py +0 -0
  332. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/table_queries.py +0 -0
  333. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/table_response.py +0 -0
  334. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/update_graph.py +0 -0
  335. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/update_pipeline.py +0 -0
  336. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/updates.py +0 -0
  337. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/persistence/upload_receipts.py +0 -0
  338. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/presentation/data_source_summary.py +0 -0
  339. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/__init__.py +0 -0
  340. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/documents.py +0 -0
  341. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/embeddings.py +0 -0
  342. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/index.py +0 -0
  343. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/ranking.py +0 -0
  344. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/text.py +0 -0
  345. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/backend/search/worker.py +0 -0
  346. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/metatables/__init__.py +0 -0
  347. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/metatables/configuration.yaml +0 -0
  348. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/metatables/main.py +0 -0
  349. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/api/request_timing.py +0 -0
  350. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/__init__.py +0 -0
  351. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/admin_install.py +0 -0
  352. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/app.py +0 -0
  353. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/filters.py +0 -0
  354. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/local.py +0 -0
  355. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/migrations.py +0 -0
  356. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/project.py +0 -0
  357. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/cli/skills.py +0 -0
  358. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/compiled_sql/__init__.py +0 -0
  359. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/compiled_sql/mssql.py +0 -0
  360. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/compiled_sql/v1.py +0 -0
  361. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/dtype_codec.py +0 -0
  362. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/endpoint.py +0 -0
  363. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/README.md +0 -0
  364. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/__init__.py +0 -0
  365. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/bounded_reader.py +0 -0
  366. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/data_sources/README.md +0 -0
  367. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/data_sources/mssql.json +0 -0
  368. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/data_sources/mysql.json +0 -0
  369. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/data_sources/postgresql.json +0 -0
  370. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/data_sources/register.py +0 -0
  371. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/external_table.py +0 -0
  372. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/README.md +0 -0
  373. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/__init__.py +0 -0
  374. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/__main__.py +0 -0
  375. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/migrations/__init__.py +0 -0
  376. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/migrations/env.py +0 -0
  377. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/migrations/script.py.mako +0 -0
  378. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/migrations/versions/metatables_local_example/0001.py +0 -0
  379. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/local_app/tables.py +0 -0
  380. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/query.py +0 -0
  381. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/quickstart.py +0 -0
  382. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/reader.py +0 -0
  383. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/scripts/__init__.py +0 -0
  384. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/scripts/setup_metatables.py +0 -0
  385. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tables.py +0 -0
  386. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/README.md +0 -0
  387. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/__init__.py +0 -0
  388. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/__main__.py +0 -0
  389. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/data/README.md +0 -0
  390. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/data/yahoo_spy_qqq_iwm_2026-06-15_2026-07-17.csv +0 -0
  391. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/frames.py +0 -0
  392. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/__init__.py +0 -0
  393. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/env.py +0 -0
  394. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/registry.py +0 -0
  395. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/script.py.mako +0 -0
  396. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/versions/__init__.py +0 -0
  397. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/versions/metatables_market_tutorial/0001_create_market_tutorial_tables.py +0 -0
  398. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +0 -0
  399. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/migrations/versions/metatables_market_tutorial/__init__.py +0 -0
  400. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/operations.py +0 -0
  401. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/tables.py +0 -0
  402. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/tutorial/updaters.py +0 -0
  403. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/examples/updater.py +0 -0
  404. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/future_registry.py +0 -0
  405. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/hashing.py +0 -0
  406. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/instrumentation.py +0 -0
  407. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/local_connection.py +0 -0
  408. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/local_files.py +0 -0
  409. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/local_run_logs.py +0 -0
  410. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/log_contract.py +0 -0
  411. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/__init__.py +0 -0
  412. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/alembic.py +0 -0
  413. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/connection.py +0 -0
  414. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/env.py +0 -0
  415. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/provider.py +0 -0
  416. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/registry.py +0 -0
  417. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/runner.py +0 -0
  418. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/scaffold.py +0 -0
  419. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/sqlite.py +0 -0
  420. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/templates/__init__.py +0 -0
  421. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/templates/env.py.mako +0 -0
  422. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/templates/script.py.mako +0 -0
  423. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/migrations/tls.py +0 -0
  424. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/models.py +0 -0
  425. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/pydantic_metadata.py +0 -0
  426. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/run_logging.py +0 -0
  427. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/runtime.py +0 -0
  428. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/runtime_context.py +0 -0
  429. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/runtime_contract.py +0 -0
  430. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/schema_names.py +0 -0
  431. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/sdk_compat.py +0 -0
  432. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/sqlalchemy_contracts.py +0 -0
  433. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/storage_layout_contract.py +0 -0
  434. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/time_index_table_refs.py +0 -0
  435. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/transfer.py +0 -0
  436. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/transfer_contract.py +0 -0
  437. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/transport.py +0 -0
  438. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/update_configuration_contract.py +0 -0
  439. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/__init__.py +0 -0
  440. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/configuration.py +0 -0
  441. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/dependencies.py +0 -0
  442. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/managers.py +0 -0
  443. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/namespacing.py +0 -0
  444. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/runner.py +0 -0
  445. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/updaters.py +0 -0
  446. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/updaters/utils.py +0 -0
  447. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/src/metatables/upload.py +0 -0
  448. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/analyst/test_agent_surface.py +0 -0
  449. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/analyst/test_api_search.py +0 -0
  450. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/analyst/test_mcp.py +0 -0
  451. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/analyst/test_tools.py +0 -0
  452. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_bootstrap_failure_cause.py +0 -0
  453. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_caller_endpoint.py +0 -0
  454. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_data_source_identity.py +0 -0
  455. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_development_client.py +0 -0
  456. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_hosted_agent.py +0 -0
  457. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_hosted_environment_target.py +0 -0
  458. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_local_mode.py +0 -0
  459. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_platform_fact_cache.py +0 -0
  460. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_request_identity.py +0 -0
  461. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_runtime_bootstrap.py +0 -0
  462. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_runtime_database.py +0 -0
  463. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_runtime_scaffold.py +0 -0
  464. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_runtime_selection.py +0 -0
  465. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_runtime_storage_binding.py +0 -0
  466. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/auth/test_source_passwords.py +0 -0
  467. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/catalog/test_catalog_foundation.py +0 -0
  468. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/catalog/test_contract_projection.py +0 -0
  469. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/catalog/test_database_config.py +0 -0
  470. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/catalog/test_index_statistics.py +0 -0
  471. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/catalog/test_migration.py +0 -0
  472. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/conftest.py +0 -0
  473. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/capabilities.json +0 -0
  474. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/client_signatures.json +0 -0
  475. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/database_operations.json +0 -0
  476. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_bounded_transfer.py +0 -0
  477. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_compiler_runtime_source.py +0 -0
  478. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_relation_batching.py +0 -0
  479. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_relation_import.py +0 -0
  480. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_runtime_contract_compat.py +0 -0
  481. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_storage_layouts.py +0 -0
  482. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/contracts/test_table_contracts.py +0 -0
  483. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/Dockerfile +0 -0
  484. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/Dockerfile.dockerignore +0 -0
  485. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/__init__.py +0 -0
  486. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/conftest.py +0 -0
  487. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/provider/__init__.py +0 -0
  488. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/provider/env.py +0 -0
  489. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/provider/versions/0001_measurement.py +0 -0
  490. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_api_contract.py +0 -0
  491. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_application_migration.py +0 -0
  492. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_bootstrap_recovery.py +0 -0
  493. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_catalog_contract.py +0 -0
  494. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_credential_catalog.py +0 -0
  495. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_physical_contract.py +0 -0
  496. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_relation_import.py +0 -0
  497. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_runtime_bootstrap.py +0 -0
  498. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_sql_security.py +0 -0
  499. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_backend/test_update_client.py +0 -0
  500. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_operations/test_physical_operations.py +0 -0
  501. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_operations/test_postgresql_operations.py +0 -0
  502. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/database_operations/test_runtime_and_temporal.py +0 -0
  503. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/documentation/test_project_checks.py +0 -0
  504. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_admin_installation.py +0 -0
  505. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_api_endpoint.py +0 -0
  506. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_application_owned_migrations.py +0 -0
  507. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_catalog_outage.py +0 -0
  508. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_api_contract.py +0 -0
  509. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_api_coverage.py +0 -0
  510. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_migration_scaffold.py +0 -0
  511. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_migration_tls.py +0 -0
  512. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_package.py +0 -0
  513. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_signatures.py +0 -0
  514. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_client_value_behaviors.py +0 -0
  515. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_data_source_registry.py +0 -0
  516. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_local_actor_client_api.py +0 -0
  517. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_local_cli_workflow.py +0 -0
  518. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_local_client_selection.py +0 -0
  519. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_managed_finalize_client_api.py +0 -0
  520. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_namespaces_admin_http.py +0 -0
  521. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_public_imports.py +0 -0
  522. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_remaining_client_routes.py +0 -0
  523. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_run_graphs.py +0 -0
  524. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_run_logs.py +0 -0
  525. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_runtime_upgrade.py +0 -0
  526. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_sdk_local_startup.py +0 -0
  527. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_sqlite_runtime.py +0 -0
  528. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_delete_client_api.py +0 -0
  529. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_filter_client_api.py +0 -0
  530. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_introspection_client_api.py +0 -0
  531. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_patch_client_api.py +0 -0
  532. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_search_api.py +0 -0
  533. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_search_document_api.py +0 -0
  534. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_search_scale.py +0 -0
  535. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_stats_api.py +0 -0
  536. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_update_pipeline.py +0 -0
  537. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_table_updates_http.py +0 -0
  538. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_time_index_delete_client_api.py +0 -0
  539. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_time_index_reads_client_api.py +0 -0
  540. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_timescale_policies_client_api.py +0 -0
  541. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_update_batch_client_api.py +0 -0
  542. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_update_chunk_insert_client_api.py +0 -0
  543. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_update_dependency_priority_client_api.py +0 -0
  544. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_update_index_statistics_client_api.py +0 -0
  545. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/e2e/test_update_registration_client_api.py +0 -0
  546. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/examples/test_documented_examples.py +0 -0
  547. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/examples/test_postgresql_examples.py +0 -0
  548. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/examples/test_setup_launch.py +0 -0
  549. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/examples/test_tutorial.py +0 -0
  550. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_connection_reuse.py +0 -0
  551. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_credential_store.py +0 -0
  552. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_data_source_rules.py +0 -0
  553. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_local_data_sources.py +0 -0
  554. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_local_run_logs.py +0 -0
  555. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_postgresql_connection.py +0 -0
  556. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_postgresql_sql.py +0 -0
  557. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_postgresql_tables.py +0 -0
  558. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_postgresql_time_index_queries.py +0 -0
  559. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_request_timing.py +0 -0
  560. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_serving_policy.py +0 -0
  561. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_source_validation.py +0 -0
  562. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/integrations/test_sqlite_operations.py +0 -0
  563. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/labels/test_labels.py +0 -0
  564. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_create_table_operation.py +0 -0
  565. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_create_table_postgres.py +0 -0
  566. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_physical_operation_journal.py +0 -0
  567. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_register_catalog.py +0 -0
  568. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_search_documents.py +0 -0
  569. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/operations/test_timescale_policies.py +0 -0
  570. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/packaging/test_client_skills.py +0 -0
  571. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/packaging/test_dev_release_version.py +0 -0
  572. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/packaging/test_distribution_sources.py +0 -0
  573. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/packaging/test_editable_build.py +0 -0
  574. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/packaging/test_installed_distribution.py +0 -0
  575. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_access_map.py +0 -0
  576. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_governed_sql_scope.py +0 -0
  577. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_local_actor_membership.py +0 -0
  578. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_migration_boundary.py +0 -0
  579. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_namespace_grants.py +0 -0
  580. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_security_api.py +0 -0
  581. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_table_body_filter.py +0 -0
  582. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_table_grants.py +0 -0
  583. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_table_queries.py +0 -0
  584. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/tests/permissions/test_workload_principals.py +0 -0
  585. {mainsequence_metatable-0.1.28.dev48 → mainsequence_metatable-0.1.28.dev50}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence-metatable
3
- Version: 0.1.28.dev48
3
+ Version: 0.1.28.dev50
4
4
  Summary: Main Sequence MetaTables Python client and standalone API
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -32,6 +32,29 @@
32
32
  > Reconciliation still records each table's cascade targets, but only so the
33
33
  > [impact pre-flight](0016-impact-preflight.md) can show their effects.
34
34
 
35
+ > Amendment (2026-10-09): On PostgreSQL and TimescaleDB, a catalog change applies
36
+ > only what it changed. Reconciliation used to rebuild every role, re-inspect every
37
+ > table and re-secure every routine on each change, all under the catalog lock, so
38
+ > one registration could hold the lock for minutes and stop every other request.
39
+ > Now a change:
40
+ >
41
+ > - re-inspects the policies of the tables it changed, plus the tables whose
42
+ > recorded cascade targets they affect;
43
+ > - rebuilds only roles that are new or whose definition changed, and grants or
44
+ > revokes only the memberships and privileges that differ from the applied
45
+ > manifest;
46
+ > - re-secures routines only when the owned schemas, routines or `PUBLIC` grants
47
+ > changed since the last sweep.
48
+ >
49
+ > The full sweep still runs when the runtime DataSource changes, at initialization
50
+ > (the migration Job of every deployment) and from the admin repair action. Those
51
+ > are when grants changed outside MetaTables are repaired, not on every catalog
52
+ > change. MySQL and SQL Server keep the full sweep on every change.
53
+
54
+ > Amendment (2026-10-09): [ADR 0022](0022-concurrent-requests-and-connection-reuse.md)
55
+ > reuses login-role connections within a pod, only by the login role that opened them
56
+ > and never through `SET ROLE`; no session state carries over from one use to the next.
57
+
35
58
 
36
59
  Date: 2026-09-29
37
60
 
@@ -1,9 +1,10 @@
1
1
  # ADR 0022: Concurrent requests per pod and reused database connections
2
2
 
3
- Status: Proposed.
3
+ Status: Accepted.
4
4
 
5
- Implementation status: implemented on development; not deployed. Unit tests pass;
6
- the container suite and the load test against the development deployment are pending.
5
+ Implementation status: implemented on development. Unit tests pass; deployment
6
+ verification, the MySQL and SQL Server container suites and the load test against the
7
+ development deployment are pending.
7
8
 
8
9
  Owner: this repository.
9
10
 
@@ -39,7 +39,7 @@ decisions belong in the SDK repository and are linked as dependencies.
39
39
  | [0016: Impact pre-flight for cascades and deletes](api/0016-impact-preflight.md) | Accepted; implemented; container engine verification pending | `get_impact` returns what a row delete, key update or table drop reaches, every blocker and whether the caller may write each table, from the planner the confirmed delete runs; cascade effects never block. Projects render it in their own UIs. |
40
40
  | [0017: Hosted caller identity through the SDK request identity](api/0017-hosted-request-identity.md) | Accepted; implemented for 0.1.21; hosted rollout verification pending | The hosted API installs the SDK request identity that the platform launcher requires; the SDK verifies each caller assertion once and admission reads `User.get_logged_user()`, including the caller's signed Teams and admin flag. Local keeps its loopback token admission. |
41
41
  | [0018: Table search by meaning and columns](api/0018-table-search.md) | Accepted; implemented; container engine verification pending | One route ranks visible tables by BM25 keywords and a local English embedding model over a per-table document that includes columns, merges the rankings and returns `matched_columns`; the index refreshes on every metadata write. |
42
- | [0022: Concurrent requests per pod and reused database connections](api/0022-concurrent-requests-and-connection-reuse.md) | Proposed; implemented on development; not deployed; container and load verification pending | One number per pod sizes its threads, data-request admission, catalog pool and login-role connections; connections are reused only by the role that opened them, and maximum pods × 3T stays within the database's connection limit. |
42
+ | [0022: Concurrent requests per pod and reused database connections](api/0022-concurrent-requests-and-connection-reuse.md) | Accepted; implemented on development; deployment and load verification pending | One number per pod sizes its threads, data-request admission, catalog pool and login-role connections; connections are reused only by the role that opened them, and maximum pods × 3T stays within the database's connection limit. |
43
43
 
44
44
  ## Agents
45
45
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence-metatable"
7
- version = "0.1.28.dev48"
7
+ version = "0.1.28.dev50"
8
8
  description = "Main Sequence MetaTables Python client and standalone API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence-metatable
3
- Version: 0.1.28.dev48
3
+ Version: 0.1.28.dev50
4
4
  Summary: Main Sequence MetaTables Python client and standalone API
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -572,6 +572,7 @@ tests/packaging/test_editable_build.py
572
572
  tests/packaging/test_installed_distribution.py
573
573
  tests/permissions/test_access_map.py
574
574
  tests/permissions/test_governed_sql_scope.py
575
+ tests/permissions/test_incremental_security.py
575
576
  tests/permissions/test_local_actor_membership.py
576
577
  tests/permissions/test_migration_boundary.py
577
578
  tests/permissions/test_namespace_grants.py
@@ -33,9 +33,73 @@ class ExecutionIdentity:
33
33
  writable: frozenset[tuple[str, str]]
34
34
 
35
35
 
36
+ @dataclass(frozen=True)
37
+ class ManifestChanges:
38
+ """The statements that move the database from one applied manifest to the next.
39
+
40
+ ``reset`` roles are new or changed: each is rebuilt completely, so every one of
41
+ its memberships and privileges is granted again. ``retired`` roles are rebuilt
42
+ with nothing. Other roles change only by the memberships and privileges that
43
+ differ.
44
+ """
45
+
46
+ reset: frozenset
47
+ retired: frozenset
48
+ revoke_memberships: tuple
49
+ revoke_privileges: tuple
50
+ revoke_schemas: tuple
51
+ grant_memberships: tuple
52
+ grant_privileges: tuple
53
+
54
+
55
+ def manifest_changes(previous, desired):
56
+ """Diff two manifests; None when ``previous`` is not a complete applied manifest."""
57
+ if not (
58
+ isinstance(previous, dict)
59
+ and isinstance(previous.get("roles"), dict)
60
+ and isinstance(previous.get("memberships"), list)
61
+ and isinstance(previous.get("privileges"), list)
62
+ ):
63
+ return None
64
+ before, roles = previous["roles"], desired["roles"]
65
+ reset = frozenset(name for name, definition in roles.items() if before.get(name) != definition)
66
+ retired = frozenset(set(before) - set(roles))
67
+ rebuilt = reset | retired
68
+ old_memberships = {tuple(row) for row in previous["memberships"]}
69
+ new_memberships = {tuple(row) for row in desired["memberships"]}
70
+ old_privileges = {(n, s, t, bool(w)) for n, s, t, w in previous["privileges"]}
71
+ new_privileges = {(n, s, t, bool(w)) for n, s, t, w in desired["privileges"]}
72
+ revoke_privileges = tuple(sorted(
73
+ row for row in old_privileges - new_privileges if row[0] not in rebuilt
74
+ ))
75
+ kept_schemas = {(name, schema) for name, schema, _, _ in new_privileges}
76
+ return ManifestChanges(
77
+ reset=reset,
78
+ retired=retired,
79
+ # Rebuilding a role already revokes every membership it holds.
80
+ revoke_memberships=tuple(sorted(
81
+ row for row in old_memberships - new_memberships if row[0] not in rebuilt
82
+ )),
83
+ revoke_privileges=revoke_privileges,
84
+ revoke_schemas=tuple(sorted(
85
+ {(name, schema) for name, schema, _, _ in revoke_privileges} - kept_schemas
86
+ )),
87
+ grant_memberships=tuple(sorted(
88
+ row for row in new_memberships if row[0] in reset or row not in old_memberships
89
+ )),
90
+ grant_privileges=tuple(sorted(
91
+ row for row in new_privileges if row[0] in reset or row not in old_privileges
92
+ )),
93
+ )
94
+
95
+
36
96
  class DatabaseAccess:
37
97
  """Backend facet for setup, mirroring and restricted session admission."""
38
98
 
99
+ # A catalog change applies only what it changed; the full sweep stays for
100
+ # initialization and repair (ADR 0007, amended 2026-10-09).
101
+ incremental = False
102
+
39
103
  def __init__(self, backend):
40
104
  self.backend = backend
41
105
  self.source = backend.source
@@ -87,16 +151,20 @@ class DatabaseAccess:
87
151
  deleted or their keys updated, as (schema, table, on_delete, on_update)."""
88
152
  raise NotImplementedError
89
153
 
90
- def refresh_policies(self, session):
91
- tables = list(
92
- session.scalars(
93
- select(MetaTable)
94
- .where(MetaTable.data_source_uid == self.source.uid)
95
- .execution_options(populate_existing=True)
96
- )
154
+ def refresh_policies(self, session, tables=None):
155
+ """Inspect every table's policy, or only those of the table UIDs in ``tables``."""
156
+ query = (
157
+ select(MetaTable)
158
+ .where(MetaTable.data_source_uid == self.source.uid)
159
+ .execution_options(populate_existing=True)
97
160
  )
161
+ policies = select(SQLTablePolicy)
162
+ if tables is not None:
163
+ query = query.where(MetaTable.uid.in_(tables))
164
+ policies = policies.where(SQLTablePolicy.table_uid.in_(tables))
165
+ tables = list(session.scalars(query))
98
166
  current = {t.uid for t in tables}
99
- for old in session.scalars(select(SQLTablePolicy)):
167
+ for old in session.scalars(policies):
100
168
  if old.table_uid not in current:
101
169
  session.delete(old)
102
170
  for table in tables:
@@ -129,6 +197,59 @@ class DatabaseAccess:
129
197
  ]
130
198
  session.flush()
131
199
 
200
+ def policy_scope(self, session, changed):
201
+ """The tables whose policies a change to ``changed`` can affect.
202
+
203
+ A policy records its table's cascade targets, the tables whose foreign keys
204
+ act on its rows, so the scope adds the tables the changed ones reference and
205
+ the tables whose recorded targets name them. Returns None, meaning every
206
+ table, when a reference cannot be read.
207
+ """
208
+ import sqlalchemy as sa
209
+
210
+ changed = set(changed)
211
+ tables = {
212
+ t.uid: t
213
+ for t in session.scalars(
214
+ select(MetaTable).where(MetaTable.data_source_uid == self.source.uid)
215
+ )
216
+ }
217
+
218
+ def key(schema, name):
219
+ return self.backend.catalog.registration_schema(self.source, schema), name
220
+
221
+ by_name = {key(t.physical_schema, t.physical_table_name): uid for uid, t in tables.items()}
222
+ names = {key(t.physical_schema, t.physical_table_name) for uid, t in tables.items() if uid in changed}
223
+ names |= {
224
+ (policy.schema_name, policy.table_name)
225
+ for policy in session.scalars(
226
+ select(SQLTablePolicy).where(SQLTablePolicy.table_uid.in_(changed))
227
+ )
228
+ }
229
+ scope = set(changed)
230
+ inspector = sa.inspect(session.connection())
231
+ for uid in sorted(changed & set(tables), key=str):
232
+ table = tables[uid]
233
+ if table.provisioning_status != "active":
234
+ continue
235
+ try:
236
+ references = inspector.get_foreign_keys(
237
+ table.physical_table_name, schema=table.physical_schema
238
+ )
239
+ except Exception:
240
+ return None
241
+ for reference in references:
242
+ schema = reference.get("referred_schema") or table.physical_schema
243
+ scope.add(by_name.get(key(schema, reference["referred_table"])))
244
+ for policy in session.scalars(select(SQLTablePolicy)):
245
+ if any(
246
+ key(target.get("schema"), target.get("table")) in names
247
+ for target in policy.cascade_targets or ()
248
+ ):
249
+ scope.add(policy.table_uid)
250
+ scope.discard(None)
251
+ return scope
252
+
132
253
  def plan(self, session):
133
254
  """Read only catalog facts. No submitted statement or physical inspection."""
134
255
  roles, memberships, privileges = {}, set(), set()
@@ -190,18 +311,33 @@ class DatabaseAccess:
190
311
  memberships.add((login, role("team", team, write)))
191
312
  return dict(roles=roles, memberships=sorted(memberships), privileges=sorted(privileges))
192
313
 
193
- def reconcile(self, session, *, inspect_objects=False):
314
+ def reconcile(self, session, *, inspect_objects=False, tables=None):
315
+ """Mirror the catalog into database grants.
316
+
317
+ ``inspect_objects`` is the full sweep: every policy is inspected and every
318
+ role rebuilt, which also repairs grants changed outside MetaTables.
319
+ Otherwise only the policies ``tables`` can affect are inspected, and an
320
+ incremental backend applies only the grants that changed.
321
+ """
194
322
  state = session.get(SQLSecurityState, 1)
195
323
  if state is None or not state.ready:
196
324
  raise SQLExecutionError(code="sql_security_not_initialized")
197
325
  if inspect_objects:
198
326
  self.refresh_policies(session)
327
+ elif tables:
328
+ self.refresh_policies(session, tables=self.policy_scope(session, tables))
199
329
  desired = self.plan(session)
200
- self.apply(session, desired, state.manifest)
330
+ self.apply(session, desired, state.manifest, full=inspect_objects)
201
331
  state.manifest, state.pending = desired, False
202
332
  session.flush()
203
333
 
204
- def apply(self, session, desired, previous):
334
+ def reconcile_change(self, session, *, tables, full=False):
335
+ """Reconcile one catalog unit of work just before it commits."""
336
+ if full or not self.incremental:
337
+ return self.reconcile(session, inspect_objects=True)
338
+ return self.reconcile(session, tables=tables)
339
+
340
+ def apply(self, session, desired, previous, *, full=True):
205
341
  raise NotImplementedError
206
342
 
207
343
  def admit(self, session, actor, *, write, reconcile=True):
@@ -318,6 +454,13 @@ def _changed(session, *_):
318
454
 
319
455
  with session.no_autoflush:
320
456
  for row in session.new | session.dirty | session.deleted:
457
+ if isinstance(row, MetaTable) and row.data_source_uid == source_uid:
458
+ # Rows, not UIDs: a new row has its UID only once it is flushed.
459
+ session.info.setdefault("sql_security_tables", []).append(row)
460
+ elif isinstance(row, DataSource) and (row.is_runtime or row.is_default):
461
+ session.info["sql_security_full"] = True
462
+ elif session.info.get("sql_security_changed"):
463
+ continue
321
464
  relevant = (
322
465
  isinstance(row, MetaTable)
323
466
  and row.data_source_uid == source_uid
@@ -347,7 +490,6 @@ def _changed(session, *_):
347
490
  )
348
491
  if relevant:
349
492
  session.info["sql_security_changed"] = True
350
- break
351
493
 
352
494
 
353
495
  def _before_commit(session):
@@ -361,14 +503,15 @@ def _before_commit(session):
361
503
  ):
362
504
  return
363
505
  session.flush()
506
+ tables = {row.uid for row in session.info.pop("sql_security_tables", ())}
507
+ full = session.info.pop("sql_security_full", False)
364
508
  if not session.info.pop("sql_security_changed", False):
365
509
  return
366
510
  session.info["sql_security_syncing"] = True
367
511
  try:
368
512
  backend = resolver()
369
513
  backend.catalog.lock(session)
370
- access = backend.access
371
- access.reconcile(session, inspect_objects=True)
514
+ backend.access.reconcile_change(session, tables=tables, full=full)
372
515
  finally:
373
516
  session.info.pop("sql_security_syncing", None)
374
517
 
@@ -391,6 +534,8 @@ def _after_transaction_end(session, transaction):
391
534
  committed = session.info.pop("sql_commit_finished", False)
392
535
  access = session.info.pop("sql_deferred_access", None)
393
536
  session.info.pop("sql_security_changed", None)
537
+ session.info.pop("sql_security_tables", None)
538
+ session.info.pop("sql_security_full", None)
394
539
  session.info.pop("sql_admission_uncommitted", None)
395
540
  if committed and access is not None:
396
541
  try:
@@ -164,7 +164,7 @@ class MySQLAccess(HostedAccess):
164
164
  state.pending = False
165
165
  session.commit()
166
166
 
167
- def apply(self, session, desired, previous):
167
+ def apply(self, session, desired, previous, *, full=True):
168
168
  q = mysql_identifier
169
169
  with ExitStack() as resources:
170
170
  engine = self.backend.catalog.open_engine(self.source, resources)
@@ -288,7 +288,7 @@ class MSSQLAccess(HostedAccess):
288
288
  )
289
289
  return {(schema, name, referential_action(delete), referential_action(update)) for schema, name, delete, update in rows}
290
290
 
291
- def apply(self, session, desired, previous):
291
+ def apply(self, session, desired, previous, *, full=True):
292
292
  connection = session.connection()
293
293
  connection.engine.hide_parameters = True
294
294
  q = ms_identifier
@@ -5,7 +5,7 @@ from contextlib import contextmanager
5
5
 
6
6
  from sqlalchemy import text
7
7
 
8
- from metatables.api.backend.backends.access import DatabaseAccess
8
+ from metatables.api.backend.backends.access import DatabaseAccess, manifest_changes
9
9
  from metatables.api.backend.backends.contracts import SQLExecutionError
10
10
  from metatables.api.backend.persistence.models import SQLSecurityState
11
11
 
@@ -24,6 +24,8 @@ USER_SCHEMA = "{schema} !~ '^pg_' AND {schema} <> 'information_schema'"
24
24
 
25
25
 
26
26
  class PostgreSQLAccess(DatabaseAccess):
27
+ incremental = True
28
+
27
29
  def prerequisite_problems(self, connection):
28
30
  schema = getattr(self.source.connection, "default_schema", None) or "public"
29
31
  login, database, creates_roles, creates_schemas, catalog_owner, tables = connection.execute(text(
@@ -229,82 +231,84 @@ class PostgreSQLAccess(DatabaseAccess):
229
231
  targets.add((*hypertable, delete, update))
230
232
  return targets
231
233
 
232
- def reconcile(self, session, *, inspect_objects=False):
233
- if inspect_objects:
234
- state = session.get(SQLSecurityState, 1)
235
- roles = set(self.plan(session)["roles"]) | set(
236
- (state.manifest if state else {}).get("roles", {})
237
- )
238
- self.secure_routines(session.connection(), roles)
239
- return super().reconcile(session, inspect_objects=inspect_objects)
234
+ def object_fingerprint(self, connection):
235
+ """What the routine sweep secures: owned schemas and routines, and PUBLIC grants.
236
+
237
+ A change to any of them, such as a migration that adds a routine or grants
238
+ to PUBLIC, makes the next reconciliation sweep them again.
239
+ """
240
+ schemas = USER_SCHEMA.format(schema="n.nspname")
241
+ return connection.execute(text(
242
+ "SELECT md5(concat_ws('|', "
243
+ "(SELECT string_agg(n.oid::text, ',' ORDER BY n.oid) FROM pg_namespace n WHERE "
244
+ + schemas + " AND " + OWNED.format(owner="n.nspowner") + "), "
245
+ "(SELECT string_agg(p.oid::text || ':' || p.prosecdef::text, ',' ORDER BY p.oid) "
246
+ "FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace WHERE "
247
+ + schemas + " AND " + OWNED.format(owner="p.proowner") + "), "
248
+ "(SELECT count(*)::text FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace "
249
+ "CROSS JOIN LATERAL aclexplode(c.relacl) acl WHERE acl.grantee=0 AND "
250
+ + schemas + " AND " + OWNED.format(owner="c.relowner") + "), "
251
+ "(SELECT count(*)::text FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid "
252
+ "JOIN pg_namespace n ON n.oid=c.relnamespace CROSS JOIN LATERAL aclexplode(a.attacl) acl "
253
+ "WHERE acl.grantee=0 AND n.nspname !~ '^pg_' AND " + OWNED.format(owner="c.relowner") + ")"
254
+ "))"
255
+ )).scalar()
256
+
257
+ def reconcile(self, session, *, inspect_objects=False, tables=None):
258
+ state = session.get(SQLSecurityState, 1)
259
+ manifest = (state.manifest if state else None) or {}
260
+ connection = session.connection()
261
+ objects = self.object_fingerprint(connection)
262
+ if inspect_objects or manifest.get("objects") != objects:
263
+ roles = set(self.plan(session)["roles"]) | set(manifest.get("roles", {}))
264
+ self.secure_routines(connection, roles)
265
+ objects = self.object_fingerprint(connection)
266
+ super().reconcile(session, inspect_objects=inspect_objects, tables=tables)
267
+ state = session.get(SQLSecurityState, 1)
268
+ state.manifest = {**state.manifest, "objects": objects}
269
+ session.flush()
240
270
 
241
- def apply(self, session, desired, previous):
271
+ def apply(self, session, desired, previous, *, full=True):
242
272
  connection = session.connection()
243
273
  connection.engine.hide_parameters = True
244
- roles = desired["roles"]
245
274
  invoker = self.role("invoker", "routines")
246
- self._role(connection, invoker)
247
275
  database = connection.exec_driver_sql("SELECT current_database()").scalar()
276
+ changes = None if full else manifest_changes(previous, desired)
277
+ if changes is None:
278
+ return self._apply_all(connection, desired, previous, database=database, invoker=invoker)
279
+ roles = desired["roles"]
280
+ for name in sorted(changes.reset):
281
+ self._role(connection, name, self.password(name) if roles[name]["login"] else None)
282
+ for name in sorted(changes.reset | changes.retired):
283
+ login = name in roles and bool(roles[name]["login"])
284
+ self._reset_role(connection, name, login=login, database=database, invoker=invoker)
285
+ for member, parent in changes.revoke_memberships:
286
+ connection.exec_driver_sql(f"REVOKE {quote(parent)} FROM {quote(member)}")
287
+ for name, schema, table, _ in changes.revoke_privileges:
288
+ relation = f"{quote(schema)}.{quote(table)}"
289
+ # A dropped table took its grants with it.
290
+ if connection.execute(text("SELECT to_regclass(:relation) IS NOT NULL"), {"relation": relation}).scalar():
291
+ connection.exec_driver_sql(f"REVOKE ALL ON TABLE {relation} FROM {quote(name)}")
292
+ for name, schema in changes.revoke_schemas:
293
+ if connection.execute(text("SELECT to_regnamespace(:schema) IS NOT NULL"), {"schema": quote(schema)}).scalar():
294
+ connection.exec_driver_sql(f"REVOKE USAGE ON SCHEMA {quote(schema)} FROM {quote(name)}")
295
+ for member, parent in changes.grant_memberships:
296
+ connection.exec_driver_sql(f"GRANT {quote(parent)} TO {quote(member)}")
297
+ for schema in sorted({schema for _, schema, _, _ in changes.grant_privileges} - {"metatables"}):
298
+ connection.exec_driver_sql(f"GRANT USAGE ON SCHEMA {quote(schema)} TO {quote(invoker)}")
299
+ self._grant_privileges(connection, changes.grant_privileges)
300
+
301
+ def _apply_all(self, connection, desired, previous, *, database, invoker):
302
+ """The full rebuild: every role is reset and granted again, repairing drift."""
303
+ roles = desired["roles"]
304
+ self._role(connection, invoker)
248
305
  for name, definition in roles.items():
249
306
  self._role(connection, name, self.password(name) if definition["login"] else None)
250
307
  names = set(roles) | set(previous.get("roles", {})) | {invoker}
251
308
  schemas = self.owned_schemas(connection)
252
309
  for name in sorted(names):
253
- owned = connection.execute(
254
- text(
255
- "SELECT 1 FROM pg_class WHERE relowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_namespace WHERE nspowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_proc WHERE proowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_database WHERE datdba=(SELECT oid FROM pg_roles WHERE rolname=:name)"
256
- ),
257
- {"name": name},
258
- ).first()
259
- if owned:
260
- raise SQLExecutionError(code="sql_principal_permission_drift")
261
- # Repair inherited drift as well as direct table privileges.
262
- parents = (
263
- connection.execute(
264
- text(
265
- "SELECT parent.rolname FROM pg_auth_members m JOIN pg_roles child ON child.oid=m.member JOIN pg_roles parent ON parent.oid=m.roleid WHERE child.rolname=:name"
266
- ),
267
- {"name": name},
268
- )
269
- .scalars()
270
- .all()
271
- )
272
- for parent in parents:
273
- connection.exec_driver_sql(f"REVOKE {quote(parent)} FROM {quote(name)}")
274
- connection.exec_driver_sql(
275
- f"REVOKE ALL ON DATABASE {quote(database)} FROM {quote(name)}"
276
- )
277
- # Revoke this role's grants on owned objects; other owners' grants are theirs.
278
- granted = connection.execute(
279
- text(
280
- "SELECT 'SCHEMA', quote_ident(n.nspname) FROM pg_namespace n CROSS JOIN LATERAL aclexplode(n.nspacl) acl "
281
- "JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND " + OWNED.format(owner="n.nspowner")
282
- + " UNION SELECT CASE WHEN c.relkind='S' THEN 'SEQUENCE' ELSE 'TABLE' END, "
283
- "quote_ident(n.nspname) || '.' || quote_ident(c.relname) FROM pg_class c "
284
- "JOIN pg_namespace n ON n.oid=c.relnamespace CROSS JOIN LATERAL aclexplode(c.relacl) acl "
285
- "JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND " + OWNED.format(owner="c.relowner")
286
- ),
287
- {"name": name},
288
- ).all()
289
- for kind, target in granted:
290
- connection.exec_driver_sql(f"REVOKE ALL ON {kind} {target} FROM {quote(name)}")
291
- # Table-level REVOKE does not remove separately granted column ACLs.
292
- columns = connection.execute(
293
- text(
294
- "SELECT n.nspname, c.relname, a.attname FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace CROSS JOIN LATERAL aclexplode(a.attacl) acl JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND n.nspname !~ '^pg_' AND "
295
- + OWNED.format(owner="c.relowner")
296
- ),
297
- {"name": name},
298
- ).all()
299
- for schema, table, column in columns:
300
- connection.exec_driver_sql(
301
- f"REVOKE ALL ({quote(column)}) ON TABLE {quote(schema)}.{quote(table)} FROM {quote(name)}"
302
- )
303
- if name in roles and roles[name]["login"]:
304
- connection.exec_driver_sql(
305
- f"GRANT CONNECT ON DATABASE {quote(database)} TO {quote(name)}"
306
- )
307
- connection.exec_driver_sql(f"GRANT {quote(invoker)} TO {quote(name)}")
310
+ login = name in roles and bool(roles[name]["login"])
311
+ self._reset_role(connection, name, login=login, database=database, invoker=invoker)
308
312
  for schema in schemas:
309
313
  if schema != "metatables":
310
314
  connection.exec_driver_sql(
@@ -312,13 +316,74 @@ class PostgreSQLAccess(DatabaseAccess):
312
316
  )
313
317
  for member, parent in desired["memberships"]:
314
318
  connection.exec_driver_sql(f"GRANT {quote(parent)} TO {quote(member)}")
315
- for name, schema, table, write in desired["privileges"]:
319
+ self._grant_privileges(connection, desired["privileges"])
320
+
321
+ def _grant_privileges(self, connection, privileges):
322
+ for name, schema, table, write in privileges:
316
323
  connection.exec_driver_sql(f"GRANT USAGE ON SCHEMA {quote(schema)} TO {quote(name)}")
317
324
  permissions = "SELECT, INSERT, UPDATE, DELETE" if write else "SELECT"
318
325
  connection.exec_driver_sql(
319
326
  f"GRANT {permissions} ON TABLE {quote(schema)}.{quote(table)} TO {quote(name)}"
320
327
  )
321
328
 
329
+ def _reset_role(self, connection, name, *, login, database, invoker):
330
+ """Leave ``name`` with only CONNECT and the routine invoker, if it logs in."""
331
+ owned = connection.execute(
332
+ text(
333
+ "SELECT 1 FROM pg_class WHERE relowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_namespace WHERE nspowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_proc WHERE proowner=(SELECT oid FROM pg_roles WHERE rolname=:name) UNION ALL SELECT 1 FROM pg_database WHERE datdba=(SELECT oid FROM pg_roles WHERE rolname=:name)"
334
+ ),
335
+ {"name": name},
336
+ ).first()
337
+ if owned:
338
+ raise SQLExecutionError(code="sql_principal_permission_drift")
339
+ # Repair inherited drift as well as direct table privileges.
340
+ parents = (
341
+ connection.execute(
342
+ text(
343
+ "SELECT parent.rolname FROM pg_auth_members m JOIN pg_roles child ON child.oid=m.member JOIN pg_roles parent ON parent.oid=m.roleid WHERE child.rolname=:name"
344
+ ),
345
+ {"name": name},
346
+ )
347
+ .scalars()
348
+ .all()
349
+ )
350
+ for parent in parents:
351
+ connection.exec_driver_sql(f"REVOKE {quote(parent)} FROM {quote(name)}")
352
+ connection.exec_driver_sql(
353
+ f"REVOKE ALL ON DATABASE {quote(database)} FROM {quote(name)}"
354
+ )
355
+ # Revoke this role's grants on owned objects; other owners' grants are theirs.
356
+ granted = connection.execute(
357
+ text(
358
+ "SELECT 'SCHEMA', quote_ident(n.nspname) FROM pg_namespace n CROSS JOIN LATERAL aclexplode(n.nspacl) acl "
359
+ "JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND " + OWNED.format(owner="n.nspowner")
360
+ + " UNION SELECT CASE WHEN c.relkind='S' THEN 'SEQUENCE' ELSE 'TABLE' END, "
361
+ "quote_ident(n.nspname) || '.' || quote_ident(c.relname) FROM pg_class c "
362
+ "JOIN pg_namespace n ON n.oid=c.relnamespace CROSS JOIN LATERAL aclexplode(c.relacl) acl "
363
+ "JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND " + OWNED.format(owner="c.relowner")
364
+ ),
365
+ {"name": name},
366
+ ).all()
367
+ for kind, target in granted:
368
+ connection.exec_driver_sql(f"REVOKE ALL ON {kind} {target} FROM {quote(name)}")
369
+ # Table-level REVOKE does not remove separately granted column ACLs.
370
+ columns = connection.execute(
371
+ text(
372
+ "SELECT n.nspname, c.relname, a.attname FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace CROSS JOIN LATERAL aclexplode(a.attacl) acl JOIN pg_roles r ON r.oid=acl.grantee WHERE r.rolname=:name AND n.nspname !~ '^pg_' AND "
373
+ + OWNED.format(owner="c.relowner")
374
+ ),
375
+ {"name": name},
376
+ ).all()
377
+ for schema, table, column in columns:
378
+ connection.exec_driver_sql(
379
+ f"REVOKE ALL ({quote(column)}) ON TABLE {quote(schema)}.{quote(table)} FROM {quote(name)}"
380
+ )
381
+ if login:
382
+ connection.exec_driver_sql(
383
+ f"GRANT CONNECT ON DATABASE {quote(database)} TO {quote(name)}"
384
+ )
385
+ connection.exec_driver_sql(f"GRANT {quote(invoker)} TO {quote(name)}")
386
+
322
387
  @contextmanager
323
388
  def connection(self, identity, *, write, timeout):
324
389
  import psycopg
@@ -10,6 +10,8 @@ from metatables.api.backend.persistence.models import Base, SQLSecurityState
10
10
 
11
11
 
12
12
  class SQLiteAccess(DatabaseAccess):
13
+ incremental = True
14
+
13
15
  def submit(self, cursor, statement, parameters):
14
16
  cursor.execute(statement, parameters)
15
17
 
@@ -75,7 +77,7 @@ class SQLiteAccess(DatabaseAccess):
75
77
  )
76
78
  return targets
77
79
 
78
- def apply(self, session, desired, previous):
80
+ def apply(self, session, desired, previous, *, full=True):
79
81
  # The immutable grant snapshot is installed on each dedicated connection.
80
82
  return None
81
83