matrx-orm 3.1.138__tar.gz → 3.1.140__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.138 → matrx_orm-3.1.140}/PKG-INFO +2 -2
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/FEATURE.md +35 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/__init__.py +2 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/catalog.py +42 -7
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/async_db_manager.py +114 -1
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/exceptions.py +75 -0
- matrx_orm-3.1.140/matrx_orm/no_org_assignment.py +79 -0
- matrx_orm-3.1.140/matrx_orm/resources/__init__.py +1 -0
- matrx_orm-3.1.140/matrx_orm/resources/additional-assigners-2026-09-12.json +352 -0
- matrx_orm-3.1.140/matrx_orm/resources/org_assignment_trigger_baseline.json +503 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/__init__.py +14 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/items.py +8 -2
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/model.py +30 -0
- matrx_orm-3.1.140/matrx_orm/secrets_battery/mutation_receipts.py +164 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/org_service.py +19 -17
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/pyproject.toml +3 -3
- matrx_orm-3.1.140/tests/level1/test_lock_contention_retry.py +194 -0
- matrx_orm-3.1.140/tests/level1/test_org_assignment_inventory.py +666 -0
- matrx_orm-3.1.140/tests/level1/test_standalone_write_session_context.py +81 -0
- matrx_orm-3.1.138/tests/level1/test_org_assignment_inventory.py +0 -105
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/.gitignore +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/AGENTS.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/CLAUDE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/MODEL_API.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/docs/migrations.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/session_context.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/catalog_select.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/platform_access.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/pytest_plugin.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/scripts/release.sh +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/conftest.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_adapter_registry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_associations_wiring.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_count_limit_param_leak.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_persisted_count.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_write_queue_deadline.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_record_error_bounded_insert.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_record_error_storm.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/session/test_spill_guard_plugin.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_array_arg_element_type.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_dynamic_select_unregistered.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_keyed_digest.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_order_by_desc_nulls_last.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.138 → matrx_orm-3.1.140}/tests/test_sync_twins_guard.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.140
|
|
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
|
|
@@ -25,7 +25,7 @@ Requires-Python: >=3.13
|
|
|
25
25
|
Requires-Dist: asyncpg>=0.31.0
|
|
26
26
|
Requires-Dist: cryptography>=43.0
|
|
27
27
|
Requires-Dist: gitpython>=3.1.40
|
|
28
|
-
Requires-Dist: matrx-utils>=2.0.
|
|
28
|
+
Requires-Dist: matrx-utils>=2.0.36
|
|
29
29
|
Requires-Dist: psycopg-pool>=3.2.5
|
|
30
30
|
Requires-Dist: psycopg[binary]>=3.2.5
|
|
31
31
|
Requires-Dist: python-dotenv>=1.0
|
|
@@ -96,8 +96,31 @@
|
|
|
96
96
|
structured error context stay usable even when their caller has only the
|
|
97
97
|
typed predicate object.
|
|
98
98
|
|
|
99
|
+
## Organization-assignment retirements are reviewed proposals
|
|
100
|
+
|
|
101
|
+
- **The packaged genesis remains immutable.**
|
|
102
|
+
`scripts/validate_org_backstop_coverage.py` reads the digest-pinned package
|
|
103
|
+
resource; it never writes an installed wheel or the source resource in place.
|
|
104
|
+
- **A verified removal writes an explicit proposal.** Run
|
|
105
|
+
`--update-baseline --baseline-output <new-path>` only after the authenticated
|
|
106
|
+
inventory has no additions. The command refuses growth, bad database/function
|
|
107
|
+
evidence, and an existing output path.
|
|
108
|
+
- **A function retirement needs review evidence.** The immutable 16-root census
|
|
109
|
+
always returns every requested identity; an absent row is eligible only with
|
|
110
|
+
`--function-retirement-evidence <json>` mapping that exact qualified root to
|
|
111
|
+
a nonempty review reference and no live attachments.
|
|
112
|
+
- **Review and commit the proposal before packaging it.** Replace
|
|
113
|
+
`resources/org_assignment_trigger_baseline.json` in a normal source commit,
|
|
114
|
+
then build the wheel so standalone installs consume the reviewed retirement.
|
|
115
|
+
|
|
99
116
|
## Change Log
|
|
100
117
|
|
|
118
|
+
- 2026-09-12 — Made organization-assignment retirement output an explicit,
|
|
119
|
+
non-overwriting review proposal; a checked-in resource update is required
|
|
120
|
+
before the next standalone wheel carries a retirement.
|
|
121
|
+
- 2026-09-12 — Preserved every requested assignment-function row through the
|
|
122
|
+
catalog gate so an evidence-backed, attachment-free function retirement can
|
|
123
|
+
be proposed without weakening the immutable 16-root census.
|
|
101
124
|
- 2026-09-11 — Made disk-spill recovery tolerate deleted actors without losing
|
|
102
125
|
the spill, its original actor evidence, or system ownership.
|
|
103
126
|
- 2026-09-10 — Added stable semantic `Predicate.describe()` rendering for
|
|
@@ -125,6 +148,18 @@
|
|
|
125
148
|
schema-qualified known assigner functions and every `organization_id` column
|
|
126
149
|
default so the release ratchet can block growth without treating an automatic
|
|
127
150
|
assignment as protection.
|
|
151
|
+
- 2026-09-12 — Hardened the assignment inventory contract with the measured
|
|
152
|
+
database identity and all eight requested function roots. The ratchet retains
|
|
153
|
+
its captured genesis list and digest; verified removals are ledger entries, so
|
|
154
|
+
a same-count baseline edit cannot replace historical debt.
|
|
155
|
+
- 2026-09-12 — Added a second digest-pinned census for eight later-discovered
|
|
156
|
+
assigner roots and 32 attachments. The original genesis is untouched; exact
|
|
157
|
+
function and trigger evidence is measured, and only recorded retirements can
|
|
158
|
+
reduce the known debt.
|
|
159
|
+
- 2026-09-12 — Made `matrx_orm.resources` the canonical distributable owner of
|
|
160
|
+
both assignment-debt ledgers. `no_org_assignment` resolves them through
|
|
161
|
+
`importlib.resources`, so the 16-root catalog contract and its source-gate
|
|
162
|
+
wrapper work from a wheel without a sibling repository.
|
|
128
163
|
- 2026-08-21 — Fixed the `ON CONFLICT` retry counter in `_bulk_insert_failures`:
|
|
129
164
|
it qualified the target as `public.system_write_failure`, which no longer
|
|
130
165
|
exists, so every retry-conflict capture raised `UndefinedTableError` and
|
|
@@ -300,6 +300,7 @@ from .exceptions import (
|
|
|
300
300
|
ParameterError,
|
|
301
301
|
PermissionDeniedError,
|
|
302
302
|
PoolAcquireTimeoutError,
|
|
303
|
+
LockContentionError,
|
|
303
304
|
ReadOnlyTransactionError,
|
|
304
305
|
QueryError,
|
|
305
306
|
QueryTimeoutError,
|
|
@@ -718,6 +719,7 @@ __all__ = [
|
|
|
718
719
|
"ConnectionError",
|
|
719
720
|
"IntegrityError",
|
|
720
721
|
"PoolAcquireTimeoutError",
|
|
722
|
+
"LockContentionError",
|
|
721
723
|
"ReadOnlyTransactionError",
|
|
722
724
|
"QueryTimeoutError",
|
|
723
725
|
"TransactionError",
|
|
@@ -5,8 +5,9 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from .catalog_sql import
|
|
8
|
+
from .catalog_sql import PG_CATALOG_TABLES_CTE
|
|
9
9
|
from .core.async_db_manager import AsyncDatabaseManager
|
|
10
|
+
from .no_org_assignment import organization_assignment_function_identities
|
|
10
11
|
|
|
11
12
|
__all__ = [
|
|
12
13
|
"actor_stamp_column_drift",
|
|
@@ -484,7 +485,7 @@ async def publication_column_status(
|
|
|
484
485
|
async def organization_assignment_inventory(
|
|
485
486
|
database: str,
|
|
486
487
|
*,
|
|
487
|
-
function_identities: list[tuple[str, str]],
|
|
488
|
+
function_identities: list[tuple[str, str]] | None = None,
|
|
488
489
|
) -> dict[str, list[dict[str, Any]]]:
|
|
489
490
|
"""Inventory known database organization assigners and column defaults.
|
|
490
491
|
|
|
@@ -492,9 +493,36 @@ async def organization_assignment_inventory(
|
|
|
492
493
|
must provide ``organization_id`` itself; discovering one of these rows is
|
|
493
494
|
evidence to remove, not a reason to permit a missing value.
|
|
494
495
|
"""
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
identities = function_identities or list(organization_assignment_function_identities())
|
|
497
|
+
schemas = [schema for schema, _ in identities]
|
|
498
|
+
names = [name for _, name in identities]
|
|
499
|
+
metadata_rows, function_rows, trigger_rows, default_rows = await asyncio.gather(
|
|
500
|
+
_query(
|
|
501
|
+
database,
|
|
502
|
+
"SELECT current_database() AS database_name",
|
|
503
|
+
),
|
|
504
|
+
_query(
|
|
505
|
+
database,
|
|
506
|
+
"""
|
|
507
|
+
WITH requested AS (
|
|
508
|
+
SELECT function_schema, function_name
|
|
509
|
+
FROM unnest($1::text[], $2::text[])
|
|
510
|
+
AS requested(function_schema, function_name)
|
|
511
|
+
)
|
|
512
|
+
SELECT r.function_schema, r.function_name,
|
|
513
|
+
p.oid::text AS function_oid,
|
|
514
|
+
pg_get_function_identity_arguments(p.oid) AS identity_arguments,
|
|
515
|
+
md5(pg_get_functiondef(p.oid)) AS definition_md5,
|
|
516
|
+
p.oid IS NOT NULL AS present
|
|
517
|
+
FROM requested r
|
|
518
|
+
LEFT JOIN pg_namespace n ON n.nspname = r.function_schema
|
|
519
|
+
LEFT JOIN pg_proc p ON p.pronamespace = n.oid
|
|
520
|
+
AND p.proname = r.function_name
|
|
521
|
+
ORDER BY r.function_schema, r.function_name
|
|
522
|
+
""",
|
|
523
|
+
schemas,
|
|
524
|
+
names,
|
|
525
|
+
),
|
|
498
526
|
_query(
|
|
499
527
|
database,
|
|
500
528
|
"""
|
|
@@ -504,7 +532,9 @@ async def organization_assignment_inventory(
|
|
|
504
532
|
AS requested(function_schema, function_name)
|
|
505
533
|
)
|
|
506
534
|
SELECT pns.nspname AS function_schema, p.proname AS function_name,
|
|
507
|
-
tns.nspname AS schema, c.relname AS table, t.tgname AS trigger
|
|
535
|
+
tns.nspname AS schema, c.relname AS table, t.tgname AS trigger,
|
|
536
|
+
t.tgenabled::text AS enabled, t.oid::text AS trigger_oid,
|
|
537
|
+
pg_get_triggerdef(t.oid) AS definition
|
|
508
538
|
FROM pg_trigger t
|
|
509
539
|
JOIN pg_class c ON c.oid = t.tgrelid
|
|
510
540
|
JOIN pg_namespace tns ON tns.oid = c.relnamespace
|
|
@@ -534,7 +564,12 @@ async def organization_assignment_inventory(
|
|
|
534
564
|
""",
|
|
535
565
|
),
|
|
536
566
|
)
|
|
537
|
-
return {
|
|
567
|
+
return {
|
|
568
|
+
"metadata": metadata_rows,
|
|
569
|
+
"functions": function_rows,
|
|
570
|
+
"triggers": trigger_rows,
|
|
571
|
+
"defaults": default_rows,
|
|
572
|
+
}
|
|
538
573
|
|
|
539
574
|
|
|
540
575
|
async def trigger_function_usage(
|
|
@@ -5,6 +5,7 @@ from dataclasses import dataclass
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
+
import random
|
|
8
9
|
import traceback
|
|
9
10
|
from contextlib import asynccontextmanager
|
|
10
11
|
from typing import Any
|
|
@@ -31,6 +32,7 @@ from matrx_orm.exceptions import (
|
|
|
31
32
|
DatabaseConnectError,
|
|
32
33
|
DatabaseError,
|
|
33
34
|
IntegrityError,
|
|
35
|
+
LockContentionError,
|
|
34
36
|
ParameterError,
|
|
35
37
|
PermissionDeniedError,
|
|
36
38
|
PoolAcquireTimeoutError,
|
|
@@ -72,6 +74,24 @@ _SCHEMA_MISMATCH_EXC = (
|
|
|
72
74
|
asyncpg.exceptions.InvalidSchemaNameError,
|
|
73
75
|
)
|
|
74
76
|
|
|
77
|
+
# Cancelled to break a lock collision. ``TransactionRollbackError`` is an
|
|
78
|
+
# umbrella for every SQLSTATE 40xxx, including 40003 (completion unknown) and
|
|
79
|
+
# 40002 (transaction integrity constraint violation). Only the three explicit
|
|
80
|
+
# statuses below establish that PostgreSQL aborted this statement in full.
|
|
81
|
+
_CONTENTION_EXC = (
|
|
82
|
+
asyncpg.exceptions.TransactionRollbackError,
|
|
83
|
+
asyncpg.exceptions.LockNotAvailableError,
|
|
84
|
+
)
|
|
85
|
+
_CONTENTION_SQLSTATES = frozenset({"40P01", "40001", "55P03"})
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _is_confidently_aborted_lock_contention(exc: BaseException) -> bool:
|
|
89
|
+
"""Whether ``exc`` proves a standalone statement can be re-issued."""
|
|
90
|
+
return (
|
|
91
|
+
isinstance(exc, _CONTENTION_EXC)
|
|
92
|
+
and getattr(exc, "sqlstate", None) in _CONTENTION_SQLSTATES
|
|
93
|
+
)
|
|
94
|
+
|
|
75
95
|
# PostgreSQL emits these SQLSTATE class-57 errors while asyncpg is opening a
|
|
76
96
|
# physical connection during a server restart/failover. They happen before a
|
|
77
97
|
# checkout exists, so no caller SQL was sent and a replay-safe owner may retry.
|
|
@@ -123,6 +143,22 @@ POOL_RELEASE_TIMEOUT_SECONDS = 10.0
|
|
|
123
143
|
READ_TIMEOUT_RETRIES = 1 # extra attempts for a timed-out read; total = 1 + this
|
|
124
144
|
READ_TIMEOUT_RETRY_BACKOFF = 0.25 # seconds before the read retry
|
|
125
145
|
|
|
146
|
+
# ── lock collisions (40P01 / 40001 / 55P03) ──────────────────────────────────
|
|
147
|
+
# Postgres breaks a lock cycle by CANCELLING one party, and the victim is rolled
|
|
148
|
+
# back IN FULL — no part of the cancelled statement survives. That makes a single
|
|
149
|
+
# statement (outside a caller-managed transaction) provably safe to re-issue,
|
|
150
|
+
# writes included, and re-issuing it is what every serious ORM does.
|
|
151
|
+
#
|
|
152
|
+
# The victim is very often innocent: a multi-table READ holding AccessShareLocks
|
|
153
|
+
# is killed because a concurrent DDL session wants AccessExclusiveLock on one of
|
|
154
|
+
# the same tables, which is an everyday event here (migrations apply against live
|
|
155
|
+
# traffic). On 2026-09-12 that reached a person as the banner
|
|
156
|
+
# "listConversations: deadlock detected" on /chat, and ops.app_log shows the same
|
|
157
|
+
# class crashing POST /coding-sessions/bridge with a 500. Bounded and LOUD: real
|
|
158
|
+
# contention still surfaces, it just costs two extra attempts first.
|
|
159
|
+
CONTENTION_RETRIES = 2 # extra attempts for a cancelled statement; total = 1 + this
|
|
160
|
+
CONTENTION_BACKOFF = 0.06 # seconds before the first re-issue; doubled each time
|
|
161
|
+
|
|
126
162
|
# ── idle-in-transaction ceiling (the platform-wide DDL blocker) ───────────────
|
|
127
163
|
# A session that BEGINs and then goes quiet is the single most expensive thing a
|
|
128
164
|
# client can do to a shared Postgres: it holds every lock it took (so DDL —
|
|
@@ -1208,6 +1244,21 @@ class AsyncDatabaseManager:
|
|
|
1208
1244
|
try:
|
|
1209
1245
|
results = await tx_conn.fetch(query, *args, timeout=statement_timeout)
|
|
1210
1246
|
return [dict(r) for r in results]
|
|
1247
|
+
except _CONTENTION_EXC as e:
|
|
1248
|
+
if not _is_confidently_aborted_lock_contention(e):
|
|
1249
|
+
raise
|
|
1250
|
+
# NEVER re-run inside a caller-managed transaction. The whole
|
|
1251
|
+
# atomic block is dead once Postgres cancels one of its
|
|
1252
|
+
# statements, and the work already done in it is the caller's to
|
|
1253
|
+
# decide about — ``retry_on_transient`` wraps the TRANSACTION.
|
|
1254
|
+
raise LockContentionError(
|
|
1255
|
+
original_error=e,
|
|
1256
|
+
query=query,
|
|
1257
|
+
args=args,
|
|
1258
|
+
config_name=config_name,
|
|
1259
|
+
attempts=1,
|
|
1260
|
+
in_transaction=True,
|
|
1261
|
+
) from None
|
|
1211
1262
|
except asyncpg.exceptions.PostgresSyntaxError as e:
|
|
1212
1263
|
raise QueryError(
|
|
1213
1264
|
model=None,
|
|
@@ -1287,7 +1338,13 @@ class AsyncDatabaseManager:
|
|
|
1287
1338
|
# A timed-out READ retries ONCE on a fresh connection (self-heal for
|
|
1288
1339
|
# a starvation-induced command_timeout). Each iteration re-acquires,
|
|
1289
1340
|
# so a poisoned connection is never reused. Writes never loop here.
|
|
1290
|
-
|
|
1341
|
+
# Two independent budgets, each re-acquiring a FRESH connection: a
|
|
1342
|
+
# timed-out read (below) and a statement Postgres cancelled to break
|
|
1343
|
+
# a lock collision (which applies to writes too — the victim is
|
|
1344
|
+
# rolled back in full).
|
|
1345
|
+
read_attempt = 0
|
|
1346
|
+
contention_attempt = 0
|
|
1347
|
+
while True:
|
|
1291
1348
|
async with cls.get_connection(config_name, timeout) as conn:
|
|
1292
1349
|
try:
|
|
1293
1350
|
results = await conn.fetch(query, *args, timeout=statement_timeout)
|
|
@@ -1298,6 +1355,14 @@ class AsyncDatabaseManager:
|
|
|
1298
1355
|
read_attempt + 1,
|
|
1299
1356
|
query[:120],
|
|
1300
1357
|
)
|
|
1358
|
+
if contention_attempt > 0:
|
|
1359
|
+
logger.warning(
|
|
1360
|
+
"[lock-retry] HEALED on attempt %d after Postgres "
|
|
1361
|
+
"cancelled the statement to break a lock collision "
|
|
1362
|
+
"(rolled back, safe to re-run): %s",
|
|
1363
|
+
contention_attempt + 1,
|
|
1364
|
+
query[:120],
|
|
1365
|
+
)
|
|
1301
1366
|
if (
|
|
1302
1367
|
not results
|
|
1303
1368
|
and verify_empty
|
|
@@ -1319,6 +1384,36 @@ class AsyncDatabaseManager:
|
|
|
1319
1384
|
if true_rows is not None:
|
|
1320
1385
|
return true_rows
|
|
1321
1386
|
return [_normalize_record(r) for r in results]
|
|
1387
|
+
except _CONTENTION_EXC as e:
|
|
1388
|
+
if not _is_confidently_aborted_lock_contention(e):
|
|
1389
|
+
raise
|
|
1390
|
+
# Rolled back in full → the SAME statement is re-issued
|
|
1391
|
+
# on a fresh connection, writes included. Jittered so N
|
|
1392
|
+
# tasks cancelled by ONE collision do not collide again
|
|
1393
|
+
# in lockstep. Announced every time: a masked contention
|
|
1394
|
+
# problem is the thing this must never become.
|
|
1395
|
+
if contention_attempt < CONTENTION_RETRIES:
|
|
1396
|
+
delay = CONTENTION_BACKOFF * (2**contention_attempt)
|
|
1397
|
+
delay += random.random() * delay * 0.5
|
|
1398
|
+
logger.warning(
|
|
1399
|
+
"[lock-retry] attempt %d/%d cancelled by a lock "
|
|
1400
|
+
"collision (%s) — re-running in %.3fs: %s",
|
|
1401
|
+
contention_attempt + 1,
|
|
1402
|
+
1 + CONTENTION_RETRIES,
|
|
1403
|
+
getattr(e, "sqlstate", None) or e.__class__.__name__,
|
|
1404
|
+
delay,
|
|
1405
|
+
query[:120],
|
|
1406
|
+
)
|
|
1407
|
+
await asyncio.sleep(delay)
|
|
1408
|
+
contention_attempt += 1
|
|
1409
|
+
continue
|
|
1410
|
+
raise LockContentionError(
|
|
1411
|
+
original_error=e,
|
|
1412
|
+
query=query,
|
|
1413
|
+
args=args,
|
|
1414
|
+
config_name=config_name,
|
|
1415
|
+
attempts=1 + contention_attempt,
|
|
1416
|
+
) from None
|
|
1322
1417
|
except asyncpg.exceptions.PostgresSyntaxError as e:
|
|
1323
1418
|
raise QueryError(
|
|
1324
1419
|
model=None,
|
|
@@ -1367,6 +1462,7 @@ class AsyncDatabaseManager:
|
|
|
1367
1462
|
query[:120],
|
|
1368
1463
|
)
|
|
1369
1464
|
await asyncio.sleep(READ_TIMEOUT_RETRY_BACKOFF)
|
|
1465
|
+
read_attempt += 1
|
|
1370
1466
|
continue
|
|
1371
1467
|
raise ConnectionError(
|
|
1372
1468
|
model=None,
|
|
@@ -1403,6 +1499,7 @@ class AsyncDatabaseManager:
|
|
|
1403
1499
|
query[:120],
|
|
1404
1500
|
)
|
|
1405
1501
|
await asyncio.sleep(READ_TIMEOUT_RETRY_BACKOFF)
|
|
1502
|
+
read_attempt += 1
|
|
1406
1503
|
continue
|
|
1407
1504
|
if connection_closed:
|
|
1408
1505
|
raise ConnectionError(
|
|
@@ -1441,6 +1538,7 @@ class AsyncDatabaseManager:
|
|
|
1441
1538
|
query[:120],
|
|
1442
1539
|
)
|
|
1443
1540
|
await asyncio.sleep(READ_TIMEOUT_RETRY_BACKOFF)
|
|
1541
|
+
read_attempt += 1
|
|
1444
1542
|
continue
|
|
1445
1543
|
raise QueryTimeoutError(
|
|
1446
1544
|
operation="execute_query",
|
|
@@ -1507,6 +1605,21 @@ class AsyncDatabaseManager:
|
|
|
1507
1605
|
except ImportError:
|
|
1508
1606
|
pass
|
|
1509
1607
|
|
|
1608
|
+
# A declared host session context (notably actor provenance) is made of
|
|
1609
|
+
# transaction-local GUCs. A plain standalone write used to skip BEGIN,
|
|
1610
|
+
# so its trigger saw the database default even though the caller had
|
|
1611
|
+
# explicitly declared an actor. Keep the declaration in the caller's
|
|
1612
|
+
# task (the write-queue drain has a different ContextVar context) and
|
|
1613
|
+
# use the canonical transaction path for this one write.
|
|
1614
|
+
from matrx_orm.core.session_context import session_context_gucs
|
|
1615
|
+
|
|
1616
|
+
if session_context_gucs():
|
|
1617
|
+
from matrx_orm.core.transaction import transaction
|
|
1618
|
+
|
|
1619
|
+
config_name = resolve_database_name(config_name)
|
|
1620
|
+
async with transaction(config_name):
|
|
1621
|
+
return await cls.execute_query(config_name, query, *args, timeout=timeout)
|
|
1622
|
+
|
|
1510
1623
|
from matrx_orm.core.write_queue import get_write_queue_registry
|
|
1511
1624
|
|
|
1512
1625
|
config_name = resolve_database_name(config_name)
|
|
@@ -1183,6 +1183,81 @@ class PoolAcquireTimeoutError(DatabaseError):
|
|
|
1183
1183
|
return f"{_RED}{body}{_RESET}"
|
|
1184
1184
|
|
|
1185
1185
|
|
|
1186
|
+
class LockContentionError(DatabaseError):
|
|
1187
|
+
"""Raised when Postgres cancelled a statement to break a lock collision.
|
|
1188
|
+
|
|
1189
|
+
SQLSTATE 40P01 (deadlock_detected), 40001 (serialization_failure) and 55P03
|
|
1190
|
+
(lock_not_available). The victim is rolled back IN FULL — no part of the
|
|
1191
|
+
cancelled statement survives — so a single statement outside a
|
|
1192
|
+
caller-managed transaction is provably safe to re-issue, and
|
|
1193
|
+
``AsyncDatabaseManager.execute_query`` re-issues it a bounded number of
|
|
1194
|
+
times with jittered backoff, announcing every heal. This exception means
|
|
1195
|
+
either that budget was exhausted, or that the statement ran INSIDE an
|
|
1196
|
+
explicit ``transaction()`` where the partial work is the caller's to decide
|
|
1197
|
+
about (wrap the whole transaction in ``retry_on_transient`` if re-running it
|
|
1198
|
+
is safe).
|
|
1199
|
+
|
|
1200
|
+
The usual cause is not the caller: a multi-table statement becomes a
|
|
1201
|
+
deadlock victim whenever a concurrent DDL session wants AccessExclusiveLock
|
|
1202
|
+
on a table the statement already holds a lock on. Migrations applied against
|
|
1203
|
+
live traffic produce exactly this (2026-09-12: a frontend conversation-list
|
|
1204
|
+
READ, which writes nothing, surfaced "deadlock detected" to a person).
|
|
1205
|
+
"""
|
|
1206
|
+
|
|
1207
|
+
def __init__(
|
|
1208
|
+
self,
|
|
1209
|
+
original_error=None,
|
|
1210
|
+
query: str | None = None,
|
|
1211
|
+
args=None,
|
|
1212
|
+
config_name: str | None = None,
|
|
1213
|
+
attempts: int = 1,
|
|
1214
|
+
in_transaction: bool = False,
|
|
1215
|
+
):
|
|
1216
|
+
sqlstate = getattr(original_error, "sqlstate", None)
|
|
1217
|
+
details = {
|
|
1218
|
+
"query": query,
|
|
1219
|
+
"args": args,
|
|
1220
|
+
"config_name": config_name,
|
|
1221
|
+
"sqlstate": sqlstate,
|
|
1222
|
+
"attempts": attempts,
|
|
1223
|
+
"in_transaction": in_transaction,
|
|
1224
|
+
}
|
|
1225
|
+
where = (
|
|
1226
|
+
"inside a caller-managed transaction, so nothing was re-run"
|
|
1227
|
+
if in_transaction
|
|
1228
|
+
else f"after {attempts} attempt(s)"
|
|
1229
|
+
)
|
|
1230
|
+
super().__init__(
|
|
1231
|
+
message=(
|
|
1232
|
+
f"Postgres cancelled this statement to break a lock collision "
|
|
1233
|
+
f"({sqlstate or 'lock contention'}) {where}: {original_error}"
|
|
1234
|
+
),
|
|
1235
|
+
model=None,
|
|
1236
|
+
details=details,
|
|
1237
|
+
)
|
|
1238
|
+
|
|
1239
|
+
def format_message(self):
|
|
1240
|
+
details = self.details or {}
|
|
1241
|
+
lines = ["\n" + "-" * 80]
|
|
1242
|
+
lines.append("Matrx ORM | LockContentionError")
|
|
1243
|
+
lines.append("")
|
|
1244
|
+
lines.append(self.message)
|
|
1245
|
+
lines.append("")
|
|
1246
|
+
lines.append("Hint:")
|
|
1247
|
+
lines.append(" - NOTHING of the cancelled statement committed; re-running is safe.")
|
|
1248
|
+
if details.get("in_transaction"):
|
|
1249
|
+
lines.append(" - It ran inside an explicit transaction(), so the ORM did NOT")
|
|
1250
|
+
lines.append(" re-run it: the rest of the transaction is yours. Wrap the whole")
|
|
1251
|
+
lines.append(" transaction in `retry_on_transient` when re-running it is safe.")
|
|
1252
|
+
else:
|
|
1253
|
+
lines.append(f" - The ORM already re-ran it {details.get('attempts', '?')} time(s).")
|
|
1254
|
+
lines.append(" Repeated failures mean REAL contention on these tables — look at")
|
|
1255
|
+
lines.append(" what else held a lock (DDL applied against live traffic is the")
|
|
1256
|
+
lines.append(" usual partner), not at this caller.")
|
|
1257
|
+
lines.append("-" * 80 + "\n")
|
|
1258
|
+
return f"{_RED}" + "\n".join(lines) + f"{_RESET}"
|
|
1259
|
+
|
|
1260
|
+
|
|
1186
1261
|
class IntegrityError(DatabaseError):
|
|
1187
1262
|
"""Raised for database integrity violations."""
|
|
1188
1263
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Standalone organization-assignment debt inventory and provenance pins."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
from functools import lru_cache
|
|
8
|
+
from importlib.resources import files
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
_RESOURCE_PACKAGE = "matrx_orm.resources"
|
|
12
|
+
_ORIGINAL_RESOURCE = "org_assignment_trigger_baseline.json"
|
|
13
|
+
_DISCOVERY_RESOURCE = "additional-assigners-2026-09-12.json"
|
|
14
|
+
|
|
15
|
+
ORIGINAL_GENESIS_SHA256 = "859df77f01d30ef745fd6724d7152a349ccb900b61c33772fe89d678714895ae"
|
|
16
|
+
DISCOVERY_GENESIS_SHA256 = "1f66a51b072918d998e25ad46a0e659229c19f1eb2069e499aa2450eb3f8b0c4"
|
|
17
|
+
DISCOVERY_PROJECT_ID = "brsgrqvjdzwihsvnfqkf"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def resource_text(name: str) -> str:
|
|
21
|
+
"""Read a packaged inventory without relying on a sibling checkout."""
|
|
22
|
+
return files(_RESOURCE_PACKAGE).joinpath(name).read_text(encoding="utf-8")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def original_baseline_payload() -> dict[str, Any]:
|
|
26
|
+
"""Return the canonical mutable-retirement ledger from package data."""
|
|
27
|
+
payload = json.loads(resource_text(_ORIGINAL_RESOURCE))
|
|
28
|
+
if not isinstance(payload, dict):
|
|
29
|
+
raise ValueError("organization assignment baseline must be an object")
|
|
30
|
+
genesis = {
|
|
31
|
+
key: payload.get(key)
|
|
32
|
+
for key in (
|
|
33
|
+
"historical_four_family_triggers",
|
|
34
|
+
"historical_specialized_triggers",
|
|
35
|
+
"historical_organization_defaults",
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
digest = hashlib.sha256(
|
|
39
|
+
json.dumps(genesis, sort_keys=True, separators=(",", ":")).encode()
|
|
40
|
+
).hexdigest()
|
|
41
|
+
if payload.get("genesis_sha256") != ORIGINAL_GENESIS_SHA256 or digest != ORIGINAL_GENESIS_SHA256:
|
|
42
|
+
raise ValueError("organization assignment baseline digest mismatch")
|
|
43
|
+
return payload
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def discovery_genesis_payload() -> dict[str, Any]:
|
|
47
|
+
"""Return the separately captured additional-debt census from package data."""
|
|
48
|
+
payload = json.loads(resource_text(_DISCOVERY_RESOURCE))
|
|
49
|
+
if not isinstance(payload, dict):
|
|
50
|
+
raise ValueError("organization assignment discovery must be an object")
|
|
51
|
+
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
|
|
52
|
+
if hashlib.sha256(canonical).hexdigest() != DISCOVERY_GENESIS_SHA256:
|
|
53
|
+
raise ValueError("organization assignment discovery digest mismatch")
|
|
54
|
+
return payload
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@lru_cache(maxsize=1)
|
|
58
|
+
def organization_assignment_function_identities() -> tuple[tuple[str, str], ...]:
|
|
59
|
+
"""Return every exact function root covered by the packaged gate."""
|
|
60
|
+
original = original_baseline_payload().get("function_identities")
|
|
61
|
+
discovery = discovery_genesis_payload().get("items")
|
|
62
|
+
if not isinstance(original, list) or not isinstance(discovery, list):
|
|
63
|
+
raise ValueError("organization assignment function inventory is incomplete")
|
|
64
|
+
identities: list[tuple[str, str]] = []
|
|
65
|
+
for identity in original:
|
|
66
|
+
if not isinstance(identity, str) or identity.count(".") != 1:
|
|
67
|
+
raise ValueError("organization assignment function identity is invalid")
|
|
68
|
+
identities.append(tuple(identity.split(".", 1)))
|
|
69
|
+
for item in discovery:
|
|
70
|
+
if not isinstance(item, dict):
|
|
71
|
+
raise ValueError("organization assignment discovery item is invalid")
|
|
72
|
+
schema = item.get("schema_name")
|
|
73
|
+
name = item.get("function_name")
|
|
74
|
+
if not isinstance(schema, str) or not isinstance(name, str):
|
|
75
|
+
raise ValueError("organization assignment discovery root is invalid")
|
|
76
|
+
identities.append((schema, name))
|
|
77
|
+
if len(identities) != 16 or len(set(identities)) != 16:
|
|
78
|
+
raise ValueError("organization assignment root count is invalid")
|
|
79
|
+
return tuple(identities)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Immutable machine-readable inventories shipped with matrx-orm."""
|