quadkit 0.0.42__tar.gz → 0.0.44__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.
- quadkit-0.0.44/.gitignore +24 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/PKG-INFO +3 -3
- {quadkit-0.0.42 → quadkit-0.0.44}/README.md +2 -2
- {quadkit-0.0.42 → quadkit-0.0.44}/pyproject.toml +1 -2
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/validation.py +4 -4
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/resolver.py +1 -1
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/ambient.py +20 -3
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/README.md +36 -8
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/configurator.py +12 -8
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/factory.py +56 -21
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/processors.py +52 -3
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/resilience.py +1 -1
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/di/sub_providers/observability.py +1 -1
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/pipeline.py +1 -1
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/hashing/ambient.py +17 -2
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_hashing.py +35 -1
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_identity_generators_and_ambient.py +46 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_bridging.py +74 -2
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_factory.py +60 -32
- quadkit-0.0.42/.gitignore +0 -214
- quadkit-0.0.42/CHANGELOG.md +0 -73
- quadkit-0.0.42/docs/ARCHITECTURE.md +0 -252
- quadkit-0.0.42/docs/CONFIGURATION.md +0 -126
- quadkit-0.0.42/docs/GUIDE.md +0 -451
- quadkit-0.0.42/docs/HOWTOS.md +0 -275
- quadkit-0.0.42/docs/QUICKSTART.md +0 -91
- quadkit-0.0.42/docs/SECURITY.md +0 -165
- quadkit-0.0.42/docs/TROUBLESHOOTING.md +0 -217
- quadkit-0.0.42/docs/gifs/hero/app.py +0 -455
- quadkit-0.0.42/docs/gifs/hero/hero.tape +0 -71
- quadkit-0.0.42/docs/gifs/hero/quadkit-hero.gif +0 -0
- quadkit-0.0.42/docs/plugins.md +0 -54
- quadkit-0.0.42/src/import_error.txt +0 -14
- {quadkit-0.0.42 → quadkit-0.0.44}/LICENSE +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/NOTICE +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/example.yaml +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/asgi_lifespan.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/config/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/config/discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/config/models.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/config_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/events.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/factory.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/health_probes.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/injectable_provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/invoker.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/pipeline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/runner.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/secrets.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/standard.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/app/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/codegen/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/codegen/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/codegen/field_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/bridges/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/bridges/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/bridges/sync_bridge.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/channels/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/channels/channel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/channels/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/di/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/executors/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/executors/dispatcher.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/executors/parallel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/executors/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/executors/task_manager.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/locks/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/locks/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/locks/rwlock.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/concurrency/task_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/merge.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/sources.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/lib/watcher.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/main.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/secrets.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/config/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/_graph.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/builder.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/config/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/config/models.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/container.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/container_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/container_resolution.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/container_runtime.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/registrar.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/resolver.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/container/scope.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/context.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/decorators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/aop_interceptors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/interceptors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/strategies.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/extensions/validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/function_provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/integration/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/integration/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/markers.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/_graph_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/compiler.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/context.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/collect.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/detect_cycles.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/expand.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/order.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/protocol.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/validate.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/compiler/phases/visibility.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/dynamic.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/errors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/graph.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/metadata.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/module/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/events.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/health.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/orchestrator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/orchestrator/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/provider_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/context.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/descriptor.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/diagnostics.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/injector.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/invoker.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/store.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/type_hints.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/resolution/validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/di/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/aggregate.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/coercion.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/entity.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/factory.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/models/value_object.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/domain/unit_of_work.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/hooks/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/hooks/ambient.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/hooks/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/hooks/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/identity/generator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/config/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/config/models.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/config/redaction.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/config/sampling.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/debug.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/redaction.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/logging/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/core/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/core/mapper.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/mapping/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/caching.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/di.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/observability.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/routing.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/builtins/validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/core/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/core/chain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/core/exception_filters.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/core/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/middleware/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/core.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/di/sub_providers/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/engine.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/plugins/state.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/builder.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/clock.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/context.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/context_keys.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/context_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/data.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/lazy.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/registry/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/registry/core.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/registry/introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/trusted_html.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/primitives/typing.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/core.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/operators/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/operators/control.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/operators/time_ops.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/operators/transform.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/retry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/reactive/subjects.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/result/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/result/_pipeline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/result/errors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/result/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/result/utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/saga/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/saga/base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/saga/canonical_json.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/saga/content_addressed.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/decorators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/encryption/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/encryption/service.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/events.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/guards/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/guards/chain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/guards/decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/hashing/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/hashing/digest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/hashing/kdf.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/hooks.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/sanitization/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/sanitization/filename.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/sanitization/html.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/sanitization/sanitizer.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/sanitization/url.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/secrets/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/secrets/rotation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/secrets/store.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/secrets/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/security/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/backends/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/backends/json.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/backends/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/di/provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/di/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/domain/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/domain/domain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/domain/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/registry/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/registry/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/registry/registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/schema/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/schema/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/schema/schema.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/serialization/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/decorators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/engine/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/engine/coercion.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/engine/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/engine/validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/rules/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/rules/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/rules/rules.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/schema/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/schema/fields.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/schema/introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/schema/py.typed +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/validation/types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/_fixtures.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_boot_level.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_cross_method.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_dependency_chain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_exports.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_importers.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_module_health_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_module_lifecycle_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_name_lookup.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/module/test_stub_enforcement_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/di/test_visibility_enforcement_e2e.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/mapping/test_mapping_lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/middleware/test_middleware_lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/test_corrected_patterns_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/test_database_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/test_full_pipeline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/integration/test_monitor_config_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/test.md +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/test_import_diagnostic.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/aop/test_interceptor_timeout.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/clock/test_clock.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/codegen/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/codegen/test_generator_base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/codegen/test_staged_generation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/codegen/test_template_overrides.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_bounded_channel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_channel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_parallel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_provider_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_concurrency_rwlock.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_config_pool.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_dispatcher.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_sync_bridge.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_task_manager.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/concurrency/test_task_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_config_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_config_protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_config_sources.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_env_interpolation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_loader_fail_fast.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_logging_redaction_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_logging_sampling.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_profile_overlay.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_scoping.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_secrets_validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_strict_bool_env.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/config/test_strict_sections.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/test_context_correlation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/test_core_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/test_core_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/test_request_context_di.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/test_typing.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/core/validation/test_protocols.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/integration/test_provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_compiler.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_dynamic.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_errors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_global.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_graph_reflection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_health_graph.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_integration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_module_lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_reexport.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_stub_compiler.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_stub_decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/module/test_visibility.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_advanced_features.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_container_basics.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_container_builder.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_container_freeze.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_container_hardening.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_container_visibility.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_decorators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_descriptor.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_di_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_di_decorators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_di_provider_config_wiring.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_diagnostics.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_extensions_discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_extensions_validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_function_provider_boot.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_graph_validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_interceptor_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_invoker_unit.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_lifecycle_orchestrator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_module_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_module_visibility_boot.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_module_visibility_enforcement.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_named_binding.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_orchestrator_health.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_basics.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_config_injection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_conformance.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_orchestration.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_reset_state.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_provider_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_scope_concurrency.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_scope_manager.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_service_store.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_type_hints.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/di/test_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_aggregates.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain_init.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain_model_strict.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_domain_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_models_factory.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/domain/test_value_object.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/identity/test_identity.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/logging/test_logging_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_auto_map.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_mapping_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_mapping_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_mapping_mapper.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_mapping_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_mapping_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_protocol.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/mapping/test_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_builtins.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_chain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_config_alignment.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_exception_filters.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_chain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_ep_discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_routing.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_middleware_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_p2_retry_traceback.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_registry_defaults.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/middleware/test_registry_with_resilience.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/plugins/test_discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/plugins/test_engine.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/plugins/test_state.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/plugins/test_state_hardening.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/plugins/test_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/primitives/test_primitives_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/primitives/test_registry_advanced.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/primitives/test_registry_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/primitives/test_trusted_html.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_control.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_core.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_facade.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_retry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_subjects.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_time_ops.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/reactive/test_transform.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_guards.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_package_hooks_p2.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_secret_rotation_policy.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_secrets_rotation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_secrets_store.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_security_api.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_security_components_p2.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_security_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_security_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/security/test_security_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_schema.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_di_provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_domain.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_init.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_json.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/serialization/test_serialization_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_boot_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_config_and_misc.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_discovery.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_health_baseline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_health_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_runner_and_lifespan.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_app_validation_and_misc.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_application.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_application_base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_application_lifecycle.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_base_and_misc_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_clock_and_pipeline_primitives.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_codegen.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_compiler_graph_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_component_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_concurrency_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_concurrency_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_hardening.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_quadkit.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_requirements.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_sources.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_config_watcher.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_container_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_container_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_container_override.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_container_resolver_impl.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_container_runtime_mixin.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_context_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_contract_completeness.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_core_builder.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_core_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_core_lazy.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_core_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_core_pipeline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_dependency_injector.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_di_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_di_descriptor.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_di_module_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_domain_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_domain_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_domain_model_base.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_dynamic_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_events_security_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_execution_result.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_hatch_build_targets.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_health_probes.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_hook_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_hook_registry_edge_cases.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_hook_registry_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_hook_registry_scenarios.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_infra_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_input_sanitizers.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_interceptors.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_json_serialization_backend.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_apply_redaction.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_debug.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_di_provider.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_init.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_redaction.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_redaction_compound.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_logging_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_m13_m14_verification.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_mapper.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_mapper_enhanced.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_mapping.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_middleware_enhancements.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_middleware_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_middleware_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_module_decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_module_scan_and_provide.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_module_system.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_no_db_imports.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_observability.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_orchestrator_parallel.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_p2_scope_log_level.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_primitives_context.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_primitives_data.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_primitives_registry.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_provider_boot_enhanced.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_provider_decorator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_quadkit_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_quadkit_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_repr_helpers.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_resilience_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_combinators.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_core.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_pipeline.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_pipeline_and_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_types_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_result_utils.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_round22_hardening.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_round41_hardening.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_saga_primitives.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_sampling_and_config.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_secret_stores_and_rotation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_serialization_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_serialization_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_service_descriptor.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_structured_logging.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_time_ops.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_validation_coercion.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_validation_exceptions.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_validation_rules.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/test_validation_validator_engine.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/__init__.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/conftest.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_async_validator.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_coercion.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_helpers.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_constants.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_constants_new.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_fields.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_fields_extended.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_init.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_introspection.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_module.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validation_types.py +0 -0
- {quadkit-0.0.42 → quadkit-0.0.44}/tests/unit/validation/test_validator.py +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated public-repository ignore rules.
|
|
2
|
+
# Private monorepo paths are intentionally not referenced here.
|
|
3
|
+
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*.so
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
!.env.example
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
coverage.xml
|
|
18
|
+
htmlcov/
|
|
19
|
+
build/
|
|
20
|
+
dist/
|
|
21
|
+
*.log
|
|
22
|
+
.DS_Store
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: quadkit
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.44
|
|
4
4
|
Summary: Async-first DI/IoC framework for Python — core package
|
|
5
5
|
Project-URL: Homepage, https://dbtinoy-.github.io/quadkit/
|
|
6
6
|
Project-URL: Repository, https://github.com/dbtinoy-/quadkit
|
|
@@ -251,10 +251,10 @@ report vulnerabilities privately per
|
|
|
251
251
|
|
|
252
252
|
## Stability
|
|
253
253
|
|
|
254
|
-
Version `0.0.
|
|
254
|
+
Version `0.0.44` in the `0.x` series, released in lockstep with the
|
|
255
255
|
other four distributions; APIs may change between minor versions until
|
|
256
256
|
1.0 — pin an exact version
|
|
257
|
-
(`quadkit==0.0.
|
|
257
|
+
(`quadkit==0.0.44`) or a tight range (`>=0.0.44,<0.1.0`). Full policy:
|
|
258
258
|
[stability and compatibility](https://dbtinoy-.github.io/quadkit/reference/stability/).
|
|
259
259
|
|
|
260
260
|
## Links
|
|
@@ -199,10 +199,10 @@ report vulnerabilities privately per
|
|
|
199
199
|
|
|
200
200
|
## Stability
|
|
201
201
|
|
|
202
|
-
Version `0.0.
|
|
202
|
+
Version `0.0.44` in the `0.x` series, released in lockstep with the
|
|
203
203
|
other four distributions; APIs may change between minor versions until
|
|
204
204
|
1.0 — pin an exact version
|
|
205
|
-
(`quadkit==0.0.
|
|
205
|
+
(`quadkit==0.0.44`) or a tight range (`>=0.0.44,<0.1.0`). Full policy:
|
|
206
206
|
[stability and compatibility](https://dbtinoy-.github.io/quadkit/reference/stability/).
|
|
207
207
|
|
|
208
208
|
## Links
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# - Database code → quadkit-sql
|
|
14
14
|
# - Auth/JWT/crypto → quadkit-auth
|
|
15
15
|
# - HTTP/ASGI/routing → quadkit-web
|
|
16
|
-
# - Message queue / email → quadkit-queue / quadkit-mailer / quadkit-notification
|
|
17
16
|
# - Any domain-specific feature
|
|
18
17
|
#
|
|
19
18
|
# Core should be lightweight. `pip install quadkit` should take seconds,
|
|
@@ -30,7 +29,7 @@ build-backend = "hatchling.build"
|
|
|
30
29
|
|
|
31
30
|
[project]
|
|
32
31
|
name = "quadkit"
|
|
33
|
-
version = "0.0.
|
|
32
|
+
version = "0.0.44"
|
|
34
33
|
description = "Async-first DI/IoC framework for Python — core package"
|
|
35
34
|
readme = "README.md"
|
|
36
35
|
requires-python = ">=3.11"
|
|
@@ -70,7 +70,7 @@ class ContainerValidator:
|
|
|
70
70
|
# not something the user can fix with annotations.
|
|
71
71
|
logger.warning(
|
|
72
72
|
"validate.scope_check_unhashable_hint",
|
|
73
|
-
|
|
73
|
+
service_type=service_name,
|
|
74
74
|
error=str(e),
|
|
75
75
|
)
|
|
76
76
|
else:
|
|
@@ -85,13 +85,13 @@ class ContainerValidator:
|
|
|
85
85
|
except AttributeError as e:
|
|
86
86
|
logger.warning(
|
|
87
87
|
"validate.scope_check_attribute_error",
|
|
88
|
-
|
|
88
|
+
service_type=service_name,
|
|
89
89
|
error=str(e),
|
|
90
90
|
)
|
|
91
91
|
except (KeyError, ValueError) as e:
|
|
92
92
|
logger.warning(
|
|
93
93
|
"validate.scope_check_resolution_error",
|
|
94
|
-
|
|
94
|
+
service_type=service_name,
|
|
95
95
|
error=str(e),
|
|
96
96
|
)
|
|
97
97
|
|
|
@@ -123,7 +123,7 @@ class ContainerValidator:
|
|
|
123
123
|
except (AttributeError, TypeError, KeyError, ValueError) as e:
|
|
124
124
|
logger.debug(
|
|
125
125
|
"validate_no_orphans.dep_resolution_error",
|
|
126
|
-
|
|
126
|
+
service_type=getattr(service_type, "__name__", str(service_type)),
|
|
127
127
|
error=str(e),
|
|
128
128
|
)
|
|
129
129
|
continue
|
|
@@ -79,7 +79,7 @@ class ServiceResolver:
|
|
|
79
79
|
if self._debug_resolution:
|
|
80
80
|
logger.debug(
|
|
81
81
|
"di.resolution.resolved",
|
|
82
|
-
|
|
82
|
+
service_type=getattr(service_type, "__name__", repr(service_type)),
|
|
83
83
|
)
|
|
84
84
|
return instance
|
|
85
85
|
|
|
@@ -7,7 +7,8 @@ Example:
|
|
|
7
7
|
from quadkit import identity
|
|
8
8
|
|
|
9
9
|
id = identity.generate_for("user") # ULID/UUID based on config
|
|
10
|
-
|
|
10
|
+
opaque = identity.new_uuid() # the configured strategy, not
|
|
11
|
+
# necessarily a UUID — see below
|
|
11
12
|
|
|
12
13
|
For tests:
|
|
13
14
|
from quadkit import identity
|
|
@@ -78,10 +79,26 @@ def generate_for(entity_type: str) -> str:
|
|
|
78
79
|
|
|
79
80
|
|
|
80
81
|
def new_uuid() -> str:
|
|
81
|
-
"""Generate
|
|
82
|
+
"""Generate an id with the ambient generator, whatever it is.
|
|
83
|
+
|
|
84
|
+
**The name is narrower than the behaviour.** This delegates to the
|
|
85
|
+
installed ``IdGeneratorProtocol``, so the result follows
|
|
86
|
+
``IdentityConfig.strategy``: UUID4 by default, but a 36-char UUID7, a
|
|
87
|
+
26-char Crockford base32 ULID, or a prefixed ULID (``usr_01H…``) when
|
|
88
|
+
the application configures one — and whatever a test installs through
|
|
89
|
+
``use()``.
|
|
90
|
+
|
|
91
|
+
Two consequences worth stating, because the name hides both:
|
|
92
|
+
|
|
93
|
+
- **Shape is not guaranteed.** Do not feed the result to a ``UUID``
|
|
94
|
+
column or ``uuid.UUID()`` unless the strategy is pinned to UUID4/7.
|
|
95
|
+
- **Randomness is not guaranteed.** UUID7 and ULID are time-ordered:
|
|
96
|
+
the leading bits are a millisecond timestamp. For a value that must
|
|
97
|
+
be unguessable — a reset token, a session id, a webhook secret — use
|
|
98
|
+
``secrets.token_urlsafe()``, not this.
|
|
82
99
|
|
|
83
100
|
Returns:
|
|
84
|
-
|
|
101
|
+
An id string from the ambient generator.
|
|
85
102
|
"""
|
|
86
103
|
return _ambient.get().generate()
|
|
87
104
|
|
|
@@ -43,15 +43,15 @@ Each log line is a single JSON object emitted by
|
|
|
43
43
|
{
|
|
44
44
|
"timestamp": "2026-08-19 10:15:30",
|
|
45
45
|
"level": "INFO",
|
|
46
|
-
"logger": "quadkit.web.controller",
|
|
47
46
|
"event": "user_created",
|
|
48
47
|
"service": "my-app",
|
|
49
48
|
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
|
|
50
49
|
"span_id": "00f067aa0ba902b7",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
50
|
+
"_logger_name": "quadkit.web.controller",
|
|
51
|
+
"_filename": "controller.py",
|
|
52
|
+
"_lineno": 42,
|
|
53
|
+
"_module": "controller",
|
|
54
|
+
"_func_name": "create_user",
|
|
55
55
|
"user_id": "usr_123"
|
|
56
56
|
}
|
|
57
57
|
```
|
|
@@ -60,16 +60,44 @@ Each log line is a single JSON object emitted by
|
|
|
60
60
|
|-------------|---------------------------------------------------------------|
|
|
61
61
|
| `timestamp` | `TimeStamper(fmt="%Y-%m-%d %H:%M:%S")` |
|
|
62
62
|
| `level` | `structlog.stdlib.add_log_level` |
|
|
63
|
-
| `logger` | `_add_logger_name` — auto-prefixed with `quadkit.` |
|
|
64
63
|
| `event` | Message passed to `logger.info("...")` |
|
|
65
64
|
| `service` | Injected by `configure_logging(service_name=...)` / `Application.name`; overridable via `bind(service=...)` |
|
|
66
65
|
| `trace_id` / `span_id` | `_otel_processor` — only when an OTEL trace context is active |
|
|
67
|
-
| `
|
|
66
|
+
| `_logger_name` | `get_logger()` / `_add_logger_name` — auto-prefixed with `quadkit.` |
|
|
67
|
+
| `_filename` / `_lineno` / `_module` / `_func_name` | `CallsiteParameterAdder`, wrapped by `_NamespacedCallsiteAdder` |
|
|
68
68
|
| `exception` | Formatted traceback, present on `logger.exception(...)` / `exc_info=True` |
|
|
69
69
|
|
|
70
70
|
Key-value arguments passed to a log call are appended verbatim as top-level
|
|
71
71
|
fields (`logger.info("user_created", user_id=usr.id)` → `"user_id"`).
|
|
72
72
|
|
|
73
|
+
## Field names: what the envelope owns, and what you own
|
|
74
|
+
|
|
75
|
+
Two namespaces, so a caller's field and the pipeline's metadata can never
|
|
76
|
+
be the same key:
|
|
77
|
+
|
|
78
|
+
- **`_`-prefixed keys belong to the framework** — `_logger_name`,
|
|
79
|
+
`_filename`, `_lineno`, `_module`, `_func_name`. Do not pass them.
|
|
80
|
+
- **Every other plain name belongs to the caller.** `module=`, `filename=`,
|
|
81
|
+
`name=`, `msg=` are ordinary fields; `logger.info("module_booted",
|
|
82
|
+
module=self.name)` renders the value you passed.
|
|
83
|
+
- **Five envelope names are reserved**: `event`, `level`, `timestamp`,
|
|
84
|
+
`service` and `exception`. `service` is deliberately overridable via
|
|
85
|
+
`bind(service=...)`; the other four are not yours to set.
|
|
86
|
+
`dev/checks/reserved_log_fields.py` fails the build on a call site that
|
|
87
|
+
passes one.
|
|
88
|
+
|
|
89
|
+
`event` is the sharp one: it is structlog's parameter for the *message*, so
|
|
90
|
+
`logger.warning("emit_failed", event=type(evt).__name__)` raises
|
|
91
|
+
`TypeError` — inside the `except` block that was reporting the failure.
|
|
92
|
+
Because a diagnostic must never raise, `_NamedLogger` moves such a field to
|
|
93
|
+
`event_field` rather than letting the call blow up; the gate is what makes
|
|
94
|
+
you rename it properly (`event_type`, `webhook_event`).
|
|
95
|
+
|
|
96
|
+
Callsite metadata reports *your* frame, not the framework's: the adder is
|
|
97
|
+
configured with `additional_ignores=["quadkit.logging"]`, without which
|
|
98
|
+
`_NamedLogger.info` in `logging/factory.py` is the nearest non-structlog
|
|
99
|
+
frame and every line in the process is stamped with it.
|
|
100
|
+
|
|
73
101
|
## Behavior guarantees
|
|
74
102
|
|
|
75
103
|
- **Levels**: `DEBUG < INFO < WARNING < ERROR < CRITICAL`. A global
|
|
@@ -94,5 +122,5 @@ fields (`logger.info("user_created", user_id=usr.id)` → `"user_id"`).
|
|
|
94
122
|
- Never `print()`; never log secret material (redaction is a safety net,
|
|
95
123
|
not a substitute for not logging secrets).
|
|
96
124
|
- For error tracking, forward `level >= ERROR` events with `event`,
|
|
97
|
-
`exception`, `
|
|
125
|
+
`exception`, `_logger_name`, and `trace_id` fields — correlation IDs make
|
|
98
126
|
distributed debugging possible.
|
|
@@ -21,6 +21,7 @@ from quadkit.logging.processors import (
|
|
|
21
21
|
_add_logger_name,
|
|
22
22
|
_context_processor,
|
|
23
23
|
_level_filter_processor,
|
|
24
|
+
_NamespacedCallsiteAdder,
|
|
24
25
|
_otel_processor,
|
|
25
26
|
_redact_processor,
|
|
26
27
|
_sampling_processor,
|
|
@@ -55,7 +56,7 @@ def configure_logging(
|
|
|
55
56
|
service_name: Application name injected into log context.
|
|
56
57
|
levels: Per-logger level overrides. Keys are logger name prefixes,
|
|
57
58
|
values are level strings. Example:
|
|
58
|
-
``{"quadkit.di": "DEBUG", "
|
|
59
|
+
``{"quadkit.di": "DEBUG", "the optional provider module": "WARNING"}``.
|
|
59
60
|
sampling_enabled: Enable deterministic log sampling.
|
|
60
61
|
sampling_default_rate: Default sample rate (1.0 = log everything,
|
|
61
62
|
0.1 = log ~10%).
|
|
@@ -101,13 +102,16 @@ def configure_logging(
|
|
|
101
102
|
_service_processor,
|
|
102
103
|
_otel_processor,
|
|
103
104
|
_redact_processor,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
_NamespacedCallsiteAdder(
|
|
106
|
+
structlog.processors.CallsiteParameterAdder(
|
|
107
|
+
{
|
|
108
|
+
structlog.processors.CallsiteParameter.FILENAME,
|
|
109
|
+
structlog.processors.CallsiteParameter.LINENO,
|
|
110
|
+
structlog.processors.CallsiteParameter.MODULE,
|
|
111
|
+
structlog.processors.CallsiteParameter.FUNC_NAME,
|
|
112
|
+
},
|
|
113
|
+
additional_ignores=["quadkit.logging"],
|
|
114
|
+
),
|
|
111
115
|
),
|
|
112
116
|
structlog.processors.StackInfoRenderer(),
|
|
113
117
|
]
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
Provides ``get_logger()`` for obtaining structlog bound-loggers with a
|
|
4
4
|
``.name`` attribute, and ``LoggerFactoryImpl`` which implements the
|
|
5
5
|
``LoggerFactoryProtocol`` protocol.
|
|
6
|
+
|
|
7
|
+
A logging call must never raise. structlog names the message parameter
|
|
8
|
+
``event``, so ``logger.info("task_finished", event=evt.name)`` is a
|
|
9
|
+
``TypeError`` — raised from inside the ``except`` block that was trying to
|
|
10
|
+
report a failure. ``_deconflict()`` moves such a field to ``event_field``
|
|
11
|
+
instead of letting the diagnostic take down the path it was diagnosing;
|
|
12
|
+
``dev/checks/reserved_log_fields.py`` fails the build on the call site so
|
|
13
|
+
the remap stays a safety net rather than an interface.
|
|
6
14
|
"""
|
|
7
15
|
|
|
8
16
|
from __future__ import annotations
|
|
@@ -16,6 +24,25 @@ if TYPE_CHECKING:
|
|
|
16
24
|
from quadkit.logging.config.models import LoggingConfig
|
|
17
25
|
|
|
18
26
|
|
|
27
|
+
def _deconflict(kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
28
|
+
"""Move a caller field named ``event`` out of structlog's way.
|
|
29
|
+
|
|
30
|
+
``event`` is structlog's parameter for the log message, so passing it as
|
|
31
|
+
a field raises ``TypeError``. The field is preserved under
|
|
32
|
+
``event_field`` (``event_field_``, ``event_field__``, … if the caller
|
|
33
|
+
already used that name) rather than dropped: a log call is a diagnostic
|
|
34
|
+
and must not raise.
|
|
35
|
+
"""
|
|
36
|
+
if "event" not in kwargs:
|
|
37
|
+
return kwargs
|
|
38
|
+
safe = dict(kwargs)
|
|
39
|
+
key = "event_field"
|
|
40
|
+
while key in safe:
|
|
41
|
+
key += "_"
|
|
42
|
+
safe[key] = safe.pop("event")
|
|
43
|
+
return safe
|
|
44
|
+
|
|
45
|
+
|
|
19
46
|
class _NamedLogger:
|
|
20
47
|
"""Thin wrapper that adds ``.name`` to a structlog bound logger.
|
|
21
48
|
|
|
@@ -34,26 +61,31 @@ class _NamedLogger:
|
|
|
34
61
|
# These exist so ``hasattr(_NamedLogger, 'debug')`` etc. return True for
|
|
35
62
|
# the DI validator. At runtime the call is forwarded via __getattr__.
|
|
36
63
|
|
|
37
|
-
|
|
38
|
-
|
|
64
|
+
# ``msg`` is positional-only: without the ``/`` this wrapper would add a
|
|
65
|
+
# reserved word of its own making, and ``logger.info("x", msg=body)``
|
|
66
|
+
# would fail with "got multiple values for argument 'msg'" even though
|
|
67
|
+
# the underlying structlog logger has no such parameter.
|
|
68
|
+
|
|
69
|
+
def debug(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
70
|
+
self._inner.debug(msg, *args, **_deconflict(kwargs))
|
|
39
71
|
|
|
40
|
-
def info(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
|
41
|
-
self._inner.info(msg, *args, **kwargs)
|
|
72
|
+
def info(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
73
|
+
self._inner.info(msg, *args, **_deconflict(kwargs))
|
|
42
74
|
|
|
43
|
-
def warning(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
|
44
|
-
self._inner.warning(msg, *args, **kwargs)
|
|
75
|
+
def warning(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
76
|
+
self._inner.warning(msg, *args, **_deconflict(kwargs))
|
|
45
77
|
|
|
46
|
-
def error(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
|
47
|
-
self._inner.error(msg, *args, **kwargs)
|
|
78
|
+
def error(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
79
|
+
self._inner.error(msg, *args, **_deconflict(kwargs))
|
|
48
80
|
|
|
49
|
-
def critical(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
|
50
|
-
self._inner.critical(msg, *args, **kwargs)
|
|
81
|
+
def critical(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
82
|
+
self._inner.critical(msg, *args, **_deconflict(kwargs))
|
|
51
83
|
|
|
52
|
-
def exception(self, msg: str, *args: Any, **kwargs: Any) -> None:
|
|
53
|
-
self._inner.exception(msg, *args, **kwargs)
|
|
84
|
+
def exception(self, msg: str, /, *args: Any, **kwargs: Any) -> None:
|
|
85
|
+
self._inner.exception(msg, *args, **_deconflict(kwargs))
|
|
54
86
|
|
|
55
87
|
def bind(self, **kwargs: Any) -> _NamedLogger:
|
|
56
|
-
result = self._inner.bind(**kwargs)
|
|
88
|
+
result = self._inner.bind(**_deconflict(kwargs))
|
|
57
89
|
return self if result is self._inner else _NamedLogger(result, self.name)
|
|
58
90
|
|
|
59
91
|
def unbind(self, *keys: str) -> _NamedLogger:
|
|
@@ -122,18 +154,21 @@ class LoggerFactoryImpl:
|
|
|
122
154
|
self._config = config
|
|
123
155
|
|
|
124
156
|
def get_logger(self, name: str | None = None) -> LoggerProtocol:
|
|
125
|
-
"""Get or create a logger
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
157
|
+
"""Get or create a logger.
|
|
158
|
+
|
|
159
|
+
This used to ``bind(service=name)``. ``service`` is the envelope
|
|
160
|
+
field identifying the *application* (set by ``configure_logging()``
|
|
161
|
+
and used for log routing), and ``_service_processor`` yields to a
|
|
162
|
+
bound value — so every DI-resolved logger relabelled the service as
|
|
163
|
+
whichever component had asked for it. The logger name already
|
|
164
|
+
travels in ``_logger_name``.
|
|
165
|
+
"""
|
|
166
|
+
return cast("LoggerProtocol", get_logger(name))
|
|
133
167
|
|
|
134
168
|
|
|
135
169
|
__all__ = [
|
|
136
170
|
"LoggerFactoryImpl",
|
|
137
171
|
"_NamedLogger",
|
|
172
|
+
"_deconflict",
|
|
138
173
|
"get_logger",
|
|
139
174
|
]
|
|
@@ -108,6 +108,52 @@ def _otel_processor(
|
|
|
108
108
|
return event_dict
|
|
109
109
|
|
|
110
110
|
|
|
111
|
+
class _NamespacedCallsiteAdder:
|
|
112
|
+
"""Run structlog's ``CallsiteParameterAdder`` in the ``_`` namespace.
|
|
113
|
+
|
|
114
|
+
Two problems with using the adder directly:
|
|
115
|
+
|
|
116
|
+
1. It writes ``filename``, ``lineno``, ``module`` and ``func_name`` —
|
|
117
|
+
ordinary domain words. ``logger.info("module_booted",
|
|
118
|
+
module=self.name)`` is a natural call (this repo had 111 of them) and
|
|
119
|
+
the adder silently overwrote every one with the emitting *source*
|
|
120
|
+
file's module. Framework metadata therefore lives under ``_``-
|
|
121
|
+
prefixed keys, the convention ``_logger_name`` already follows, and
|
|
122
|
+
the plain names belong to the caller.
|
|
123
|
+
2. Left to itself the adder reports ``_NamedLogger.info`` in
|
|
124
|
+
``logging/factory.py`` as the callsite of every log line in the
|
|
125
|
+
process, because that wrapper is the nearest non-structlog frame.
|
|
126
|
+
``additional_ignores`` skips the framework's own logging package so
|
|
127
|
+
the real caller is reported.
|
|
128
|
+
|
|
129
|
+
The inner adder is run against a scratch dict so it cannot clobber a
|
|
130
|
+
caller field on its way past.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
__slots__ = ("_inner",)
|
|
134
|
+
|
|
135
|
+
#: Keys structlog's adder may consult on the stdlib-bridge path.
|
|
136
|
+
_PASSTHROUGH = ("_record", "_from_structlog")
|
|
137
|
+
|
|
138
|
+
def __init__(self, inner: Any) -> None:
|
|
139
|
+
self._inner = inner
|
|
140
|
+
|
|
141
|
+
def __call__(
|
|
142
|
+
self,
|
|
143
|
+
logger: Any,
|
|
144
|
+
method_name: str,
|
|
145
|
+
event_dict: dict[str, Any],
|
|
146
|
+
) -> dict[str, Any]:
|
|
147
|
+
scratch: dict[str, Any] = {
|
|
148
|
+
key: event_dict[key] for key in self._PASSTHROUGH if key in event_dict
|
|
149
|
+
}
|
|
150
|
+
for key, value in self._inner(logger, method_name, scratch).items():
|
|
151
|
+
if key in self._PASSTHROUGH:
|
|
152
|
+
continue
|
|
153
|
+
event_dict.setdefault(f"_{key}", value)
|
|
154
|
+
return event_dict
|
|
155
|
+
|
|
156
|
+
|
|
111
157
|
def _add_logger_name(
|
|
112
158
|
logger: Any,
|
|
113
159
|
method_name: str,
|
|
@@ -116,12 +162,14 @@ def _add_logger_name(
|
|
|
116
162
|
"""Safe replacement for structlog.stdlib.add_logger_name.
|
|
117
163
|
|
|
118
164
|
Handles loggers that don't have a ``.name`` attribute (like
|
|
119
|
-
``PrintLogger``).
|
|
165
|
+
``PrintLogger``). Writes ``_logger_name`` — the key ``get_logger()``
|
|
166
|
+
already binds, and the framework namespace — not ``logger``, which a
|
|
167
|
+
caller may legitimately want as a field of their own.
|
|
120
168
|
"""
|
|
121
|
-
if "
|
|
169
|
+
if "_logger_name" not in event_dict:
|
|
122
170
|
name = getattr(logger, "name", None)
|
|
123
171
|
if name:
|
|
124
|
-
event_dict["
|
|
172
|
+
event_dict["_logger_name"] = name
|
|
125
173
|
return event_dict
|
|
126
174
|
|
|
127
175
|
|
|
@@ -232,6 +280,7 @@ def _sampling_processor(
|
|
|
232
280
|
__all__ = [
|
|
233
281
|
"LEVEL_NAME_TO_INT",
|
|
234
282
|
"_LoggingState",
|
|
283
|
+
"_NamespacedCallsiteAdder",
|
|
235
284
|
"_add_logger_name",
|
|
236
285
|
"_context_processor",
|
|
237
286
|
"_level_filter_processor",
|
|
@@ -23,7 +23,7 @@ logger = get_logger(__name__)
|
|
|
23
23
|
class RetryMiddleware:
|
|
24
24
|
"""Middleware that retries the downstream handler on transient failures.
|
|
25
25
|
|
|
26
|
-
Delegates to :func:`
|
|
26
|
+
Delegates to :func:`the optional provider module` for backoff logic.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
29
|
catch: Exception types considered retryable. Must be explicitly provided.
|
{quadkit-0.0.42 → quadkit-0.0.44}/src/quadkit/observability/di/sub_providers/observability.py
RENAMED
|
@@ -38,7 +38,7 @@ class ObservabilityProvider(Provider):
|
|
|
38
38
|
on module composition order — and in nested module graphs this
|
|
39
39
|
provider lands *after* ``MonitorProvider`` and suppresses the concrete
|
|
40
40
|
collector. Guard each token, the same pattern the other fallback
|
|
41
|
-
sites use (``quadkit-auth``, ``quadkit-cache``, ``
|
|
41
|
+
sites use (``quadkit-auth``, ``quadkit-cache``, ``the optional provider``),
|
|
42
42
|
so whichever real implementation registered first survives.
|
|
43
43
|
"""
|
|
44
44
|
collector = NoOpMetricsCollector()
|
|
@@ -65,13 +65,28 @@ def install(implementation: HasherProtocol) -> None:
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
def hash_hex(data: str | bytes) -> str:
|
|
68
|
-
"""Hash data and return hex digest.
|
|
68
|
+
"""Hash data with the ambient hasher and return a hex digest.
|
|
69
|
+
|
|
70
|
+
**The algorithm is a process-wide config value, not a property of this
|
|
71
|
+
call.** ``HashingConfig.default_hasher`` selects sha256 (the default) or
|
|
72
|
+
blake2b, and ``use()`` swaps it again in tests — with no signal at the
|
|
73
|
+
call site and no algorithm marker in the returned string.
|
|
74
|
+
|
|
75
|
+
That makes this the right tool for an **ephemeral** digest (a cache key,
|
|
76
|
+
a content fingerprint compared within one process, a change detector)
|
|
77
|
+
and the wrong one for a **persisted** digest. A stored value is silently
|
|
78
|
+
coupled to the config that produced it: flip ``default_hasher`` and
|
|
79
|
+
every row written under the old algorithm stops matching, which for a
|
|
80
|
+
lookup key like a hashed API token means every credential fails to
|
|
81
|
+
resolve at once. Persist digests with an explicitly constructed hasher
|
|
82
|
+
(``Sha256Hasher().digest(...)``), or store the algorithm alongside the
|
|
83
|
+
digest so the value is self-describing.
|
|
69
84
|
|
|
70
85
|
Args:
|
|
71
86
|
data: String or bytes to hash.
|
|
72
87
|
|
|
73
88
|
Returns:
|
|
74
|
-
Hex-encoded digest string.
|
|
89
|
+
Hex-encoded digest string from the ambient hasher.
|
|
75
90
|
"""
|
|
76
91
|
return _ambient.get().digest(data)
|
|
77
92
|
|
|
@@ -9,7 +9,8 @@ import pytest
|
|
|
9
9
|
from quadkit.contracts.security import HasherProtocol, KeyDerivationProtocol
|
|
10
10
|
from quadkit.di.container import Container
|
|
11
11
|
from quadkit.security.config import HashingConfig, SecurityConfig
|
|
12
|
-
from quadkit.security.hashing import
|
|
12
|
+
from quadkit.security.hashing import PBKDF2KDF, Blake2bHasher, Sha256Hasher
|
|
13
|
+
from quadkit.security.hashing import ambient as hashing
|
|
13
14
|
from quadkit.security.provider import SecurityProvider
|
|
14
15
|
|
|
15
16
|
|
|
@@ -95,3 +96,36 @@ class TestSecurityProviderHashingDefaults:
|
|
|
95
96
|
|
|
96
97
|
assert isinstance(hasher, Sha256Hasher)
|
|
97
98
|
assert isinstance(kdf, PBKDF2KDF)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class TestAmbientHasherIsNotAPersistenceFormat:
|
|
102
|
+
"""The ambient digest is a process-wide config value, not a stable format."""
|
|
103
|
+
|
|
104
|
+
def test_swapping_the_hasher_invalidates_every_stored_digest(self) -> None:
|
|
105
|
+
"""A persisted `hash_hex` value is coupled to `default_hasher`.
|
|
106
|
+
|
|
107
|
+
Nothing at the call site says so, and the digest carries no
|
|
108
|
+
algorithm marker, so the coupling is invisible until someone flips
|
|
109
|
+
`HashingConfig.default_hasher` — at which point a stored lookup key
|
|
110
|
+
(a hashed API token, say) stops matching for every row at once. The
|
|
111
|
+
docstring now says this; the test keeps it true.
|
|
112
|
+
"""
|
|
113
|
+
token = "sk-live-abc123"
|
|
114
|
+
|
|
115
|
+
stored = hashing.hash_hex(token)
|
|
116
|
+
|
|
117
|
+
with hashing.use(Blake2bHasher()):
|
|
118
|
+
assert hashing.hash_hex(token) != stored
|
|
119
|
+
assert hashing.verify_hex(token, stored) is False
|
|
120
|
+
|
|
121
|
+
assert hashing.verify_hex(token, stored) is True
|
|
122
|
+
|
|
123
|
+
def test_an_explicit_hasher_is_immune_to_the_ambient_swap(self) -> None:
|
|
124
|
+
"""The documented escape hatch for values that outlive the process."""
|
|
125
|
+
pinned = Sha256Hasher()
|
|
126
|
+
token = "sk-live-abc123"
|
|
127
|
+
|
|
128
|
+
stored = pinned.digest(token)
|
|
129
|
+
|
|
130
|
+
with hashing.use(Blake2bHasher()):
|
|
131
|
+
assert pinned.digest(token) == stored
|
|
@@ -6,6 +6,8 @@ from __future__ import annotations
|
|
|
6
6
|
import time
|
|
7
7
|
from uuid import UUID
|
|
8
8
|
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
9
11
|
from quadkit.contracts.core.identity import IdStrategy
|
|
10
12
|
from quadkit.identity import ambient
|
|
11
13
|
from quadkit.identity.constants import DEFAULT_PREFIX_SEPARATOR, DEFAULT_ULID_LENGTH
|
|
@@ -135,3 +137,47 @@ def test_ambient_use_context_stacks() -> None:
|
|
|
135
137
|
|
|
136
138
|
# Restored to the original after the outer block exits.
|
|
137
139
|
assert not ambient.generate_for("X").startswith(("outer-", "inner-"))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ── What the name promises vs what the call returns ───────────────────────
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_new_uuid_is_whatever_the_ambient_generator_is() -> None:
|
|
146
|
+
"""``new_uuid()`` is not a UUID unless the configured strategy is one.
|
|
147
|
+
|
|
148
|
+
The name says UUID4 and the docstring used to agree with it, but the
|
|
149
|
+
call delegates to the installed ``IdGeneratorProtocol``. An application
|
|
150
|
+
that configures ULID for database locality gets a 26-character Crockford
|
|
151
|
+
base32 string out of a function named ``new_uuid`` — so a ``UUID``
|
|
152
|
+
column or a ``uuid.UUID()`` parse on the far end fails at runtime, not
|
|
153
|
+
at boot.
|
|
154
|
+
"""
|
|
155
|
+
with ambient.use(UlidGenerator()):
|
|
156
|
+
value = ambient.new_uuid()
|
|
157
|
+
|
|
158
|
+
assert len(value) == DEFAULT_ULID_LENGTH
|
|
159
|
+
with pytest.raises(ValueError, match=r"badly formed|invalid"):
|
|
160
|
+
UUID(value)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_new_uuid_is_not_guaranteed_unpredictable() -> None:
|
|
164
|
+
"""Time-ordered strategies leak their timestamp into the leading bits.
|
|
165
|
+
|
|
166
|
+
``SECURITY.md`` used to describe this call as "uuid4() (random)" under
|
|
167
|
+
the heading *UUID predictability*, which is exactly the claim a reader
|
|
168
|
+
checks before using an id as a secret. Two ULIDs minted a moment apart
|
|
169
|
+
share their timestamp prefix and sort in creation order.
|
|
170
|
+
"""
|
|
171
|
+
with ambient.use(UlidGenerator()):
|
|
172
|
+
first = ambient.new_uuid()
|
|
173
|
+
second = ambient.new_uuid()
|
|
174
|
+
time.sleep(0.002)
|
|
175
|
+
later = ambient.new_uuid()
|
|
176
|
+
|
|
177
|
+
# Same millisecond: identical timestamp prefix, only the random tail
|
|
178
|
+
# differs (the tail is not monotonic within a tick, so no ordering is
|
|
179
|
+
# asserted there).
|
|
180
|
+
assert first[:6] == second[:6]
|
|
181
|
+
# Across a tick: the value sorts by creation time, which is the property
|
|
182
|
+
# that makes it guessable.
|
|
183
|
+
assert later > first
|