feat: provider extension points, ProviderFulfilment contract, auth security fixes#253
Merged
Merged
Conversation
047e784 to
8a683c7
Compare
62374a4 to
5dae11d
Compare
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
3cadf35 to
a05feb8
Compare
Create orb.providers.aws.value_objects as the canonical public import path for AWSAllocationStrategy and its helpers. Update callers in ec2_fleet handler, AWSTemplate aggregate, and tests to import from the new shallow path rather than the internal domain sub-package. The class definition stays in providers/aws/domain/template/value_objects; value_objects.py re-exports it to establish a stable provider-level API.
Wrap execute_operation in asyncio.timeout(dispatch_timeout_seconds) to prevent unbounded awaits when a provider hangs. Run _persist_acquiring via asyncio.to_thread so the blocking DB write does not hold the event loop between retry attempts. dispatch_timeout_seconds is read from request config (key dispatch_timeout_seconds) and defaults to 300 s. TimeoutError is caught and returned as a final failure result so the retry loop can record the outcome cleanly.
- Delete validate_provider_availability (zero callers; bootstrap
moved to provider_services.py)
- Remove unused ConfigurationPort import from provider_validation_service
- Inject ProviderValidationService via constructor in
CreateMachineRequestHandler instead of constructing a second
instance locally, so the registered singleton is used
- Replace hardcoded ensure_provider_type_registered("aws") in
_load_strategy_defaults with pkgutil discovery of all provider
subpackages that carry a registration module
- Update tests to pass provider_validation_service as a constructor
argument and configure AsyncMock return values appropriately
- Add orb.providers to the architecture leak-detection whitelist
for config/loader.py (intentional bootstrap wiring)
Register IAMAuthStrategy and CognitoAuthStrategy in providers/aws/registration.py via register_aws_auth_strategies(), called from initialize_aws_provider(). Remove provider-specific if/elif branches and inline imports from api/server.py. _create_auth_strategy now delegates uniformly to AuthRegistry.get_strategy() for all strategy names. Config extraction is centralised in _build_strategy_kwargs(). No orb.providers.aws.* imports remain in api/server.py.
- Replace `if not registered_types else "aws"` fallback with
RuntimeError when no providers are registered in
infrastructure_command_handler._get_active_providers (both
no-config and all-disabled branches)
- Replace hardcoded Region/Profile display in
_show_provider_infrastructure with CLISpecRegistry.format_display;
fall back to raw key/value for unknown provider types
- Replace `getattr(args, "provider_type", "aws")` default in
handle_provider_add with an explicit error when provider_type is
absent
- Replace `provider.get("type", "aws")` default in
handle_provider_update with `provider.get("type") or ""`; CLISpec
lookup returns None for empty string, handled by existing fallback
- Add unit tests for all changed behaviours
Replace hardcoded --aws-profile/--aws-region in providers add
and providers update subcommands with registry iteration:
CLISpecRegistry.all().values() → spec.add_arguments(parser).
Add register_all_provider_cli_specs() to providers/registration.py
as a lightweight bootstrap (no full strategy init) that build_parser
calls before iterating the registry, so provider-specific flags are
available before any application context exists.
Inject per-provider CLI flags into the init subparser via the same
registry loop, enabling _get_default_config to use spec.extract_config()
instead of hardcoded {"profile": args.profile, "region": args.region},
with fallback to init-level flags for backward compatibility.
Update architecture known-violation lists to whitelist the intentional
cli/args.py → orb.providers.registration import.
Add default_api field to ProviderRegistration so each provider can declare its default API name at registration time. AWS reads the value from aws_defaults.json. ProviderRegistry.get_default_api exposes it via ProviderRegistryPort. TemplateDefaultsService delegates the provider_api fallback to the registry instead of reading handlers.defaults.default_handler directly, removing the AWS-specific config path from the application layer. Remove hardcoded "aws" default from TemplateCreateRequest.provider_api and the templates router create path; callers must supply provider_api or the command handler will reject the request explicitly.
Remove AWS-specific getattr blocks and top-level launch_template_id from TemplateDTO. Add provider_config: BaseModel | None populated via TemplateExtensionRegistry.create_extension_config so infra layer stays provider-agnostic. AWSTemplateDTOConfig captures fleet_type, fleet_role, percent_on_demand, launch_template_id, abis_instance_requirements. AWSTemplate.validate_aws_template promotes from provider_config dict for round-trip compatibility via model_dump. Tests updated accordingly.
Introduce per-provider field-mapping extension points in the HostFactory scheduler so AWS-specific logic no longer lives in shared infrastructure: - Add FieldMappingPort protocol: get_mappings(), apply_defaults(), derive_attributes() - Add FieldMappingRegistry (simple class-variable dict, same pattern as CLISpecRegistry) - Add AWSFieldMapping adapter (providers/aws/scheduler/) that owns the AWS field-name dict, apply_aws_defaults logic, and the derive_cpu_ram_from_instance_type call - Remove apply_aws_defaults from HostFactoryFieldMappings (shared class) and the unconditional call in hostfactory_strategy.py; replace with registry.get(provider_type).apply_defaults(mapped) - Remove direct orb.providers.aws.utilities.ec2.instances imports from field_mapper.py and hostfactory_strategy.py; both now delegate to registry.get(provider_type).derive_attributes() - Change field_mapper.py provider_type default from "aws" to None - Register AWSFieldMapping in initialize_aws_provider() - Remove stale known-violations from test_provider_leak_detection
Replace the stringly-typed is_final boolean with an explicit Accepted | Completed | RequiresFollowUp | Failed discriminated union. ProvisioningResult.outcome is set on every return path; is_final is derived from it via __post_init__ for backward compatibility. BaseProviderStrategy gains three abstract async methods (acquire, return_machines, get_status) that AWSProvider- Strategy implements, correctly modelling AWS async-acceptance semantics. assert_never() guards all match exhaustion points.
Add ProviderDefaultsLoaderPort protocol, DefaultsLoaderRegistry (class-var dict, same pattern as CLISpecRegistry), and AWSDefaultsLoader that reads aws_defaults.json via importlib.resources. Register AWS loader in initialize_aws_provider(). Refactor ConfigurationLoader._load_strategy_defaults to iterate the registry instead of reflecting over pkgutil.iter_modules.
TerminateInstances is accepted asynchronously — instances enter shutting-down, not terminated. Writing COMPLETED immediately was a lie that caused ReturnMachinesOrchestrator to exit while machines were still running. Replace _update_request_to_completed with _update_request_to_terminating (IN_PROGRESS) so background sync can poll and transition to COMPLETED only when all instances reach terminated. Also adds machine_ids to ReturnMachinesOutput so callers see which machines were submitted for return.
Remove has_extension guards from _get_extension_defaults and
_get_provider_instance_extension_defaults — get_extension_defaults
already returns {} for unknown providers so the checks are redundant.
Remove hasattr/getattr dynamic validate_{provider_type} dispatch from
validate_template_with_extensions — no Template subclass in the
codebase has a validate_aws() or similar method, making the block
unreachable dead code. Provider-specific validation belongs in the
extension registry, not on template objects.
Move provider-specific tests under tests/providers/<name>/: - tests/unit/providers/aws/** -> tests/providers/aws/unit/ - tests/onmoto/ -> tests/providers/aws/moto/ - tests/onaws/ -> tests/providers/aws/live/ - tests/unit/providers/test_aws_handlers.py -> tests/providers/aws/unit/ Cross-provider files remain in tests/unit/providers/. Add provider-aware pytest flags to tests/conftest.py: - --live (replaces --run-aws; backward-compat alias kept) - --no-mocked (skip moto subtree) - --provider <name> (filter to one provider) Add tests/providers/aws/conftest.py consolidating moto fixtures. Thin moto/conftest.py re-exports helpers for existing imports. Live conftest pre-flight gated behind --live flag. Update makefiles/common.mk TESTS_ONMOTO to new path. Update pyproject.toml norecursedirs to tests/providers/aws/live.
FollowUpContext types are pure frozen value objects with literal discriminants — domain concepts, not application concerns. Moving them to orb.domain.base.follow_up_context eliminates the domain→application import violation introduced alongside OperationOutcome. orb.application.services.request_follow_up_context is kept as a re-export shim for backward compatibility.
When _load_strategy_defaults is called before a full DI bootstrap (e.g. bare config loading or isolated tests), DefaultsLoaderRegistry is empty because AWSDefaultsLoader is only registered inside initialize_aws_provider(). Add register_all_defaults_loaders() to orb.providers.registration (same lightweight pattern as register_all_provider_cli_specs()) and call it from _load_strategy_defaults when the registry has no entries.
- Remove provider_config_handler aws_region/aws_profile fallback; require CLISpec registration for known provider types - Document HostFactoryFieldMappings.MAPPINGS["aws"] as bootstrap-free fallback; canonical AWS mappings live in AWSFieldMapping adapter - Update onaws → providers/aws/live path stragglers in dev-tools and contract test docstrings; keep test_onaws.py target intact - Add provider-aware Make targets: test-no-live, test-providers, test-providers-aws[-unit|-moto|-live], test-architecture - Whitelist config/loader.py → orb.providers.registration as known bootstrap-only import in provider-leak detection
…stry test test_aws_extension_registration called clear_registry() and registered AWSTemplateExtensionConfig against the "aws" key, but never restored the registry. The production bootstrap registers AWSTemplateDTOConfig against "aws"; after the test ran, subsequent tests saw AWSTemplateExtensionConfig instead, causing TemplateDTO.from_domain to produce empty provider_config for all AWS templates — 147 failures across moto and unit test suites. Wrap the mutation in try/finally and snapshot-restore both _extensions and _extension_instances dicts so the registry is identical before and after.
When tests/onmoto/conftest.py was migrated to tests/providers/aws/ conftest.py, the handler construction was accidentally changed from using cfg_port (the container-resolved ConfigurationPort) to the config_port parameter (which callers pass as None). Handlers such as RunInstancesHandler require a non-None config_port to build launch parameters; with None they raised AWSConfigurationError, the acquire returned FAILED, and HostFactory mapped that to "complete_with_error" — a value not in RequestStatus that wait_for_request never treats as terminal, causing a 30-second timeout. Fix: prefer cfg_port when config_port is None, matching the original onmoto/conftest.py behaviour.
…efaults in remaining test files Pyright misreports AuthConfig(strategy="...") and BearerTokenAuthSubConfig(secret_key=...) as missing required fields even though all other fields carry Field(...) defaults with extra="forbid" set. This is a known pyright/pydantic-v2 interaction. Applied the same # type: ignore[call-arg] suppression already used across the codebase for identical false-positives.
… infrastructure layer Per clean architecture rules, mutable global registry state is an infrastructure concern, not a domain concern. Aligns with the sibling DefaultsLoaderRegistry and FieldMappingRegistry, which already live under infrastructure/registry/. Protocol interfaces (ProviderCLISpecPort, TemplateExtension) remain in the domain layer; only the registry implementations move. Updates the architecture violation counts to reflect the lower number of domain-layer infrastructure leaks after the move.
ProvisioningResult is shared across providers; AWS-specific nouns on its field names leaked provider details into application-layer types. The AWS extractor still populates these fields; the names no longer encode the source provider.
…acity_based_fulfilment The parameter was declared in the signature and documented in the docstring but never referenced in the function body. Both call sites (ec2_fleet and spot_fleet handlers) already omit it via keyword args, so removal requires no changes at the call sites.
Replace Any-typed request and status params with concrete types (Request and RequestStatus). Lift both imports to module level and remove the five deferred per-method imports of RequestStatus that were scattered across _update_request_to_in_progress, _execute_deprovisioning_for_request, _update_request_to_failed, _update_request_to_terminating, and _update_request_to_completed. Also remove the now-redundant deferred Request import inside execute_command and the deferred RequestStatus import in _handle_dry_run.
…EADME The example showed `from src.domain.template.extensions import ...` which had two problems: the `src.` prefix was never valid (the package root is `orb`), and the class moved to `orb.infrastructure.registry.template_extension_registry`. Update to the correct canonical path.
…emove infra import application layer now depends on TemplateExtensionRegistryPort (Protocol) defined in the domain layer. Infrastructure registry remains; an adapter satisfies the port via DI. Removes the only application→infrastructure registry import; aligns with the DefaultsLoaderPort / FieldMappingPort pattern. - Add TemplateExtensionRegistryPort (Protocol) to domain/template/ports/ - Add TemplateExtensionRegistryAdapter in infrastructure/registry/ wrapping classmethods - TemplateDefaultsService constructor accepts TemplateExtensionRegistryPort (Optional) - DI factory injects TemplateExtensionRegistryAdapter() at construction time - violation_counts.json: application_forbidden_imports 6 → 5
Large ABIS scenarios with capacity=100 occasionally exceed 60s on a single REST call because the request_machines / get_request_status path issues many AWS describe_* calls under load. The 2 minute ceiling gives headroom without affecting fast scenarios, which return well under the old limit.
…der_error with read-side alias Outer envelope key in error_details is renamed to be provider-neutral. The read side accepts both old and new key names so persisted records written before this change keep working. Inner AWS-specific dict keys (aws_request_id, aws_error_code, aws_error_message) remain — they are AWS exception field names, not shared types.
…rio yields <2 instances EC2Fleet Maintain + spot uses weighted vmTypes, so capacity_to_request=4 can be fulfilled by a single physical instance with WeightedCapacity=4. The partial-return-reduces-capacity test needs at least 2 physical instances to terminate one and verify the other survives. Mirrors the existing skip in test_partial_return_terminates_instance_only (line 2237).
40eb900 to
3792bd4
Compare
Lock had drifted to msgpack 1.1.2 (out-of-bounds read on Unpacker reuse) during rebase replay. uv lock --upgrade brings transitive deps in line with current main and clears the high-severity vulnerability.
ListRequestsHandler now eagerly instantiates RequestDTOFactory in __init__ (factory hoist). The previous test patched the factory after the handler was already constructed, so the patch had no effect and the real factory accessed attributes the SimpleNamespace mock did not define (e.g. last_status_check). Move the construction inside the patch context and re-target the patch at the import site.
…return tests
EC2Fleet partial path now calls _fleet_has_no_remaining_instances, which
runs _collect_with_next_token in a NextToken loop against a MagicMock
ec2_client. MagicMock.get(...) returns a truthy MagicMock for the
NextToken key, so the loop never terminates — the test hung indefinitely.
SpotFleet partial path has the same defensive call. Its retry-based
variant returns a MagicMock whose .get('ActiveInstances', []) yields an
empty iterator, which falsely flags the fleet as empty and triggers an
unintended launch-template cleanup, failing the assertion.
Patch _fleet_has_no_remaining_instances to return False on both
partial-return tests so the production code skips the new defensive
check and the original partial-return semantic is exercised.
This was referenced Jun 22, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds provider extension points so new providers (Azure, GCP, OCI, etc.) can be added cleanly without leaking provider-specific knowledge into shared services. Scope grew during review: the branch now also includes an auth subsystem refactor with typed sub-configs, four security fixes found during an auth audit, AWS error detail surfacing, provider registration consolidation, a ProviderFulfilment domain contract that fixes weighted-fleet status semantics, an MCP server bootstrap fix, several live-test scheduler/wire-format corrections, and CI/test infrastructure improvements.
Motivation: In-flight provider PRs (#234 OCI, plus #256/#257/#258 — the Azure + GCP work originally proposed in #240, now split into a common-scaffold PR plus one per provider) were each touching 50+ shared files because
mainlacked proper extension points. This PR adds those extension points and tightens the seams so new provider PRs are small and reviewable.After this lands, adding a new provider touches: 1 line in
_REGISTERED_PROVIDERS+providers/<name>/package + SDK deps.Extension points added (8)
ProviderRegistration.default_api— provider declares its default API at registration;ProviderRegistry.get_default_api()exposes it;TemplateDefaultsServicedelegates instead of reading provider-internal config directly. Removes hardcoded"aws"defaults fromapi/routers/templates.py.CLISpecRegistryenforcement —cli/args.py,init_command_handler.py,infrastructure_command_handler.py,provider_config_handler.pyall drive provider flags/display/config from the registry. No more hardcoded--aws-profile/--aws-regionlines per consumer.TemplateExtensionRegistry—TemplateDTO.provider_config: BaseModel | Nonetyped field populated via the registry. Replaces thegetattr(template, "fleet_type", None)string-literal pattern infrom_domain. AWS-specific fields move intoAWSTemplateDTOConfig.OperationOutcometyped discriminated union (Accepted | Completed | RequiresFollowUp | Failed). Replaces stringly-typedprovider_metadatakeys. Provider strategies declare actual operation state explicitly; orchestrator pattern-matches withassert_never()for exhaustiveness.AuthRegistryenforcement —iam/cognitostrategies now registered by the AWS provider inproviders/aws/registration.py;api/server.pydispatch is uniformauth_registry.get_strategy(...)with no provider-specific imports.FieldMappingRegistryfor HostFactory scheduler — per-provider field-name mappings,apply_defaultshook, andderive_attributes(cpu/ram lookup) hook. Removes AWS-specific imports from shared scheduler infrastructure.DefaultsLoaderRegistry— provider defaults loaded via registered loaders;config/loader.pyiterates instead of hardcoded dispatch.ProviderFulfilmentcontract (NEW) —ProviderPort.check_hosts_statusreturnsCheckHostsStatusResultwithProviderFulfilment(state, message, target_units, fulfilled_units, …). Every provider computes fulfilment in its own API terms (RunInstances: instance count; EC2Fleet/SpotFleet: weighted capacity vs target; ASG: weighted InService sum vs DesiredCapacity). Application'srequest_status_servicetrusts the provider verdict — no count math, no AWS-specific keys leak into shared code. Future providers (GCP MIG / Azure VMSS / OCI Pool) plug in identically.Auth subsystem refactor
IAMAuthSubConfig,CognitoAuthSubConfig,BearerTokenAuthSubConfig,ProviderAuthSubConfig— Pydantic models replace bare dicts for auth configuration.from_auth_config(cls, auth_config)classmethod on each strategy — single, typed construction path.AuthRegistry.get_strategy(name, auth_config)unified signature._build_strategy_kwargsdispatch block fromapi/server.py.register_aws_auth_strategies()now reachable from bootstrap (was dead code).EnhancedBearerTokenStrategyasbearer_token_enhanced.Security fixes (4 critical/high)
These findings came out of an auth security review; the four issues below are fixed in this PR. Remaining hardening items (IAM admin role ARN allowlist,
SecretStrfor keys, jti claim, CORS defaults) are tracked in a follow-up epic._get_public_keyreturned a raw JWK dict; PyJWT could not decode itcryptographylibassume_permissionsprivilege bypass — config flag granted all permissions without any AWS checkORB_IAM_ASSUME_PERMISSIONS_DEV_ONLY=trueenv var; logsCRITICALwhen activewarninginstead of raisingConfigurationError, consistent with base strategyalgorithmfield accepted arbitrary strings includingnone{HS256, HS384, HS512}with explicitnonerejectionStatus / fulfilment fixes (post-review)
running_counttorequest.requested_countfor fleets, but for EC2Fleet/SpotFleet/ASG withWeightedCapacity,requested_countis in capacity UNITS, not instance count. Each provider now emits its own fulfilment verdict —request_status_serviceconsumes only the typedProviderFulfilment.stateand never inspects AWS metadata keys._update_request_to_terminatingwritesIN_PROGRESSuntil all instances actually reachterminated. Combined with terminal-state guard inupdate_request_statusand a query-time short-circuit, prevents premature COMPLETED that drops machines from the response.terminate_instance_in_auto_scaling_group(ShouldDecrementDesiredCapacity=True)per instance —DesiredCapacitydecrements byWeightedCapacity, not by 1. EC2Fleet/SpotFleet releases subtractsum(WeightedCapacity)fromTotalTargetCapacityviamodify_fleet/modify_spot_fleet_request. Symmetric with weighted scale-up.GetRequestHandlercache-only-when-terminalin_progresssnapshots, so every subsequent poll for the same request was answered from stale cache and never reached the read-through sync. Cache now only stores entries whenrequest.status.is_terminal()— non-terminal polls always hit the sync. Was masking ~50 live-test polling failures.check_hosts_statusasync offloadcheck_hosts_status(synchronous boto3 calls) is now dispatched viaasyncio.to_threadfrom the strategy, preventing the event loop from blocking during provider-status polls under load.ListReturnRequestsHandlerread-through syncGetRequestHandler/ListActiveRequestsHandler. Without it, callers pollinglist_return_requestssaw IN_PROGRESS forever. CLI has no background sync, so every poll IS the sync.GetRequestHandlerpreviously returned an empty machine list. Now returns the persisted machines.OpenResourceBrokerMCPServer(app=None)never initialised the DI container; every MCP request failed dispatch with "No strategy found for provider". Fixed by bootstrappingApplicationin bothhandle_mcp_serveand the live test fixture.template_idKeyErrortest_case["overrides"]["scheduler"]to use the right key — every scheduler has a single wire format and tests must match it precisely.list_return_requestsand expected per-requeststatus, but the HF wire format flattens to{machine, gracePeriod}per spec. Both tests now pollget_request_status(return_id)— the correct cross-scheduler API for "is this request complete?".CI / infrastructure / cleanup
lxmlbumped to>=6.1.0(CVE-2026-41066).cryptographybumped to>=46.0.5(CVE-2026-26007).starlettebumped to>=0.49.1(GHSA-82w8-qh3p-5jfq).Makefile:test-providers-aws-livenow uses--extra apiso the venv hasuvicornfor the REST server subprocess.Makefile:PYTEST_WORKERScapped at half-CPU (was unbounded; OOM'd dev laptops during live runs)..gitignore: ignore live test artifact directorytests/providers/aws/live/run_templates/; drop obsoletetests/onaws/rule.reviewdog/action-suggesteronpull_request_targetso fork PRs get ruff suggestions without write tokens.tests/onaws/→tests/providers/aws/live/,tests/onmoto/→tests/providers/aws/moto/.profile_namefromORB_CONFIG_DIR/config.json+AWS_PROFILEenv-var fallback so pytest-env's injected fakeAWS_ACCESS_KEY_ID=testingcannot mask real credentials.modify_fleet(TotalTargetCapacity=0)beforedelete_fleetssomaintain/request/instantfleet types delete cleanly.maxNumberdefault to100.Provider PRs this unblocks
providers/oci/+ registration.field_mappings.py,hostfactory_strategy.py, andprovider_config_handler.pyare already removed here.Type of Change
Related Issues
N/A
How Has This Been Tested?
Verification (this branch HEAD):
uv run pyright src/: 0 errorsuv run ruff format --check ./uv run ruff check --select W,F,I --ignore E501: cleanuv run pytest --no-cov -q tests/unit tests/providers/aws/unit tests/providers/aws/moto: 5832 unit + 410 integration pass; targeted moto suite green (1 pre-existing failure intest_request_status_capacity::test_return_request_completed_when_all_terminated— wrong expectation in pre-existing test, scheduled for follow-up; 4 other pre-existing failures unrelated to this PR's scope and pre-date this branch onfinos/main).IN_PROGRESSwhile instances areshutting-down; transitions toCOMPLETEDonly when all reachterminated.tests/providers/aws/live/) — NOT run in CI; run separately withmake test-providers-aws-live.Test Configuration
Checklist
Additional Notes
git log --oneline finos/main..HEAD --reverse. Will rebase + group commits before merge if requested.make test-no-live,make test-providers-aws[-unit|-moto|-live],make test-architecture.CLISpecRegistry,TemplateExtensionRegistry,AuthRegistry,FieldMappingRegistry,DefaultsLoaderRegistry,ProviderRegistry,TemplateAdapterPort,TemplateExampleGeneratorPort, plus the newProviderPort.check_hosts_status → CheckHostsStatusResultcontract.Performance Impact
asyncio.to_threadfor blocking persistence andasyncio.timeoutfor operation dispatch are correctness fixes, not performance changes. Auth registry lookups and provider registration are dict operations with negligible cost.ListReturnRequestsHandlerread-through sync now triggers a provider describe per poll, mirroring the existing pattern inListActiveRequestsHandler— same cost shape.Security Considerations
Four auth security issues fixed (see security fixes table above): broken Cognito JWK decoding, IAM
assume_permissionsprivilege bypass, key-length error inconsistency in EnhancedBearer, and missing algorithm allowlist. Plus CVE bumps forcryptography,Starlette, andlxml.Dependencies
No new runtime dependencies.
cryptographyis already a transitive dependency viaPyJWT; this PR uses it directly in the Cognito strategy for JWK-to-RSA-public-key conversion. CVE-driven version bumps tocryptography,Starlette,lxml.Migration Guide
For ORB operators: No action required. Existing AWS-only deployments continue to work unchanged.
For provider authors (in-flight PRs):
mainafter this lands._REGISTERED_PROVIDERSinproviders/registration.py.providers/<name>/registration.py. Seedocs/root/developer_guide/adding_a_provider.md.OperationOutcomevariants from your strategy AND havecheck_hosts_statusreturnCheckHostsStatusResult(instances, fulfilment)with provider-computed fulfilment.Test runners:
--run-awscontinues to work (aliased to--live); prefer--livegoing forward. Live AWS tests run viamake test-providers-aws-live(note: uses--extra apisouvicornis installed for the REST server subprocess).Reviewers
@finos/open-resource-broker-maintainers