contractForCanonicalType($canonicalType); $permissions = $contract['permission_model']; expect($permissions['status'])->toBe('runtime_validation_pending') ->and($permissions['known_permission_names'])->toBe(['Exchange.ManageAsApp']) ->and($permissions['least_privilege_runtime_validated'])->toBeFalse() ->and($permissions['exchange_rbac_runtime_validated'])->toBeFalse() ->and($permissions['admin_consent_required'])->toBeTrue() ->and($permissions['permission_failure_modes'])->toContain('permission_denied') ->and($permissions['permission_failure_modes'])->toContain('command_unavailable') ->and($permissions['permission_failure_modes'])->toContain('adapter_unavailable'); })->with(['transportRule', 'remoteDomain', 'inboundConnector']); it('Spec430 response-shape metadata distinguishes empty denied unavailable malformed and unexpected shapes', function (string $canonicalType): void { $shape = (new ExchangePowerShellCommandContracts)->contractForCanonicalType($canonicalType)['response_shape']; expect($shape['raw_payload_shape'])->toBe('exchange_powershell_structured_collection') ->and($shape['collection_item_path'])->toBe('items') ->and($shape['empty_collection_meaning'])->toBe('valid_empty_collection') ->and($shape['permission_denied_response_meaning'])->toBe('permission_denied') ->and($shape['command_unavailable_response_meaning'])->toBe('command_unavailable') ->and($shape['adapter_unavailable_response_meaning'])->toBe('adapter_unavailable') ->and($shape['malformed_response_meaning'])->toBe('malformed_response') ->and($shape['unexpected_object_shape_meaning'])->toBe('unexpected_object_shape') ->and($shape['response_shape_safety'])->toBe('fail_closed_until_empty_denied_unavailable_malformed_and_unexpected_shapes_are_distinct'); })->with(['transportRule', 'remoteDomain', 'inboundConnector']); it('Spec430 display-name-only payloads do not produce stable identity for included types', function (string $canonicalType): void { $result = app(CanonicalIdentityResolver::class)->resolve( spec430MetadataResourceType($canonicalType), ['DisplayName' => 'Display-only object', 'Name' => 'Display-only object'], ['source_contract_key' => 'exchange_powershell.'.$canonicalType, 'source_version' => ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION], ); expect($result->identityState)->toBe(IdentityState::MissingExternalId) ->and($result->sourceResourceId)->toStartWith('missing:') ->and($result->canonicalResourceKey)->not->toContain('Display-only object'); })->with(['transportRule', 'remoteDomain', 'inboundConnector']); it('Spec430 redaction metadata forbids secrets raw shell output content and protected configuration exposure', function (string $canonicalType): void { $rules = (new ExchangePowerShellCommandContracts)->contractForCanonicalType($canonicalType)['redaction_rules']; $json = json_encode($rules, JSON_THROW_ON_ERROR); expect($rules['raw_payload_default_visible'])->toBeFalse() ->and($rules['permission_context_default_visible'])->toBeFalse() ->and($rules['forbidden_default_output'])->toContain('tokens') ->and($rules['forbidden_default_output'])->toContain('secrets') ->and($rules['forbidden_default_output'])->toContain('authorization_header') ->and($rules['forbidden_default_output'])->toContain('cookies') ->and($rules['forbidden_default_output'])->toContain('certificate_private_material') ->and($rules['forbidden_default_output'])->toContain('passwords') ->and($rules['forbidden_default_output'])->toContain('raw_transcripts') ->and($rules['forbidden_default_output'])->toContain('raw_shell_stdout') ->and($rules['forbidden_default_output'])->toContain('raw_shell_stderr') ->and($rules['forbidden_default_output'])->toContain('mail_body_content') ->and($rules['forbidden_default_output'])->toContain('mailbox_content') ->and($rules['forbidden_default_output'])->toContain('file_content') ->and($rules['forbidden_default_output'])->toContain('teams_transcript_content') ->and($json)->not->toContain('client-secret-value') ->and($json)->not->toContain('authorization-token-value'); })->with(['transportRule', 'remoteDomain', 'inboundConnector']); it('Spec430 future execution scope metadata preserves workspace managed-environment and provider-connection handoff', function (string $canonicalType): void { $scope = (new ExchangePowerShellCommandContracts)->contractForCanonicalType($canonicalType)['future_execution_scope']; expect($scope)->toMatchArray([ 'requires_workspace_id' => true, 'requires_managed_environment_id' => true, 'requires_provider_connection_id' => true, 'provider_native_scope_identifiers_are_metadata_only' => true, ]); })->with(['transportRule', 'remoteDomain', 'inboundConnector']); it('Spec430 claim guard allows only the exact internal adapter-contract statement', function (): void { $guard = app(ClaimGuard::class); expect($guard->evaluateStatement(ExchangePowerShellCommandContracts::ALLOWED_INTERNAL_CLAIM, internalOperatorOnly: true)) ->toBe(ClaimState::InternalOnly) ->and($guard->evaluateStatement(ExchangePowerShellCommandContracts::ALLOWED_INTERNAL_CLAIM, internalOperatorOnly: false)) ->toBe(ClaimState::ClaimBlocked) ->and($guard->evaluateStatement('Exchange PowerShell adapter contracts are customer ready', internalOperatorOnly: true)) ->toBe(ClaimState::ClaimBlocked) ->and($guard->evaluateStatement('Exchange PowerShell coverage is certified', internalOperatorOnly: true)) ->toBe(ClaimState::ClaimBlocked); }); function spec430MetadataResourceType(string $canonicalType): TenantConfigurationResourceType { $definition = collect(ResourceTypeRegistry::defaultDefinitions()) ->firstWhere('canonical_type', $canonicalType); expect($definition)->not->toBeNull("Missing default resource type definition for {$canonicalType}."); return new TenantConfigurationResourceType($definition); }