matrx-orm 3.1.25__tar.gz → 3.1.26__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.25 → matrx_orm-3.1.26}/PKG-INFO +1 -1
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/async_db_manager.py +34 -0
- matrx_orm-3.1.26/matrx_orm/secrets_battery/FEATURE.md +112 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/secrets_battery/__init__.py +33 -1
- matrx_orm-3.1.26/matrx_orm/secrets_battery/model.py +93 -0
- matrx_orm-3.1.26/matrx_orm/secrets_battery/org_service.py +588 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/secrets_battery/service.py +110 -3
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/pyproject.toml +1 -1
- matrx_orm-3.1.25/matrx_orm/secrets_battery/FEATURE.md +0 -50
- matrx_orm-3.1.25/matrx_orm/secrets_battery/model.py +0 -48
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/.gitignore +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/AGENTS.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/CLAUDE.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/MODEL_API.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/docs/migrations.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/scripts/release.sh +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/conftest.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_execute_admin_sql.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_filter_raw.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.25 → matrx_orm-3.1.26}/tests/test_sync_twins_guard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.26
|
|
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
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
from dataclasses import dataclass
|
|
4
5
|
import json
|
|
5
6
|
import logging
|
|
6
7
|
import os
|
|
@@ -285,6 +286,15 @@ _init_connection = _init_connection_default
|
|
|
285
286
|
_init_vector_codec = _init_connection_default
|
|
286
287
|
|
|
287
288
|
|
|
289
|
+
@dataclass(frozen=True, slots=True)
|
|
290
|
+
class ConnectionIdentity:
|
|
291
|
+
"""The role/database a pool is actually connected as."""
|
|
292
|
+
|
|
293
|
+
current_user: str
|
|
294
|
+
session_user: str
|
|
295
|
+
database: str
|
|
296
|
+
|
|
297
|
+
|
|
288
298
|
class AsyncDatabaseManager:
|
|
289
299
|
_instance = None
|
|
290
300
|
_pools = {}
|
|
@@ -496,6 +506,30 @@ class AsyncDatabaseManager:
|
|
|
496
506
|
) from e
|
|
497
507
|
return cls._pools[config_name]
|
|
498
508
|
|
|
509
|
+
@classmethod
|
|
510
|
+
async def connection_identity(cls, config_name: str) -> ConnectionIdentity:
|
|
511
|
+
"""Who is this pool actually connected AS.
|
|
512
|
+
|
|
513
|
+
Exists so a service can PROVE it is inside its granted database
|
|
514
|
+
boundary (`current_user` = its scoped role) without hand-writing SQL —
|
|
515
|
+
the question "which role am I?" is database introspection, which the
|
|
516
|
+
ORM owns. Postgres exposes `current_user` / `session_user` /
|
|
517
|
+
`current_database` as reserved keywords rather than callable
|
|
518
|
+
functions, so `call_function` cannot reach them; this is the sanctioned
|
|
519
|
+
accessor.
|
|
520
|
+
"""
|
|
521
|
+
pool = await cls.get_pool(config_name)
|
|
522
|
+
async with pool.acquire() as conn:
|
|
523
|
+
row = await conn.fetchrow(
|
|
524
|
+
"SELECT current_user AS current_user, session_user AS session_user, "
|
|
525
|
+
"current_database() AS database"
|
|
526
|
+
)
|
|
527
|
+
return ConnectionIdentity(
|
|
528
|
+
current_user=row["current_user"],
|
|
529
|
+
session_user=row["session_user"],
|
|
530
|
+
database=row["database"],
|
|
531
|
+
)
|
|
532
|
+
|
|
499
533
|
@classmethod
|
|
500
534
|
def _start_keepalive(cls, config_name: str, pool_min: int) -> None:
|
|
501
535
|
"""Start (or restart) the per-config pool keepalive task.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# matrx-orm secrets battery — the ONE credential vault
|
|
2
|
+
|
|
3
|
+
**One table, one key, everywhere.** Every platform credential — personal AND
|
|
4
|
+
organizational — lives in `users.user_secrets` (Fernet-encrypted). Every package
|
|
5
|
+
and deployment that needs a credential holds the same `CREDENTIALS_ENCRYPTION_KEY`
|
|
6
|
+
and reads the vault directly through this module. **No package calls another
|
|
7
|
+
package or a service to resolve a credential** — there is no privileged
|
|
8
|
+
decryptor (decided 2026-07-21; doctrine: `docs/packages/PACKAGE_DOCTRINE.md` §5).
|
|
9
|
+
|
|
10
|
+
There is no second vault. The `private_vault.organization_secrets` system
|
|
11
|
+
(Supabase Vault, decryption inside Postgres) was **annihilated 2026-07-21** —
|
|
12
|
+
schema, tables, SECURITY DEFINER functions, and the duplicated `vault.secrets`
|
|
13
|
+
material all dropped. A new `Fernet(...)` or a second secrets table anywhere is
|
|
14
|
+
a defect.
|
|
15
|
+
|
|
16
|
+
## Consumer contract
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from matrx_orm.secrets_battery import require_secret
|
|
20
|
+
api_key = await require_secret(user_id, organization_id, "DATAFORSEO_API_KEY")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**`require_secret` is the one you want.** It implements the hierarchy:
|
|
24
|
+
**personal → organization → raise**, naming both scopes it searched. Most people
|
|
25
|
+
never hold their own API keys — their organization does.
|
|
26
|
+
|
|
27
|
+
`require_user_secret(user_id, key)` is the personal-only variant. Both raise
|
|
28
|
+
`SecretNotFoundError` / `SecretDecryptError` and never return None;
|
|
29
|
+
`get_user_secret` / `get_org_secret` are the degradable twins.
|
|
30
|
+
|
|
31
|
+
## Scope — one table, two shapes
|
|
32
|
+
|
|
33
|
+
A row is PERSONAL (`user_id` set, `organization_id` NULL) or ORG-SCOPED
|
|
34
|
+
(`organization_id` set, `user_id` NULL). A DB CHECK enforces exactly one, and
|
|
35
|
+
partial unique indexes make `(scope, key)` unique among live rows.
|
|
36
|
+
|
|
37
|
+
| Surface | Personal | Org |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| read one | `get_user_secret` | `get_org_secret` |
|
|
40
|
+
| read many | — | `resolve_org_secrets` |
|
|
41
|
+
| hierarchy (one key) | `require_secret` | ← same call |
|
|
42
|
+
| hierarchy (many keys) | `resolve_effective_secrets` | ← same call |
|
|
43
|
+
| CRUD | `create/update/delete_user_secret` | `create/update/delete_org_secret` |
|
|
44
|
+
| listing | `list_user_secrets` | `list_org_secrets` |
|
|
45
|
+
| grants | — | `set_org_secret_grants` |
|
|
46
|
+
|
|
47
|
+
**Precedence is the same in both directions:** a PERSONAL value wins over an org
|
|
48
|
+
value on key collision. `require_secret` checks personal first;
|
|
49
|
+
`resolve_effective_secrets` loads org values then overlays personal on top. They
|
|
50
|
+
are two expressions of one rule — keep them that way.
|
|
51
|
+
|
|
52
|
+
## Grants and access modes
|
|
53
|
+
|
|
54
|
+
An org secret is `access_mode='all_members'` (default) or `'restricted'`.
|
|
55
|
+
A restricted secret is readable only by a user holding a `can_use` row in
|
|
56
|
+
`users.user_secret_grants` — **or by an org admin**, via the `is_org_admin`
|
|
57
|
+
flag the host computes and passes down.
|
|
58
|
+
|
|
59
|
+
## The authorization boundary — read this before adding a check here
|
|
60
|
+
|
|
61
|
+
**matrx-orm has no tenancy model and must never grow one.** This module does NOT
|
|
62
|
+
decide who is a member or an admin of an organization. The HOST asserts that and
|
|
63
|
+
passes the outcome in as `is_org_admin`. What the battery DOES own is the
|
|
64
|
+
per-secret grant check, because `user_secret_grants` is its own table.
|
|
65
|
+
|
|
66
|
+
aidream's authorization layer is
|
|
67
|
+
[`aidream/services/user_secrets/organizations.py`](../../../../aidream/services/user_secrets/organizations.py):
|
|
68
|
+
membership → `iam.has_org_access_for`, adminhood → `public.is_org_admin_for`,
|
|
69
|
+
asserted before the battery is touched.
|
|
70
|
+
|
|
71
|
+
## Audit
|
|
72
|
+
|
|
73
|
+
`users.user_secret_audit` records **actions and metadata, NEVER values**
|
|
74
|
+
(`record_secret_audit`). Audit is a trail, not a transaction: a failed audit
|
|
75
|
+
write is logged loudly but never fails the operation the user asked for —
|
|
76
|
+
losing the trail must not also lose the work.
|
|
77
|
+
|
|
78
|
+
## Wiring
|
|
79
|
+
|
|
80
|
+
- **Hosted:** `configure_secrets(db_config_name="<registered config>")` at
|
|
81
|
+
startup (aidream: `package_integration.py`) — aliases `matrx_secrets` onto the
|
|
82
|
+
host pool. One physical pool.
|
|
83
|
+
- **Standalone package/service:** register your DB with matrx-orm, call the same
|
|
84
|
+
`configure_secrets`. Key comes from `CREDENTIALS_ENCRYPTION_KEY` env, or pass
|
|
85
|
+
`encryption_key=` (host injection).
|
|
86
|
+
- Key resolution (byte-identical to the historical aidream implementation — all
|
|
87
|
+
existing ciphertexts keep decrypting): explicit key → `CREDENTIALS_ENCRYPTION_KEY`
|
|
88
|
+
(44-char urlsafe-base64 used directly, else SHA-256-derived) → `SUPABASE_SECRET_KEY`
|
|
89
|
+
derivation with a loud warning → loud RuntimeError.
|
|
90
|
+
|
|
91
|
+
## Invariants
|
|
92
|
+
|
|
93
|
+
- **This is the only Fernet instance in the universe.** The dict-payload helpers
|
|
94
|
+
(`encrypt_payload`/`decrypt_payload`) serve `tool.mcp_user_conn` blobs — same
|
|
95
|
+
key, same instance.
|
|
96
|
+
- Every read is scoped by a **required** `user_id` or `organization_id`. No None
|
|
97
|
+
= "show everything".
|
|
98
|
+
- Soft delete by default (`deleted_at`); the partial unique indexes back the
|
|
99
|
+
upserts.
|
|
100
|
+
- `value_hint` is the only value-derived field that may reach a listing/UI.
|
|
101
|
+
Listing and management surfaces are value-free by construction.
|
|
102
|
+
- `value_version` is bumped by the `users.user_secrets_value_version` DB trigger
|
|
103
|
+
when `value_encrypted` changes — never by hand.
|
|
104
|
+
- Rotating an org secret's value CLEARS its personal-secret lineage
|
|
105
|
+
(`source_user_secret_id`) — the org value is no longer what the contributor holds.
|
|
106
|
+
- One unreadable row (key drift) is skipped with a loud log during bulk
|
|
107
|
+
resolution — a broken row must not deny every other key.
|
|
108
|
+
|
|
109
|
+
Drift guard: `scripts/validate_secrets_decrypt.py` (loud, non-blocking, in
|
|
110
|
+
`release.sh`) asserts every active row still decrypts with the configured key.
|
|
111
|
+
|
|
112
|
+
Verified against live code + the live `users.user_secrets` schema 2026-07-21.
|
|
@@ -34,7 +34,21 @@ from .crypto import (
|
|
|
34
34
|
mask_value,
|
|
35
35
|
reset_encryption_for_tests,
|
|
36
36
|
)
|
|
37
|
-
from .model import PACKAGE_DB_NAME, UserSecret
|
|
37
|
+
from .model import PACKAGE_DB_NAME, UserSecret, UserSecretAudit, UserSecretGrant
|
|
38
|
+
from .org_service import (
|
|
39
|
+
ACCESS_MODES,
|
|
40
|
+
OrgSecretRow,
|
|
41
|
+
create_org_secret,
|
|
42
|
+
delete_org_secret,
|
|
43
|
+
get_org_secret_row,
|
|
44
|
+
list_org_secrets,
|
|
45
|
+
record_secret_audit,
|
|
46
|
+
resolve_effective_secrets,
|
|
47
|
+
resolve_org_secrets,
|
|
48
|
+
set_org_secret_grants,
|
|
49
|
+
sync_org_secret_from_user,
|
|
50
|
+
update_org_secret,
|
|
51
|
+
)
|
|
38
52
|
from .service import (
|
|
39
53
|
KNOWN_CATEGORIES,
|
|
40
54
|
VALID_KEY_RE,
|
|
@@ -47,6 +61,8 @@ from .service import (
|
|
|
47
61
|
get_user_secret,
|
|
48
62
|
list_user_secrets,
|
|
49
63
|
parse_env_text,
|
|
64
|
+
get_org_secret,
|
|
65
|
+
require_secret,
|
|
50
66
|
require_user_secret,
|
|
51
67
|
update_user_secret,
|
|
52
68
|
)
|
|
@@ -87,7 +103,21 @@ __all__ = [
|
|
|
87
103
|
"decrypt_payload",
|
|
88
104
|
"mask_value",
|
|
89
105
|
"UserSecret",
|
|
106
|
+
"UserSecretGrant",
|
|
107
|
+
"UserSecretAudit",
|
|
90
108
|
"PACKAGE_DB_NAME",
|
|
109
|
+
"ACCESS_MODES",
|
|
110
|
+
"OrgSecretRow",
|
|
111
|
+
"create_org_secret",
|
|
112
|
+
"delete_org_secret",
|
|
113
|
+
"get_org_secret_row",
|
|
114
|
+
"list_org_secrets",
|
|
115
|
+
"record_secret_audit",
|
|
116
|
+
"resolve_effective_secrets",
|
|
117
|
+
"resolve_org_secrets",
|
|
118
|
+
"set_org_secret_grants",
|
|
119
|
+
"sync_org_secret_from_user",
|
|
120
|
+
"update_org_secret",
|
|
91
121
|
"SecretRow",
|
|
92
122
|
"SecretNotFoundError",
|
|
93
123
|
"SecretDecryptError",
|
|
@@ -95,6 +125,8 @@ __all__ = [
|
|
|
95
125
|
"VALID_KEY_RE",
|
|
96
126
|
"list_user_secrets",
|
|
97
127
|
"get_user_secret",
|
|
128
|
+
"require_secret",
|
|
129
|
+
"get_org_secret",
|
|
98
130
|
"require_user_secret",
|
|
99
131
|
"create_user_secret",
|
|
100
132
|
"update_user_secret",
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Package-owned model for the canonical vault table ``users.user_secrets``.
|
|
2
|
+
|
|
3
|
+
Bound to the ``matrx_secrets`` config name (an alias): hosts point it at their
|
|
4
|
+
already-registered pool via ``configure_secrets(db_config_name=...)`` — one
|
|
5
|
+
physical pool, no second connection. ``user_id`` is a plain UUID column here
|
|
6
|
+
(the DB enforces the FK to ``auth.users``) so the battery needs no host models.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from matrx_orm import (
|
|
12
|
+
BinaryField,
|
|
13
|
+
BooleanField,
|
|
14
|
+
DateTimeField,
|
|
15
|
+
IntegerField,
|
|
16
|
+
JSONBField,
|
|
17
|
+
Model,
|
|
18
|
+
TextField,
|
|
19
|
+
UUIDField,
|
|
20
|
+
model_registry,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
PACKAGE_DB_NAME = "matrx_secrets"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class UserSecret(Model):
|
|
27
|
+
"""One vault row. PERSONAL (user_id set, organization_id NULL) or
|
|
28
|
+
ORG-SCOPED (organization_id set, user_id NULL) — never both."""
|
|
29
|
+
|
|
30
|
+
id = UUIDField(primary_key=True, null=False)
|
|
31
|
+
user_id = UUIDField()
|
|
32
|
+
organization_id = UUIDField()
|
|
33
|
+
created_by = UUIDField()
|
|
34
|
+
updated_by = UUIDField()
|
|
35
|
+
access_mode = TextField(null=False, default="all_members")
|
|
36
|
+
source_user_secret_id = UUIDField()
|
|
37
|
+
source_user_secret_version = IntegerField()
|
|
38
|
+
key = TextField(null=False)
|
|
39
|
+
value_encrypted = BinaryField(null=False)
|
|
40
|
+
value_hint = TextField()
|
|
41
|
+
description = TextField()
|
|
42
|
+
category = TextField()
|
|
43
|
+
is_active = BooleanField(null=False, default=True)
|
|
44
|
+
inject_into_sandbox = BooleanField(null=False, default=True)
|
|
45
|
+
last_used_at = DateTimeField()
|
|
46
|
+
created_at = DateTimeField(null=False)
|
|
47
|
+
updated_at = DateTimeField(null=False)
|
|
48
|
+
deleted_at = DateTimeField()
|
|
49
|
+
value_version = IntegerField(null=False, default=1)
|
|
50
|
+
|
|
51
|
+
_table_name = "user_secrets"
|
|
52
|
+
_db_schema = "users"
|
|
53
|
+
_database = PACKAGE_DB_NAME
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class UserSecretGrant(Model):
|
|
57
|
+
"""Per-user grant for an ``access_mode='restricted'`` org secret."""
|
|
58
|
+
|
|
59
|
+
id = UUIDField(primary_key=True, null=False)
|
|
60
|
+
user_secret_id = UUIDField(null=False)
|
|
61
|
+
user_id = UUIDField(null=False)
|
|
62
|
+
can_use = BooleanField(null=False, default=True)
|
|
63
|
+
can_manage = BooleanField(null=False, default=False)
|
|
64
|
+
granted_by = UUIDField()
|
|
65
|
+
created_at = DateTimeField(null=False)
|
|
66
|
+
updated_at = DateTimeField(null=False)
|
|
67
|
+
|
|
68
|
+
_table_name = "user_secret_grants"
|
|
69
|
+
_db_schema = "users"
|
|
70
|
+
_database = PACKAGE_DB_NAME
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class UserSecretAudit(Model):
|
|
74
|
+
"""Access/management trail. Records actions and metadata, NEVER values.
|
|
75
|
+
HIPAA §164.312(b) audit controls are required, not addressable."""
|
|
76
|
+
|
|
77
|
+
id = IntegerField(primary_key=True, null=False)
|
|
78
|
+
user_secret_id = UUIDField()
|
|
79
|
+
organization_id = UUIDField()
|
|
80
|
+
user_id = UUIDField()
|
|
81
|
+
actor_id = UUIDField()
|
|
82
|
+
action = TextField(null=False)
|
|
83
|
+
metadata = JSONBField(null=False, default={})
|
|
84
|
+
created_at = DateTimeField(null=False)
|
|
85
|
+
|
|
86
|
+
_table_name = "user_secret_audit"
|
|
87
|
+
_db_schema = "users"
|
|
88
|
+
_database = PACKAGE_DB_NAME
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
model_registry.register_all([UserSecret, UserSecretGrant, UserSecretAudit], skip_existing=True)
|
|
92
|
+
|
|
93
|
+
__all__ = ["UserSecret", "UserSecretGrant", "UserSecretAudit", "PACKAGE_DB_NAME"]
|