matrx-orm 3.1.211__tar.gz → 3.1.213__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.
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/PKG-INFO +1 -1
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/__init__.py +2 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/diagnostics.py +74 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/package_wiring.py +37 -4
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/pyproject.toml +1 -6
- matrx_orm-3.1.213/tests/test_package_wiring_views.py +46 -0
- matrx_orm-3.1.211/matrx_orm/matrx_orm_production_door.pth +0 -3
- matrx_orm-3.1.211/matrx_orm/pytest_live_db_guard.py +0 -272
- matrx_orm-3.1.211/matrx_orm/pytest_production_door.py +0 -428
- matrx_orm-3.1.211/tests/session/test_live_db_guard_plugin.py +0 -210
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/.gitignore +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/AGENTS.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/CHANGELOG.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/CLAUDE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/MODEL_API.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/docs/migrations.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/admin_lane.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/read_write.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/session_context.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/statement_ceiling.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/core/write_retry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/no_org_assignment.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/catalog_select.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/platform_access.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/pytest_lock_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/pytest_plugin.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/resources/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/resources/additional-assigners-2026-09-12.json +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/resources/org_assignment_trigger_baseline.json +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/excluded_targets.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/backup_restore.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/mutation_receipts.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/native_enable.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/native_lifecycle.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/native_passkeys.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/native_source.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/org_vault_gate.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/secrets_battery/vault_history.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/matrx_orm/write_actor.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/scripts/release.sh +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/conftest.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_adapter_registry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_association_trigger_actor_naming.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_associations_wiring.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_column_scoped_writes.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_committed_row_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_count_limit_param_leak.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_deadlock_retry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_fk_cycle_resolution.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_lock_contention_retry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_org_assignment_inventory.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_orm_banners_are_client_safe.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_percentile_cont.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_persisted_count.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_person_scoped_session_bypasses_shared_cache.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_pool_create_never_wedges.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_read_write_declared.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_standalone_write_session_context.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_transaction_database_identity.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_transaction_gucs_one_round_trip.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_transaction_pool_release_sends_nothing.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_write_queue_deadline.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/level2/verify_committed_row_guard_pg17.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/native_source_cases.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/native_source_oracle.rs +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_excluded_fk_targets.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/schema_builder/test_never_filter_columns.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_a_failed_capture_still_names_the_failure.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_record_error_bounded_insert.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_record_error_storm.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/session/test_spill_guard_plugin.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_a_backend_handed_over_mid_transaction_never_takes_our_writes.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_a_list_of_uuids_binds_as_uuid_array.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_a_read_only_backend_never_refuses_our_writes.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_a_sealed_field_shows_no_character_of_its_value.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_array_arg_element_type.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_attachment_mutation_serialization.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_backup_alias_conflict.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_backup_history_restore.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_backup_restore_live.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_call_function_as.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_call_function_none_mode.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_composite_fk_is_not_a_column_fk.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_dsn_password_masking.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_dynamic_select_unregistered.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_immutable_insert_or_exact_verify.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_keyed_digest.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_native_enable.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_native_lifecycle.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_native_lifecycle_fences.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_native_passkey_receipts.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_native_source.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_order_by_desc_nulls_last.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_org_vault_gate.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_secret_audit_names_its_organization.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_shared_lock_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_statement_ceiling_warning.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_sync_twins_guard.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_update_result_truthiness.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_user_visible_lookup.py +0 -0
- {matrx_orm-3.1.211 → matrx_orm-3.1.213}/tests/test_vault_aggregate_recovery_stateful.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.213
|
|
4
4
|
Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
|
|
5
5
|
Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
|
|
6
6
|
Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
|
|
@@ -73,6 +73,7 @@ from .core.diagnostics import (
|
|
|
73
73
|
log_pool_diagnostics,
|
|
74
74
|
long_transactions,
|
|
75
75
|
long_transactions_sql,
|
|
76
|
+
probe_server_vitals,
|
|
76
77
|
)
|
|
77
78
|
from .core.introspection import (
|
|
78
79
|
introspect_column_shapes,
|
|
@@ -474,6 +475,7 @@ __all__ = [
|
|
|
474
475
|
"LONG_TRANSACTION_SECONDS",
|
|
475
476
|
"long_transactions",
|
|
476
477
|
"long_transactions_sql",
|
|
478
|
+
"probe_server_vitals",
|
|
477
479
|
"describe_transaction",
|
|
478
480
|
"describe_transactions",
|
|
479
481
|
"install_asyncpg_idle_close_filter",
|
|
@@ -339,3 +339,77 @@ async def introspect_lock_waits(
|
|
|
339
339
|
int(query_chars),
|
|
340
340
|
)
|
|
341
341
|
return [dict(r) for r in rows]
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
# ── Out-of-band server vitals ────────────────────────────────────────────────
|
|
345
|
+
#
|
|
346
|
+
# A watchdog that must notice the database being DOWN cannot borrow a pool
|
|
347
|
+
# connection: the pool is exactly what is exhausted or hung when it matters.
|
|
348
|
+
# ``probe_server_vitals`` opens ONE fresh connection with the registered
|
|
349
|
+
# config's own parameters (host, port, user, password, TLS), runs ``select 1``
|
|
350
|
+
# (timed) and one read-only catalog query, and closes it — the whole thing
|
|
351
|
+
# under one deadline, so a hung server is a ``TimeoutError``, never a hang.
|
|
352
|
+
|
|
353
|
+
_SERVER_VITALS_SQL = """
|
|
354
|
+
SELECT
|
|
355
|
+
(SELECT count(*) FROM pg_stat_activity)::int AS connections,
|
|
356
|
+
current_setting('max_connections')::int AS max_connections,
|
|
357
|
+
(SELECT count(*) FROM pg_stat_activity WHERE wait_event_type = 'Lock')::int AS lock_waiters,
|
|
358
|
+
COALESCE((
|
|
359
|
+
SELECT max(EXTRACT(EPOCH FROM (clock_timestamp() - query_start)))
|
|
360
|
+
FROM pg_stat_activity
|
|
361
|
+
WHERE state = 'active'
|
|
362
|
+
AND backend_type = 'client backend'
|
|
363
|
+
AND pid <> pg_backend_pid()
|
|
364
|
+
AND query_start IS NOT NULL
|
|
365
|
+
), 0)::float8 AS longest_active_seconds,
|
|
366
|
+
pg_postmaster_start_time() AS postmaster_started_at
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
async def probe_server_vitals(config_name: str, *, timeout_s: float) -> dict[str, Any]:
|
|
371
|
+
"""One fresh, short-lived connection's view of the server's health.
|
|
372
|
+
|
|
373
|
+
Returns ``latency_ms`` (the ``select 1`` round trip), ``connections``,
|
|
374
|
+
``max_connections``, ``lock_waiters``, ``longest_active_seconds`` (the
|
|
375
|
+
oldest running client statement, excluding this probe and replication)
|
|
376
|
+
and ``postmaster_started_at`` (a change means the server restarted).
|
|
377
|
+
|
|
378
|
+
Read-only. Never touches the shared pool. RAISES on any failure —
|
|
379
|
+
including ``TimeoutError`` when connect + both queries exceed
|
|
380
|
+
``timeout_s`` — because the caller's whole job is to count failures.
|
|
381
|
+
"""
|
|
382
|
+
import asyncio
|
|
383
|
+
import time
|
|
384
|
+
|
|
385
|
+
import asyncpg
|
|
386
|
+
|
|
387
|
+
from matrx_orm.core.tls import resolve_asyncpg_ssl
|
|
388
|
+
|
|
389
|
+
config = get_database_config(config_name)
|
|
390
|
+
ssl = await resolve_asyncpg_ssl(config.get("ssl", "require"))
|
|
391
|
+
|
|
392
|
+
async def _run() -> dict[str, Any]:
|
|
393
|
+
conn = await asyncpg.connect(
|
|
394
|
+
host=config["host"],
|
|
395
|
+
port=config["port"],
|
|
396
|
+
database=config["database_name"],
|
|
397
|
+
user=config["user"],
|
|
398
|
+
password=config["password"],
|
|
399
|
+
ssl=ssl,
|
|
400
|
+
timeout=timeout_s,
|
|
401
|
+
statement_cache_size=0,
|
|
402
|
+
server_settings={"application_name": "matrx_server_vitals_probe"},
|
|
403
|
+
)
|
|
404
|
+
try:
|
|
405
|
+
started = time.perf_counter()
|
|
406
|
+
await conn.fetchval("SELECT 1")
|
|
407
|
+
latency_ms = (time.perf_counter() - started) * 1000.0
|
|
408
|
+
row = await conn.fetchrow(_SERVER_VITALS_SQL)
|
|
409
|
+
finally:
|
|
410
|
+
conn.terminate()
|
|
411
|
+
result = dict(row) if row is not None else {}
|
|
412
|
+
result["latency_ms"] = round(latency_ms, 1)
|
|
413
|
+
return result
|
|
414
|
+
|
|
415
|
+
return await asyncio.wait_for(_run(), timeout=timeout_s)
|
|
@@ -179,8 +179,36 @@ def _lookup(inventory: dict[tuple[str, str], TableInfo], table: str) -> TableInf
|
|
|
179
179
|
return info
|
|
180
180
|
|
|
181
181
|
|
|
182
|
+
def _lookup_view(
|
|
183
|
+
inventory: dict[tuple[str, str], TableInfo], view: str, python_root: str | Path | None
|
|
184
|
+
) -> TableInfo:
|
|
185
|
+
if "." not in view:
|
|
186
|
+
raise PackageWiringError(f"package_wiring: view '{view}' must be '<schema>.<snake>'")
|
|
187
|
+
schema, snake = view.split(".", 1)
|
|
188
|
+
sibling = next((i for (s, _), i in inventory.items() if s == schema), None)
|
|
189
|
+
if sibling is None:
|
|
190
|
+
raise PackageWiringError(
|
|
191
|
+
f"package_wiring: view '{view}' — schema '{schema}' has no generated models module"
|
|
192
|
+
)
|
|
193
|
+
from matrx_orm.schema_builder.common import dt_utils, safe_model_class_name
|
|
194
|
+
|
|
195
|
+
pascal = safe_model_class_name(snake, schema, dt_utils.to_pascal_case)
|
|
196
|
+
if python_root is not None:
|
|
197
|
+
models_file = Path(python_root) / (sibling.models_module.replace(".", "/") + ".py")
|
|
198
|
+
tree = ast.parse(models_file.read_text(), filename=str(models_file))
|
|
199
|
+
if not any(isinstance(n, ast.ClassDef) and n.name == pascal for n in tree.body):
|
|
200
|
+
raise PackageWiringError(
|
|
201
|
+
f"package_wiring: view '{view}' has no generated class {pascal} in "
|
|
202
|
+
f"{models_file} — is the view in the schema and its view_primary_keys declared?"
|
|
203
|
+
)
|
|
204
|
+
return TableInfo(schema=schema, snake=snake, pascal=pascal, models_module=sibling.models_module)
|
|
205
|
+
|
|
206
|
+
|
|
182
207
|
def resolve_manifest(
|
|
183
|
-
name: str,
|
|
208
|
+
name: str,
|
|
209
|
+
req: dict[str, Any],
|
|
210
|
+
inventory: dict[tuple[str, str], TableInfo],
|
|
211
|
+
python_root: str | Path | None = None,
|
|
184
212
|
) -> ResolvedPackage:
|
|
185
213
|
target = req.get("target") or {}
|
|
186
214
|
configure_import = target.get("configure_import")
|
|
@@ -225,9 +253,14 @@ def resolve_manifest(
|
|
|
225
253
|
)
|
|
226
254
|
)
|
|
227
255
|
|
|
228
|
-
# Explicit models.
|
|
256
|
+
# Explicit models. A VIEW has a generated model class but no auto_config entry, so a
|
|
257
|
+
# manifest names it with "view" instead of "table"; it resolves by the generator's own
|
|
258
|
+
# class-naming rule and must exist in the schema's generated models file.
|
|
229
259
|
for entry in req.get("models") or []:
|
|
230
|
-
|
|
260
|
+
if "view" in entry:
|
|
261
|
+
info = _lookup_view(inventory, entry["view"], python_root)
|
|
262
|
+
else:
|
|
263
|
+
info = _lookup(inventory, entry["table"])
|
|
231
264
|
assignments.append(Assignment("models", entry["key"], info.models_module, info.pascal))
|
|
232
265
|
|
|
233
266
|
# Explicit bases.
|
|
@@ -421,7 +454,7 @@ def _resolve_all(cfg: dict[str, Any], python_root: str) -> tuple[str, list[Resol
|
|
|
421
454
|
f"package_wiring.packages entry needs 'name' and 'manifest_path': {entry}"
|
|
422
455
|
)
|
|
423
456
|
req = _load_manifest(Path(python_root) / manifest_path)
|
|
424
|
-
packages.append(resolve_manifest(name, req, inventory))
|
|
457
|
+
packages.append(resolve_manifest(name, req, inventory, python_root))
|
|
425
458
|
return output_module, packages
|
|
426
459
|
|
|
427
460
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.213"
|
|
4
4
|
description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -51,8 +51,6 @@ dependencies = [
|
|
|
51
51
|
[project.entry-points.pytest11]
|
|
52
52
|
matrx_write_spill_guard = "matrx_orm.pytest_plugin"
|
|
53
53
|
matrx_shared_lock_guard = "matrx_orm.pytest_lock_guard"
|
|
54
|
-
matrx_live_db_guard = "matrx_orm.pytest_live_db_guard"
|
|
55
|
-
matrx_production_door = "matrx_orm.pytest_production_door"
|
|
56
54
|
|
|
57
55
|
[project.urls]
|
|
58
56
|
Homepage = "https://github.com/AI-Matrix-Engine/aidream-current"
|
|
@@ -84,9 +82,6 @@ dev = [
|
|
|
84
82
|
packages = ["matrx_orm"]
|
|
85
83
|
include = ["matrx_orm/py.typed", "matrx_orm/resources/*.json"]
|
|
86
84
|
|
|
87
|
-
[tool.hatch.build.targets.wheel.force-include]
|
|
88
|
-
"matrx_orm/matrx_orm_production_door.pth" = "matrx_orm_production_door.pth"
|
|
89
|
-
|
|
90
85
|
[tool.hatch.metadata]
|
|
91
86
|
allow-direct-references = true
|
|
92
87
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""A manifest may wire a VIEW: views get a generated model class but no auto_config entry."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from matrx_orm.schema_builder.package_wiring import (
|
|
8
|
+
PackageWiringError,
|
|
9
|
+
TableInfo,
|
|
10
|
+
resolve_manifest,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
INVENTORY = {("ai", "setting"): TableInfo("ai", "setting", "Setting", "db.models.ai")}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _req(entry):
|
|
17
|
+
return {"target": {"configure_import": "x", "configure_call": "configure"}, "models": [entry]}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _root(tmp_path: Path, classes: str) -> Path:
|
|
21
|
+
(tmp_path / "db" / "models").mkdir(parents=True)
|
|
22
|
+
(tmp_path / "db" / "models" / "ai.py").write_text(classes)
|
|
23
|
+
return tmp_path
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_a_view_resolves_to_its_generated_class(tmp_path):
|
|
27
|
+
root = _root(tmp_path, "class Setting: pass\nclass OfferingRulesCompiled: pass\n")
|
|
28
|
+
pkg = resolve_manifest(
|
|
29
|
+
"p", _req({"key": "AiOfferingRulesCompiled", "view": "ai.offering_rules_compiled"}),
|
|
30
|
+
INVENTORY, root,
|
|
31
|
+
)
|
|
32
|
+
[a] = [x for x in pkg.assignments if x.key == "AiOfferingRulesCompiled"]
|
|
33
|
+
assert (a.module, a.symbol) == ("db.models.ai", "OfferingRulesCompiled")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_a_view_without_a_generated_class_is_refused(tmp_path):
|
|
37
|
+
root = _root(tmp_path, "class Setting: pass\n")
|
|
38
|
+
with pytest.raises(PackageWiringError, match="no generated class OfferingRulesCompiled"):
|
|
39
|
+
resolve_manifest(
|
|
40
|
+
"p", _req({"key": "K", "view": "ai.offering_rules_compiled"}), INVENTORY, root
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_a_table_entry_naming_a_view_is_still_refused():
|
|
45
|
+
with pytest.raises(PackageWiringError, match="not in the host inventory"):
|
|
46
|
+
resolve_manifest("p", _req({"key": "K", "table": "ai.offering_rules_compiled"}), INVENTORY)
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
# Installed by matrx-orm: in a process whose environment carries MATRX_PRODUCTION_DOOR=1 (exported by the
|
|
2
|
-
# pytest plugin matrx_orm.pytest_production_door), install the same production door before any user code.
|
|
3
|
-
import os; exec("import sys, importlib.util as u, importlib.machinery as m\ns = m.PathFinder.find_spec('matrx_orm')\nif s and s.submodule_search_locations and 'matrx_orm.pytest_production_door' not in sys.modules:\n sp = u.spec_from_file_location('matrx_orm.pytest_production_door', list(s.submodule_search_locations)[0] + '/pytest_production_door.py')\n mod = u.module_from_spec(sp); sys.modules[sp.name] = mod; sp.loader.exec_module(mod); mod.install()") if os.environ.get("MATRX_PRODUCTION_DOOR") == "1" else None
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
"""Session-wide guard: a test run never reaches the LIVE platform database by accident.
|
|
2
|
-
|
|
3
|
-
Registered as a ``pytest11`` entry point, so pytest loads it in every suite regardless of
|
|
4
|
-
rootdir — the same mechanism as the spill guard (``matrx_orm.pytest_plugin``) and the lock
|
|
5
|
-
guard (``matrx_orm.pytest_lock_guard``). This is the SEVENTH cross-suite hazard; the other six
|
|
6
|
-
are catalogued in the aidream repo-root ``conftest.py``.
|
|
7
|
-
|
|
8
|
-
WHY IT EXISTS (lane INTEG-SERVER, 2026-09-24). A developer's ``.env`` holds the five
|
|
9
|
-
``SUPABASE_MATRIX_*`` variables for the LIVE database, because that is what the server runs
|
|
10
|
-
on. Those variables SELECT a connection; they never AUTHORISED one. So every suite that
|
|
11
|
-
imports the host's ``db`` package — ``aidream/services/agent_data/tests/test_rls_data_access.py``
|
|
12
|
-
creates, edits and HARD-deletes notes — ran against production whenever it was collected,
|
|
13
|
-
with nobody having decided that. The matrx-records suite closed this for itself on 2026-09-22
|
|
14
|
-
(a declared target, default the rehearsal branch, main behind three locked doors); this closes
|
|
15
|
-
it for every suite, once, in the package that owns the connection.
|
|
16
|
-
|
|
17
|
-
THE RULE. Before any test module is imported, the connection the five variables (or the
|
|
18
|
-
``.env`` that will supply them) resolve to is compared with the live database's identity —
|
|
19
|
-
its project ref in the pooler user (``postgres.<ref>``) or a live host. When it IS the live
|
|
20
|
-
database:
|
|
21
|
-
|
|
22
|
-
* **Default:** the five variables are REPOINTED, in this process only, to the rehearsal
|
|
23
|
-
branch — ``MATRX_TEST_DATABASE_URL`` when set (any declared non-live target, e.g. the dev
|
|
24
|
-
clone), else ``SUPABASE_BRANCH_DATABASE_URL``. With neither, they point at an unreachable
|
|
25
|
-
placeholder (``127.0.0.1:1``), so a live test FAILS to connect instead of writing to
|
|
26
|
-
production. The banner says which, once.
|
|
27
|
-
* **Live, on purpose:** ``--live-db --live-db-reason "<why>"`` inside the 1–4 AM Pacific
|
|
28
|
-
maintenance window leaves them alone and prints the reason. The environment cannot open
|
|
29
|
-
this door (an exported variable outlives the shell that set it); a missing reason or a
|
|
30
|
-
time outside the window is a usage error that stops the session.
|
|
31
|
-
|
|
32
|
-
A connection that is NOT the live database — a local Postgres in CI, the branch, the clone —
|
|
33
|
-
is never touched. Values are never printed.
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
from __future__ import annotations
|
|
37
|
-
|
|
38
|
-
import os
|
|
39
|
-
from datetime import datetime
|
|
40
|
-
from urllib.parse import unquote, urlsplit
|
|
41
|
-
from zoneinfo import ZoneInfo
|
|
42
|
-
|
|
43
|
-
import pytest
|
|
44
|
-
|
|
45
|
-
#: The ONE live database (aidream CLAUDE.md), by the identities a connection can carry.
|
|
46
|
-
LIVE_PROJECT_REFS = frozenset({"brsgrqvjdzwihsvnfqkf"})
|
|
47
|
-
LIVE_HOSTS = frozenset({"db.matrxserver.com", "db.brsgrqvjdzwihsvnfqkf.supabase.co"})
|
|
48
|
-
|
|
49
|
-
DB_VARS = (
|
|
50
|
-
"SUPABASE_MATRIX_HOST",
|
|
51
|
-
"SUPABASE_MATRIX_PORT",
|
|
52
|
-
"SUPABASE_MATRIX_USER",
|
|
53
|
-
"SUPABASE_MATRIX_PASSWORD",
|
|
54
|
-
"SUPABASE_MATRIX_DATABASE_NAME",
|
|
55
|
-
)
|
|
56
|
-
TARGET_URL_VARS = ("MATRX_TEST_DATABASE_URL", "SUPABASE_BRANCH_DATABASE_URL")
|
|
57
|
-
WINDOW_TZ, WINDOW_START, WINDOW_END = "America/Los_Angeles", 1, 4
|
|
58
|
-
PLACEHOLDER = {
|
|
59
|
-
"SUPABASE_MATRIX_HOST": "127.0.0.1",
|
|
60
|
-
"SUPABASE_MATRIX_PORT": "1",
|
|
61
|
-
"SUPABASE_MATRIX_USER": "live-db-refused-under-pytest",
|
|
62
|
-
"SUPABASE_MATRIX_PASSWORD": "refused",
|
|
63
|
-
"SUPABASE_MATRIX_DATABASE_NAME": "refused",
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
#: THE HTTP ROUTE to the same database (2026-09-27). PostgREST, the admin door and the
|
|
67
|
-
#: Management API need no pool: a project URL plus the secret key (or the account access
|
|
68
|
-
#: token) reaches production by itself. Under pytest without --live-db, a live URL sends
|
|
69
|
-
#: every one of these to an unreachable placeholder too. Names cover the canonical
|
|
70
|
-
#: variables and the aliases the host materializes from them.
|
|
71
|
-
HTTP_URL_VARS = ("SUPABASE_MATRIX_URL", "SUPABASE_URL")
|
|
72
|
-
HTTP_SECRET_VARS = (
|
|
73
|
-
"SUPABASE_MATRIX_SECRET_KEY",
|
|
74
|
-
"SUPABASE_SECRET_KEY",
|
|
75
|
-
"SUPABASE_MATRIX_SERVICE_ROLE_KEY",
|
|
76
|
-
"SUPABASE_SERVICE_ROLE_KEY",
|
|
77
|
-
"SUPABASE_ACCESS_TOKEN",
|
|
78
|
-
)
|
|
79
|
-
HTTP_PLACEHOLDER_URL = "http://127.0.0.1:1"
|
|
80
|
-
HTTP_PLACEHOLDER_SECRET = "live-http-refused-under-pytest"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def is_live_url(url: str) -> bool:
|
|
84
|
-
"""Does this HTTP URL name the live project?"""
|
|
85
|
-
host = (urlsplit((url or "").strip()).hostname or "").lower()
|
|
86
|
-
return host in LIVE_HOSTS or any(host.startswith(f"{ref}.") for ref in LIVE_PROJECT_REFS)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def decide_http(env: dict[str, str], dotenv: dict[str, str], *, live_flag: bool) -> dict[str, str] | None:
|
|
90
|
-
"""The HTTP variables to overwrite, or None. Pure — the hook applies it.
|
|
91
|
-
|
|
92
|
-
Independent of the pool decision: a CI run on a local Postgres with a live URL
|
|
93
|
-
left in .env is exactly the case the pool guard cannot see.
|
|
94
|
-
"""
|
|
95
|
-
if live_flag:
|
|
96
|
-
return None
|
|
97
|
-
urls = {k: env.get(k) or dotenv.get(k, "") for k in HTTP_URL_VARS}
|
|
98
|
-
if not any(is_live_url(u) for u in urls.values()):
|
|
99
|
-
return None
|
|
100
|
-
out = {k: HTTP_PLACEHOLDER_URL for k in HTTP_URL_VARS}
|
|
101
|
-
out.update({k: HTTP_PLACEHOLDER_SECRET for k in HTTP_SECRET_VARS})
|
|
102
|
-
return out
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
#: The ONLY accounts a test may act as (workspace law: "use ONLY admin@admin.com, never Arman's
|
|
106
|
-
#: personal account"; test@test.com is the non-admin seat). By id, because an id is what a test
|
|
107
|
-
#: reads from ``TEST_USER_ID`` and an id cannot be mistaken for a similar email.
|
|
108
|
-
TEST_ACCOUNT_IDS = {
|
|
109
|
-
"87a6e699-3622-4869-8843-d0867456c0dd": "admin@admin.com",
|
|
110
|
-
"4060701e-706a-4c76-b3ca-0bbc69fa5a14": "test@test.com",
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def refuse_a_real_person(env: dict[str, str], dotenv: dict[str, str]) -> None:
|
|
115
|
-
"""``TEST_USER_ID`` must be one of the test accounts, or the session does not start."""
|
|
116
|
-
user = (env.get("TEST_USER_ID") or dotenv.get("TEST_USER_ID") or "").strip()
|
|
117
|
-
if user and user not in TEST_ACCOUNT_IDS:
|
|
118
|
-
raise pytest.UsageError(
|
|
119
|
-
"REFUSED: TEST_USER_ID is not a test account. Tests act ONLY as admin@admin.com "
|
|
120
|
-
"(or test@test.com for a non-admin seat) — never a real person's account, and never "
|
|
121
|
-
"the owner's personal one. Set TEST_USER_ID to admin@admin.com's user id. Nothing ran."
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
#: What this session decided, for tests and banners: "untouched" | "live" | "repointed:<var>"
|
|
126
|
-
#: | "placeholder".
|
|
127
|
-
DECISION: str = "untouched"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def is_live(user: str, host: str) -> bool:
|
|
131
|
-
"""Does this connection identity name the live database?"""
|
|
132
|
-
ref = user.split(".", 1)[1] if "." in (user or "") else ""
|
|
133
|
-
return ref in LIVE_PROJECT_REFS or (host or "").strip().lower() in LIVE_HOSTS
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def _dotenv_values() -> dict[str, str]:
|
|
137
|
-
"""The ``.env`` a later ``load_dotenv()`` would read — it never overrides what is set here."""
|
|
138
|
-
try:
|
|
139
|
-
from dotenv import dotenv_values, find_dotenv
|
|
140
|
-
except ImportError: # pragma: no cover — python-dotenv absent: env only
|
|
141
|
-
return {}
|
|
142
|
-
path = find_dotenv(usecwd=True)
|
|
143
|
-
return {k: v for k, v in (dotenv_values(path) if path else {}).items() if v is not None}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def _five_from_url(url: str) -> dict[str, str]:
|
|
147
|
-
parts = urlsplit(url)
|
|
148
|
-
return {
|
|
149
|
-
"SUPABASE_MATRIX_HOST": parts.hostname or "",
|
|
150
|
-
"SUPABASE_MATRIX_PORT": str(parts.port or 5432),
|
|
151
|
-
"SUPABASE_MATRIX_USER": unquote(parts.username or ""),
|
|
152
|
-
"SUPABASE_MATRIX_PASSWORD": unquote(parts.password or ""),
|
|
153
|
-
"SUPABASE_MATRIX_DATABASE_NAME": (parts.path or "/postgres").lstrip("/") or "postgres",
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def decide(
|
|
158
|
-
env: dict[str, str],
|
|
159
|
-
dotenv: dict[str, str],
|
|
160
|
-
*,
|
|
161
|
-
live_flag: bool,
|
|
162
|
-
reason: str,
|
|
163
|
-
now: datetime,
|
|
164
|
-
) -> tuple[str, dict[str, str] | None, str]:
|
|
165
|
-
"""``(decision, five variables to set or None, banner)``. Pure — the hook applies it."""
|
|
166
|
-
effective = {k: env.get(k) or dotenv.get(k, "") for k in DB_VARS}
|
|
167
|
-
if not is_live(effective["SUPABASE_MATRIX_USER"], effective["SUPABASE_MATRIX_HOST"]):
|
|
168
|
-
return "untouched", None, ""
|
|
169
|
-
if live_flag:
|
|
170
|
-
if not reason.strip():
|
|
171
|
-
raise pytest.UsageError(
|
|
172
|
-
"--live-db needs --live-db-reason \"<why>\": nothing else records why a test run "
|
|
173
|
-
"touched the live database."
|
|
174
|
-
)
|
|
175
|
-
local = now.astimezone(ZoneInfo(WINDOW_TZ))
|
|
176
|
-
if not (WINDOW_START <= local.hour < WINDOW_END):
|
|
177
|
-
raise pytest.UsageError(
|
|
178
|
-
f"--live-db refused: it is {local:%H:%M} Pacific, and the live database is open "
|
|
179
|
-
f"to test runs only {WINDOW_START:02d}:00–{WINDOW_END:02d}:00 Pacific."
|
|
180
|
-
)
|
|
181
|
-
return "live", None, f"── LIVE DATABASE under pytest · reason: {reason.strip()}"
|
|
182
|
-
for var in TARGET_URL_VARS:
|
|
183
|
-
url = env.get(var) or dotenv.get(var, "")
|
|
184
|
-
if url:
|
|
185
|
-
five = _five_from_url(url)
|
|
186
|
-
if is_live(five["SUPABASE_MATRIX_USER"], five["SUPABASE_MATRIX_HOST"]):
|
|
187
|
-
raise pytest.UsageError(f"{var} names the LIVE database; it cannot be a test target.")
|
|
188
|
-
return (
|
|
189
|
-
f"repointed:{var}",
|
|
190
|
-
five,
|
|
191
|
-
f"── the live database was configured; this test run uses {var} instead "
|
|
192
|
-
"(pass --live-db --live-db-reason inside 1–4 AM Pacific to reach live on purpose).",
|
|
193
|
-
)
|
|
194
|
-
return (
|
|
195
|
-
"placeholder",
|
|
196
|
-
dict(PLACEHOLDER),
|
|
197
|
-
"── the live database was configured and no test target is set "
|
|
198
|
-
"(MATRX_TEST_DATABASE_URL / SUPABASE_BRANCH_DATABASE_URL); database connections in this "
|
|
199
|
-
"run go to an unreachable placeholder and FAIL instead of reaching production.",
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
204
|
-
group = parser.getgroup("matrx-live-db", "the live platform database under pytest")
|
|
205
|
-
group.addoption("--live-db", action="store_true", default=False,
|
|
206
|
-
help="reach the LIVE database on purpose (needs --live-db-reason and 1-4 AM Pacific)")
|
|
207
|
-
group.addoption("--live-db-reason", action="store", default="",
|
|
208
|
-
help="why this run needs the live database")
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
_APPLIED = False
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def _apply(live_flag: bool, reason: str) -> None:
|
|
215
|
-
"""Decide once per process and repoint the five variables. Idempotent."""
|
|
216
|
-
global DECISION, _APPLIED
|
|
217
|
-
if _APPLIED:
|
|
218
|
-
return
|
|
219
|
-
refuse_a_real_person(dict(os.environ), _dotenv_values())
|
|
220
|
-
decision, five, banner = decide(
|
|
221
|
-
dict(os.environ),
|
|
222
|
-
_dotenv_values(),
|
|
223
|
-
live_flag=live_flag,
|
|
224
|
-
reason=reason,
|
|
225
|
-
now=datetime.now(ZoneInfo(WINDOW_TZ)),
|
|
226
|
-
)
|
|
227
|
-
DECISION = decision
|
|
228
|
-
_APPLIED = True
|
|
229
|
-
if five is not None:
|
|
230
|
-
os.environ.update(five)
|
|
231
|
-
if banner:
|
|
232
|
-
print(banner)
|
|
233
|
-
http = decide_http(dict(os.environ), _dotenv_values(), live_flag=live_flag)
|
|
234
|
-
if http is not None:
|
|
235
|
-
os.environ.update(http)
|
|
236
|
-
print(
|
|
237
|
-
"── the live Supabase HTTP API was configured; its URL and secret keys point at an "
|
|
238
|
-
"unreachable placeholder in this run (pass --live-db --live-db-reason inside 1–4 AM "
|
|
239
|
-
"Pacific to reach live on purpose)."
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
@pytest.hookimpl(tryfirst=True)
|
|
244
|
-
def pytest_load_initial_conftests(early_config: pytest.Config, parser: pytest.Parser, args: list[str]) -> None:
|
|
245
|
-
"""THE EARLIEST POINT a plugin can act, and the one that matters (2026-09-27).
|
|
246
|
-
|
|
247
|
-
pytest imports every command-line path's ``conftest.py`` — and that conftest's
|
|
248
|
-
package ``__init__`` — during THIS hook, before ``pytest_configure``. A package
|
|
249
|
-
``__init__`` that imports a module which registers the database pool (aidream's
|
|
250
|
-
``aidream/api/mcp/agent_service/__init__.py`` → server → ``db``) froze the LIVE
|
|
251
|
-
identity into the pool for the whole session while the repoint was still waiting in
|
|
252
|
-
``pytest_configure``. The options are already parsed here
|
|
253
|
-
(``early_config.known_args_namespace``), so the decision runs before any conftest.
|
|
254
|
-
"""
|
|
255
|
-
ns = early_config.known_args_namespace
|
|
256
|
-
_apply(
|
|
257
|
-
bool(getattr(ns, "live_db", False)),
|
|
258
|
-
str(getattr(ns, "live_db_reason", "") or ""),
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
@pytest.hookimpl(tryfirst=True)
|
|
263
|
-
def pytest_configure(config: pytest.Config) -> None:
|
|
264
|
-
# Normally a no-op: pytest_load_initial_conftests already decided. Kept for runs
|
|
265
|
-
# that bypass initial-conftest loading (pytest.main with plugins=, --noconftest).
|
|
266
|
-
_apply(
|
|
267
|
-
bool(config.getoption("--live-db", default=False)),
|
|
268
|
-
str(config.getoption("--live-db-reason", default="") or ""),
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
__all__ = ["decide_http", "is_live_url", "DECISION", "TEST_ACCOUNT_IDS", "refuse_a_real_person", "LIVE_HOSTS", "LIVE_PROJECT_REFS", "decide", "is_live"]
|