diff --git a/.changelog-pending/2026-07-21T17-10-16-341b7f0f1ea67e05b14ab5014622e1f93182cdff.md b/.changelog-pending/2026-07-21T17-10-16-341b7f0f1ea67e05b14ab5014622e1f93182cdff.md new file mode 100644 index 00000000..e05e6746 --- /dev/null +++ b/.changelog-pending/2026-07-21T17-10-16-341b7f0f1ea67e05b14ab5014622e1f93182cdff.md @@ -0,0 +1,66 @@ +* [#695](https://github.com/workos/workos-python/pull/695) feat(generated)!: regenerate from spec (9 changes) + + **Features** + * **agents**: + * Added model `ClaimViewResponse` + * Added model `ClaimViewResponseOrganization` + * Added model `AgentAdminLinkClaimAttemptToExternalUserRequest` + * Added model `AgentAdminLinkClaimAttemptToExternalUserRequestUser` + * Added enum `ClaimViewResponseStatus` + * Added endpoint `PATCH /agents/claims/attempts` + * Added model `AgentRegistration` + * Added model `AgentCredentialValidation` + * Added model `AgentRegistrationAgentIdentity` + * Added model `AgentRegistrationClaim` + * Added model `AgentAdminValidateCredentialRequest` + * Added model `AgentRegistrationClaimClaimCompletion` + * Added enum `AgentRegistrationStatus` + * Added enum `AgentRegistrationKind` + * Added enum `AgentAdminValidateCredentialRequestType` + * Added service `Agents` + * **[api_keys](https://workos.com/docs/reference/authkit/api-keys)**: + * Added `agent_registration_id` to `ApiKeyValidationResponse` + * **[connect](https://workos.com/docs/reference/workos-connect/standalone)**: + * Added enum `ApplicationsRegistrationTypes` + * Added parameter `Applications.list.registration_types` + * **[directory_sync](https://workos.com/docs/reference/directory-sync)**: + * Added parameter `DirectoryUsers.list.idp_id` + * Added parameter `DirectoryUsers.list.email` + * **[organizations](https://workos.com/docs/reference/organization)**: + * Added model `OrganizationAuthorizedConnectApplicationList` + * Added model `OrganizationAuthorizedConnectApplicationListData` + * Added model `OrganizationAuthorizedConnectApplicationListListMetadata` + * Added service `OrganizationsAuthorizedApplications` + * **[pipes](https://workos.com/docs/reference/pipes)**: + * Added model `DataIntegrationInstallation` + * Added `auth_methods` to `CreateDataIntegration` + * Added `api_key` to `CreateDataIntegration` + * Added `api_key` to `UpdateDataIntegration` + * Added `auth_methods` to `DataIntegration` + * Added `installation` to `DataIntegration` + * Added enum `CreateDataIntegrationAuthMethods` + * Added enum `DataIntegrationAuthMethods` + * Added model `DataIntegrationCredentialsResponse` + * Added model `DataIntegrationCredentialsResponseCredential` + * Added model `DataIntegrationsUpsertApiKeyRequest` + * Added model `DataIntegrationsVendCredentialsRequest` + * Added enum `DataIntegrationCredentialsResponseError` + * Added endpoint `PUT /data-integrations/{slug}/api-key` + * Added endpoint `POST /data-integrations/{slug}/credentials` + * **[sso](https://workos.com/docs/reference/sso)**: + * Added parameter `SSO.authorize.prompt` + * **[user_management](https://workos.com/docs/reference/authkit/user)**: + * Added `ssha256` to `CreateUserPasswordHashType` + * Added `ssha256` to `UpdateUserPasswordHashType` + * Added endpoint `GET /user_management/radar_challenges/{id}` + * **[webhooks](https://workos.com/docs/reference/webhooks)**: + * Added `agent.registration.revoked` to `CreateWebhookEndpointEvents` + * Added `agent.registration.revoked` to `UpdateWebhookEndpointEvents` + * Added `agent.registration.deleted` to `CreateWebhookEndpointEvents` + * Added `agent.registration.deleted` to `UpdateWebhookEndpointEvents` + * Added `radar.challenge_created` to `CreateWebhookEndpointEvents` + * Added `radar.challenge_created` to `UpdateWebhookEndpointEvents` + * Added `agent.registration.expired` to `CreateWebhookEndpointEvents` + * Added `agent.registration.expired` to `UpdateWebhookEndpointEvents` + * **[widgets](https://workos.com/docs/reference/widgets)**: + * Made `WidgetSessionToken.organization_id` optional diff --git a/.last-synced-sha b/.last-synced-sha index d068573d..5d1fd6d4 100644 --- a/.last-synced-sha +++ b/.last-synced-sha @@ -1 +1 @@ -56a015eaa3c5fb42a7dd77526c43953a971f4907 +f40851a620a1ba0badec95e80faac475382c8dd0 diff --git a/.oagen-manifest.json b/.oagen-manifest.json index add53e43..ee67a048 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -11,6 +11,19 @@ "src/workos/admin_portal/models/intent_options.py", "src/workos/admin_portal/models/portal_link_response.py", "src/workos/admin_portal/models/sso_intent_options.py", + "src/workos/agents/__init__.py", + "src/workos/agents/_resource.py", + "src/workos/agents/models/__init__.py", + "src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request.py", + "src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request_user.py", + "src/workos/agents/models/agent_admin_validate_credential_request.py", + "src/workos/agents/models/agent_credential_validation.py", + "src/workos/agents/models/agent_registration.py", + "src/workos/agents/models/agent_registration_agent_identity.py", + "src/workos/agents/models/agent_registration_claim.py", + "src/workos/agents/models/agent_registration_claim_claim_completion.py", + "src/workos/agents/models/claim_view_response.py", + "src/workos/agents/models/claim_view_response_organization.py", "src/workos/api_keys/__init__.py", "src/workos/api_keys/_resource.py", "src/workos/api_keys/models/__init__.py", @@ -80,12 +93,38 @@ "src/workos/client_api/models/client_api_token_response.py", "src/workos/common/__init__.py", "src/workos/common/models/__init__.py", + "src/workos/common/models/access_token_agent_registration_credential_issued_data_detail.py", "src/workos/common/models/action_authentication_denied.py", "src/workos/common/models/action_authentication_denied_data.py", "src/workos/common/models/action_user_registration_denied.py", "src/workos/common/models/action_user_registration_denied_data.py", "src/workos/common/models/actor.py", "src/workos/common/models/add_role_permission.py", + "src/workos/common/models/agent_admin_validate_credential_request_type.py", + "src/workos/common/models/agent_registration_claim_attempt_created.py", + "src/workos/common/models/agent_registration_claim_attempt_created_data.py", + "src/workos/common/models/agent_registration_claim_completed.py", + "src/workos/common/models/agent_registration_claim_completed_data.py", + "src/workos/common/models/agent_registration_claim_completed_data_claimed_by.py", + "src/workos/common/models/agent_registration_created.py", + "src/workos/common/models/agent_registration_created_data.py", + "src/workos/common/models/agent_registration_created_data_agent_identity.py", + "src/workos/common/models/agent_registration_created_data_kind.py", + "src/workos/common/models/agent_registration_created_data_method.py", + "src/workos/common/models/agent_registration_created_data_status.py", + "src/workos/common/models/agent_registration_credential_issued.py", + "src/workos/common/models/agent_registration_credential_issued_data.py", + "src/workos/common/models/agent_registration_credential_issued_data_detail.py", + "src/workos/common/models/agent_registration_deleted.py", + "src/workos/common/models/agent_registration_deleted_data.py", + "src/workos/common/models/agent_registration_expired.py", + "src/workos/common/models/agent_registration_expired_data.py", + "src/workos/common/models/agent_registration_kind.py", + "src/workos/common/models/agent_registration_organization_switched.py", + "src/workos/common/models/agent_registration_organization_switched_data.py", + "src/workos/common/models/agent_registration_revoked.py", + "src/workos/common/models/agent_registration_revoked_data.py", + "src/workos/common/models/agent_registration_status.py", "src/workos/common/models/api_key_created.py", "src/workos/common/models/api_key_created_data.py", "src/workos/common/models/api_key_created_data_owner.py", @@ -146,6 +185,8 @@ "src/workos/common/models/authentication_radar_risk_detected.py", "src/workos/common/models/authentication_radar_risk_detected_data.py", "src/workos/common/models/authentication_radar_risk_detected_data_action.py", + "src/workos/common/models/authentication_reauthentication_succeeded.py", + "src/workos/common/models/authentication_reauthentication_succeeded_data.py", "src/workos/common/models/authentication_sso_failed.py", "src/workos/common/models/authentication_sso_failed_data.py", "src/workos/common/models/authentication_sso_failed_data_error.py", @@ -161,12 +202,14 @@ "src/workos/common/models/authentication_sso_timed_out_data_error.py", "src/workos/common/models/authentication_sso_timed_out_data_sso.py", "src/workos/common/models/authorization_permission.py", + "src/workos/common/models/claim_view_response_status.py", "src/workos/common/models/connect_application.py", "src/workos/common/models/connect_application_m2m.py", "src/workos/common/models/connect_application_oauth.py", "src/workos/common/models/connect_application_oauth_redirect_uris.py", "src/workos/common/models/connected_account.py", "src/workos/common/models/connected_account_auth_method.py", + "src/workos/common/models/connected_account_input_state.py", "src/workos/common/models/connected_account_state.py", "src/workos/common/models/connection_activated.py", "src/workos/common/models/connection_activated_data.py", @@ -197,13 +240,16 @@ "src/workos/common/models/connection_state.py", "src/workos/common/models/connection_status.py", "src/workos/common/models/connection_type.py", + "src/workos/common/models/create_data_integration_auth_methods.py", "src/workos/common/models/create_user_invite_options_locale.py", "src/workos/common/models/create_user_password_hash_type.py", "src/workos/common/models/create_webhook_endpoint_events.py", "src/workos/common/models/custom_provider_definition_authenticate_via.py", "src/workos/common/models/data_integration_access_token_response_error.py", + "src/workos/common/models/data_integration_auth_methods.py", "src/workos/common/models/data_integration_credential_type.py", "src/workos/common/models/data_integration_credentials_credentials_type.py", + "src/workos/common/models/data_integration_credentials_input_type.py", "src/workos/common/models/data_integration_credentials_response_error.py", "src/workos/common/models/data_integration_credentials_type.py", "src/workos/common/models/data_integration_custom_provider_authenticate_via.py", @@ -392,9 +438,13 @@ "src/workos/common/models/pipe_connected_account.py", "src/workos/common/models/pipe_connected_account_state.py", "src/workos/common/models/pipes_connected_account_connected.py", + "src/workos/common/models/pipes_connected_account_connection_failed.py", + "src/workos/common/models/pipes_connected_account_connection_failed_data.py", "src/workos/common/models/pipes_connected_account_disconnected.py", "src/workos/common/models/pipes_connected_account_reauthorization_needed.py", "src/workos/common/models/profile_connection_type.py", + "src/workos/common/models/radar_challenge_created.py", + "src/workos/common/models/radar_challenge_created_data.py", "src/workos/common/models/radar_standalone_assess_request_action.py", "src/workos/common/models/radar_standalone_assess_request_auth_method.py", "src/workos/common/models/radar_standalone_response_blocklist_type.py", @@ -466,6 +516,9 @@ "src/workos/common/models/vault_kek_created.py", "src/workos/common/models/vault_kek_created_data.py", "src/workos/common/models/vault_kek_created_data_actor_source.py", + "src/workos/common/models/vault_kek_deleted.py", + "src/workos/common/models/vault_kek_deleted_data.py", + "src/workos/common/models/vault_kek_deleted_data_actor_source.py", "src/workos/common/models/vault_metadata_read.py", "src/workos/common/models/vault_metadata_read_data.py", "src/workos/common/models/vault_metadata_read_data_actor_source.py", @@ -483,6 +536,7 @@ "src/workos/connect/_resource.py", "src/workos/connect/models/__init__.py", "src/workos/connect/models/application_credentials_list_item.py", + "src/workos/connect/models/applications_registration_types.py", "src/workos/connect/models/create_application_secret.py", "src/workos/connect/models/create_m2m_application.py", "src/workos/connect/models/create_oauth_application.py", @@ -545,6 +599,7 @@ "src/workos/organizations/models/audit_log_configuration_log_stream.py", "src/workos/organizations/models/audit_logs_retention.py", "src/workos/organizations/models/organization.py", + "src/workos/organizations/models/organization_authorized_connect_application_list_data.py", "src/workos/organizations/models/organization_domain_data.py", "src/workos/organizations/models/organization_input.py", "src/workos/organizations/models/update_audit_logs_retention.py", @@ -552,8 +607,10 @@ "src/workos/pipes/__init__.py", "src/workos/pipes/_resource.py", "src/workos/pipes/models/__init__.py", + "src/workos/pipes/models/api_key_installation.py", "src/workos/pipes/models/connected_account.py", "src/workos/pipes/models/connected_account_dto.py", + "src/workos/pipes/models/connected_account_input.py", "src/workos/pipes/models/create_data_integration.py", "src/workos/pipes/models/custom_provider_definition.py", "src/workos/pipes/models/data_integration.py", @@ -562,9 +619,11 @@ "src/workos/pipes/models/data_integration_authorize_url_response.py", "src/workos/pipes/models/data_integration_credential.py", "src/workos/pipes/models/data_integration_credentials_dto.py", + "src/workos/pipes/models/data_integration_credentials_input.py", "src/workos/pipes/models/data_integration_credentials_response.py", "src/workos/pipes/models/data_integration_credentials_response_credential.py", "src/workos/pipes/models/data_integration_custom_provider.py", + "src/workos/pipes/models/data_integration_installation.py", "src/workos/pipes/models/data_integrations_get_data_integration_authorize_url_request.py", "src/workos/pipes/models/data_integrations_get_user_token_request.py", "src/workos/pipes/models/data_integrations_list_response.py", @@ -609,6 +668,7 @@ "src/workos/sso/models/token_query.py", "src/workos/types/__init__.py", "src/workos/types/admin_portal/__init__.py", + "src/workos/types/agents/__init__.py", "src/workos/types/api_keys/__init__.py", "src/workos/types/audit_logs/__init__.py", "src/workos/types/authorization/__init__.py", @@ -665,6 +725,7 @@ "src/workos/user_management/models/organization_selection_session_authenticate_request.py", "src/workos/user_management/models/password_reset.py", "src/workos/user_management/models/password_session_authenticate_request.py", + "src/workos/user_management/models/radar_challenge.py", "src/workos/user_management/models/radar_email_challenge_code_session_authenticate_request.py", "src/workos/user_management/models/radar_sms_challenge_code_session_authenticate_request.py", "src/workos/user_management/models/redirect_uri.py", @@ -719,16 +780,45 @@ "src/workos/widgets/models/__init__.py", "src/workos/widgets/models/widget_session_token.py", "src/workos/widgets/models/widget_session_token_response.py", + "tests/fixtures/access_token_agent_registration_credential_issued_data_detail.json", "tests/fixtures/action_authentication_denied.json", "tests/fixtures/action_authentication_denied_data.json", "tests/fixtures/action_user_registration_denied.json", "tests/fixtures/action_user_registration_denied_data.json", "tests/fixtures/actor.json", "tests/fixtures/add_role_permission.json", + "tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request.json", + "tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request_user.json", + "tests/fixtures/agent_admin_validate_credential_request.json", + "tests/fixtures/agent_credential_validation.json", + "tests/fixtures/agent_registration.json", + "tests/fixtures/agent_registration_agent_identity.json", + "tests/fixtures/agent_registration_claim.json", + "tests/fixtures/agent_registration_claim_attempt_created.json", + "tests/fixtures/agent_registration_claim_attempt_created_data.json", + "tests/fixtures/agent_registration_claim_claim_completion.json", + "tests/fixtures/agent_registration_claim_completed.json", + "tests/fixtures/agent_registration_claim_completed_data.json", + "tests/fixtures/agent_registration_claim_completed_data_claimed_by.json", + "tests/fixtures/agent_registration_created.json", + "tests/fixtures/agent_registration_created_data.json", + "tests/fixtures/agent_registration_created_data_agent_identity.json", + "tests/fixtures/agent_registration_credential_issued.json", + "tests/fixtures/agent_registration_credential_issued_data.json", + "tests/fixtures/agent_registration_credential_issued_data_detail.json", + "tests/fixtures/agent_registration_deleted.json", + "tests/fixtures/agent_registration_deleted_data.json", + "tests/fixtures/agent_registration_expired.json", + "tests/fixtures/agent_registration_expired_data.json", + "tests/fixtures/agent_registration_organization_switched.json", + "tests/fixtures/agent_registration_organization_switched_data.json", + "tests/fixtures/agent_registration_revoked.json", + "tests/fixtures/agent_registration_revoked_data.json", "tests/fixtures/api_key.json", "tests/fixtures/api_key_created.json", "tests/fixtures/api_key_created_data.json", "tests/fixtures/api_key_created_data_owner.json", + "tests/fixtures/api_key_installation.json", "tests/fixtures/api_key_owner.json", "tests/fixtures/api_key_revoked.json", "tests/fixtures/api_key_revoked_data.json", @@ -804,6 +894,8 @@ "tests/fixtures/authentication_password_succeeded_data.json", "tests/fixtures/authentication_radar_risk_detected.json", "tests/fixtures/authentication_radar_risk_detected_data.json", + "tests/fixtures/authentication_reauthentication_succeeded.json", + "tests/fixtures/authentication_reauthentication_succeeded_data.json", "tests/fixtures/authentication_sso_failed.json", "tests/fixtures/authentication_sso_failed_data.json", "tests/fixtures/authentication_sso_failed_data_error.json", @@ -825,6 +917,8 @@ "tests/fixtures/authorized_connect_application_list_data.json", "tests/fixtures/challenge_authentication_factor.json", "tests/fixtures/check_authorization.json", + "tests/fixtures/claim_view_response.json", + "tests/fixtures/claim_view_response_organization.json", "tests/fixtures/client_api_token.json", "tests/fixtures/client_api_token_response.json", "tests/fixtures/configure_data_integration_body.json", @@ -835,6 +929,7 @@ "tests/fixtures/connect_application_oauth_redirect_uris.json", "tests/fixtures/connected_account.json", "tests/fixtures/connected_account_dto.json", + "tests/fixtures/connected_account_input.json", "tests/fixtures/connection.json", "tests/fixtures/connection_activated.json", "tests/fixtures/connection_activated_data.json", @@ -890,9 +985,11 @@ "tests/fixtures/data_integration_credential.json", "tests/fixtures/data_integration_credentials.json", "tests/fixtures/data_integration_credentials_dto.json", + "tests/fixtures/data_integration_credentials_input.json", "tests/fixtures/data_integration_credentials_response.json", "tests/fixtures/data_integration_credentials_response_credential.json", "tests/fixtures/data_integration_custom_provider.json", + "tests/fixtures/data_integration_installation.json", "tests/fixtures/data_integrations_get_data_integration_authorize_url_request.json", "tests/fixtures/data_integrations_get_user_token_request.json", "tests/fixtures/data_integrations_list_response.json", @@ -1034,6 +1131,7 @@ "tests/fixtures/list_object_summary.json", "tests/fixtures/list_organization.json", "tests/fixtures/list_organization_api_key.json", + "tests/fixtures/list_organization_authorized_connect_application_list_data.json", "tests/fixtures/list_redirect_uri.json", "tests/fixtures/list_user.json", "tests/fixtures/list_user_api_key.json", @@ -1059,6 +1157,7 @@ "tests/fixtures/organization_api_key_owner.json", "tests/fixtures/organization_api_key_with_value.json", "tests/fixtures/organization_api_key_with_value_owner.json", + "tests/fixtures/organization_authorized_connect_application_list_data.json", "tests/fixtures/organization_created.json", "tests/fixtures/organization_created_data.json", "tests/fixtures/organization_created_data_domain.json", @@ -1112,10 +1211,15 @@ "tests/fixtures/permission_updated_data.json", "tests/fixtures/pipe_connected_account.json", "tests/fixtures/pipes_connected_account_connected.json", + "tests/fixtures/pipes_connected_account_connection_failed.json", + "tests/fixtures/pipes_connected_account_connection_failed_data.json", "tests/fixtures/pipes_connected_account_disconnected.json", "tests/fixtures/pipes_connected_account_reauthorization_needed.json", "tests/fixtures/portal_link_response.json", "tests/fixtures/profile.json", + "tests/fixtures/radar_challenge.json", + "tests/fixtures/radar_challenge_created.json", + "tests/fixtures/radar_challenge_created_data.json", "tests/fixtures/radar_email_challenge_code_session_authenticate_request.json", "tests/fixtures/radar_list_entry_already_present_response.json", "tests/fixtures/radar_sms_challenge_code_session_authenticate_request.json", @@ -1222,6 +1326,8 @@ "tests/fixtures/vault_dek_read_data.json", "tests/fixtures/vault_kek_created.json", "tests/fixtures/vault_kek_created_data.json", + "tests/fixtures/vault_kek_deleted.json", + "tests/fixtures/vault_kek_deleted_data.json", "tests/fixtures/vault_metadata_read.json", "tests/fixtures/vault_metadata_read_data.json", "tests/fixtures/vault_names_listed.json", @@ -1239,38 +1345,52 @@ "tests/fixtures/widget_session_token_response.json", "tests/test_admin_portal.py", "tests/test_admin_portal_models_round_trip.py", + "tests/test_agents.py", + "tests/test_agents_models_round_trip.py", "tests/test_api_keys.py", + "tests/test_api_keys_models_round_trip.py", "tests/test_audit_logs.py", "tests/test_audit_logs_models_round_trip.py", "tests/test_authorization.py", "tests/test_authorization_models_round_trip.py", "tests/test_client_api.py", + "tests/test_client_api_models_round_trip.py", "tests/test_common_models_round_trip.py", "tests/test_connect.py", "tests/test_connect_models_round_trip.py", "tests/test_directory_sync.py", + "tests/test_directory_sync_models_round_trip.py", "tests/test_events.py", + "tests/test_events_models_round_trip.py", "tests/test_feature_flags.py", + "tests/test_feature_flags_models_round_trip.py", "tests/test_groups.py", "tests/test_groups_models_round_trip.py", "tests/test_models_round_trip.py", "tests/test_multi_factor_auth.py", + "tests/test_multi_factor_auth_models_round_trip.py", "tests/test_organization_domains.py", + "tests/test_organization_domains_models_round_trip.py", "tests/test_organization_membership.py", + "tests/test_organization_membership_models_round_trip.py", "tests/test_organizations.py", "tests/test_organizations_models_round_trip.py", "tests/test_pipes.py", "tests/test_pipes_models_round_trip.py", "tests/test_pipes_provider.py", + "tests/test_pipes_provider_models_round_trip.py", "tests/test_radar.py", "tests/test_radar_models_round_trip.py", "tests/test_sso.py", + "tests/test_sso_models_round_trip.py", "tests/test_user_management.py", "tests/test_user_management_models_round_trip.py", "tests/test_vault.py", + "tests/test_vault_models_round_trip.py", "tests/test_webhooks.py", "tests/test_webhooks_models_round_trip.py", - "tests/test_widgets.py" + "tests/test_widgets.py", + "tests/test_widgets_models_round_trip.py" ], "operations": { "POST /auth/challenges/{id}/verify": { @@ -2100,6 +2220,22 @@ "DELETE /user_management/redirect_uris/{id}": { "sdkMethod": "delete_redirect_uris", "service": "user_management" + }, + "PATCH /agents/claims/attempts": { + "sdkMethod": "update_attempts", + "service": "agents" + }, + "POST /agents/credentials/validate": { + "sdkMethod": "create_validate", + "service": "agents" + }, + "GET /agents/registrations/{id}": { + "sdkMethod": "get_registration", + "service": "agents" + }, + "GET /organizations/{organization_id}/authorized_applications": { + "sdkMethod": "list_authorized_applications", + "service": "organizations" } } } diff --git a/src/workos/_client.py b/src/workos/_client.py index 8322fa00..41d319cc 100644 --- a/src/workos/_client.py +++ b/src/workos/_client.py @@ -8,6 +8,7 @@ WorkOSClient as _SyncBase, AsyncWorkOSClient as _AsyncBase, ) +from .agents._resource import Agents, AsyncAgents from .multi_factor_auth._resource import MultiFactorAuth, AsyncMultiFactorAuth from .connect._resource import Connect, AsyncConnect from .authorization._resource import Authorization, AsyncAuthorization @@ -44,6 +45,11 @@ class WorkOSClient(_SyncBase): """Synchronous WorkOS API client with service accessors.""" + @functools.cached_property + def agents(self) -> Agents: + """Agents API resources.""" + return Agents(self) + @functools.cached_property def multi_factor_auth(self) -> MultiFactorAuth: """Multi Factor Auth API resources.""" @@ -182,6 +188,11 @@ def pkce(self) -> PKCE: class AsyncWorkOSClient(_AsyncBase): """Asynchronous WorkOS API client with service accessors.""" + @functools.cached_property + def agents(self) -> AsyncAgents: + """Agents API resources.""" + return AsyncAgents(self) + @functools.cached_property def multi_factor_auth(self) -> AsyncMultiFactorAuth: """Multi Factor Auth API resources.""" diff --git a/src/workos/agents/__init__.py b/src/workos/agents/__init__.py new file mode 100644 index 00000000..3b1eb581 --- /dev/null +++ b/src/workos/agents/__init__.py @@ -0,0 +1,4 @@ +# This file is auto-generated by oagen. Do not edit. + +from ._resource import Agents as Agents, AsyncAgents as AsyncAgents +from .models import * diff --git a/src/workos/agents/_resource.py b/src/workos/agents/_resource.py new file mode 100644 index 00000000..39a61850 --- /dev/null +++ b/src/workos/agents/_resource.py @@ -0,0 +1,279 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Literal, Optional, Union + +if TYPE_CHECKING: + from .._client import AsyncWorkOSClient, WorkOSClient + +from .._types import RequestOptions, enum_value +from .models import ( + AgentAdminLinkClaimAttemptToExternalUserRequestUser, + AgentCredentialValidation, + AgentRegistration, + ClaimViewResponse, +) +from workos.common.models.agent_admin_validate_credential_request_type import ( + AgentAdminValidateCredentialRequestType, +) + + +class Agents: + """Agents API resources.""" + + def __init__(self, client: "WorkOSClient") -> None: + self._client = client + + def update_attempts( + self, + *, + type: Literal["link_external_user"], + claim_attempt_token: str, + user: AgentAdminLinkClaimAttemptToExternalUserRequestUser, + organization_id: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ClaimViewResponse: + """Link a claim attempt to an external user + + Link an external user to a claim attempt and retrieve the code needed for the agent to complete the claim. The user is looked up by external ID; if no user exists, one is created. When the user belongs to multiple organizations, an explicit organization must be provided. + + Args: + type: The operation to perform on the claim attempt. Currently only `link_external_user` is supported. + claim_attempt_token: The token identifying the claim attempt. + user: The user to attach to the claim attempt, identified by email and external ID. + organization_id: The organization to place the agent in. Required when the user belongs to more than one organization. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ClaimViewResponse + + Raises: + BadRequestError: If the request is malformed (400). + AuthorizationError: If the request is forbidden (403). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "type": type, + "claim_attempt_token": claim_attempt_token, + "user": user.to_dict(), + "organization_id": organization_id, + }.items() + if v is not None + } + return self._client.request( + method="patch", + path=("agents", "claims", "attempts"), + body=body, + model=ClaimViewResponse, + request_options=request_options, + ) + + def create_validate( + self, + *, + type: Union[AgentAdminValidateCredentialRequestType, str], + credential: str, + audience: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> AgentCredentialValidation: + """Validate an agent credential + + Validate an agent credential — an API key or access token — against the environment of the API key used to authenticate the request. This is a read-only check: it never consumes or mutates the credential. + + Args: + type: The kind of credential being validated — an agent API key or an agent access token. + credential: The credential value to validate: the API key value for `api_key`, or the access token (JWT) for `access_token`. + audience: When provided, the access token's `aud` claim is verified against this value. Tokens issued for a different resource are rejected. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AgentCredentialValidation + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "type": enum_value(type), + "credential": credential, + "audience": audience, + }.items() + if v is not None + } + return self._client.request( + method="post", + path=("agents", "credentials", "validate"), + body=body, + model=AgentCredentialValidation, + request_options=request_options, + ) + + def get_registration( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> AgentRegistration: + """Get an agent registration + + Retrieve the details of an agent registration by ID. The registration is scoped to the environment of the API key used to authenticate the request. + + Args: + id: The unique ID of the agent registration. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AgentRegistration + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("agents", "registrations", str(id)), + model=AgentRegistration, + request_options=request_options, + ) + + +class AsyncAgents: + """Agents API resources (async).""" + + def __init__(self, client: "AsyncWorkOSClient") -> None: + self._client = client + + async def update_attempts( + self, + *, + type: Literal["link_external_user"], + claim_attempt_token: str, + user: AgentAdminLinkClaimAttemptToExternalUserRequestUser, + organization_id: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ClaimViewResponse: + """Link a claim attempt to an external user + + Link an external user to a claim attempt and retrieve the code needed for the agent to complete the claim. The user is looked up by external ID; if no user exists, one is created. When the user belongs to multiple organizations, an explicit organization must be provided. + + Args: + type: The operation to perform on the claim attempt. Currently only `link_external_user` is supported. + claim_attempt_token: The token identifying the claim attempt. + user: The user to attach to the claim attempt, identified by email and external ID. + organization_id: The organization to place the agent in. Required when the user belongs to more than one organization. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ClaimViewResponse + + Raises: + BadRequestError: If the request is malformed (400). + AuthorizationError: If the request is forbidden (403). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "type": type, + "claim_attempt_token": claim_attempt_token, + "user": user.to_dict(), + "organization_id": organization_id, + }.items() + if v is not None + } + return await self._client.request( + method="patch", + path=("agents", "claims", "attempts"), + body=body, + model=ClaimViewResponse, + request_options=request_options, + ) + + async def create_validate( + self, + *, + type: Union[AgentAdminValidateCredentialRequestType, str], + credential: str, + audience: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> AgentCredentialValidation: + """Validate an agent credential + + Validate an agent credential — an API key or access token — against the environment of the API key used to authenticate the request. This is a read-only check: it never consumes or mutates the credential. + + Args: + type: The kind of credential being validated — an agent API key or an agent access token. + credential: The credential value to validate: the API key value for `api_key`, or the access token (JWT) for `access_token`. + audience: When provided, the access token's `aud` claim is verified against this value. Tokens issued for a different resource are rejected. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AgentCredentialValidation + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "type": enum_value(type), + "credential": credential, + "audience": audience, + }.items() + if v is not None + } + return await self._client.request( + method="post", + path=("agents", "credentials", "validate"), + body=body, + model=AgentCredentialValidation, + request_options=request_options, + ) + + async def get_registration( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> AgentRegistration: + """Get an agent registration + + Retrieve the details of an agent registration by ID. The registration is scoped to the environment of the API key used to authenticate the request. + + Args: + id: The unique ID of the agent registration. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AgentRegistration + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("agents", "registrations", str(id)), + model=AgentRegistration, + request_options=request_options, + ) diff --git a/src/workos/agents/models/__init__.py b/src/workos/agents/models/__init__.py new file mode 100644 index 00000000..a176f403 --- /dev/null +++ b/src/workos/agents/models/__init__.py @@ -0,0 +1,26 @@ +# This file is auto-generated by oagen. Do not edit. + +from .agent_admin_link_claim_attempt_to_external_user_request import ( + AgentAdminLinkClaimAttemptToExternalUserRequest as AgentAdminLinkClaimAttemptToExternalUserRequest, +) +from .agent_admin_link_claim_attempt_to_external_user_request_user import ( + AgentAdminLinkClaimAttemptToExternalUserRequestUser as AgentAdminLinkClaimAttemptToExternalUserRequestUser, +) +from .agent_admin_validate_credential_request import ( + AgentAdminValidateCredentialRequest as AgentAdminValidateCredentialRequest, +) +from .agent_credential_validation import ( + AgentCredentialValidation as AgentCredentialValidation, +) +from .agent_registration import AgentRegistration as AgentRegistration +from .agent_registration_agent_identity import ( + AgentRegistrationAgentIdentity as AgentRegistrationAgentIdentity, +) +from .agent_registration_claim import AgentRegistrationClaim as AgentRegistrationClaim +from .agent_registration_claim_claim_completion import ( + AgentRegistrationClaimClaimCompletion as AgentRegistrationClaimClaimCompletion, +) +from .claim_view_response import ClaimViewResponse as ClaimViewResponse +from .claim_view_response_organization import ( + ClaimViewResponseOrganization as ClaimViewResponseOrganization, +) diff --git a/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request.py b/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request.py new file mode 100644 index 00000000..f5d7d7ae --- /dev/null +++ b/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request.py @@ -0,0 +1,55 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error + +from .agent_admin_link_claim_attempt_to_external_user_request_user import ( + AgentAdminLinkClaimAttemptToExternalUserRequestUser, +) + + +@dataclass(slots=True) +class AgentAdminLinkClaimAttemptToExternalUserRequest: + """Agent Admin Link Claim Attempt To External User Request model.""" + + type: Literal["link_external_user"] + """The operation to perform on the claim attempt. Currently only `link_external_user` is supported.""" + claim_attempt_token: str + """The token identifying the claim attempt.""" + user: "AgentAdminLinkClaimAttemptToExternalUserRequestUser" + """The user to attach to the claim attempt, identified by email and external ID.""" + organization_id: Optional[str] = None + """The organization to place the agent in. Required when the user belongs to more than one organization.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentAdminLinkClaimAttemptToExternalUserRequest": + """Deserialize from a dictionary.""" + try: + return cls( + type=data.get("type", "link_external_user"), + claim_attempt_token=data["claim_attempt_token"], + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + cast(Dict[str, Any], data["user"]) + ), + organization_id=data.get("organization_id"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error( + "AgentAdminLinkClaimAttemptToExternalUserRequest", e + ) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type + result["claim_attempt_token"] = self.claim_attempt_token + result["user"] = self.user.to_dict() + if self.organization_id is not None: + result["organization_id"] = self.organization_id + return result diff --git a/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request_user.py b/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request_user.py new file mode 100644 index 00000000..04aecc57 --- /dev/null +++ b/src/workos/agents/models/agent_admin_link_claim_attempt_to_external_user_request_user.py @@ -0,0 +1,39 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentAdminLinkClaimAttemptToExternalUserRequestUser: + """The user to attach to the claim attempt, identified by email and external ID.""" + + email: str + """The email address of the user.""" + external_id: str + """The external ID of the user.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentAdminLinkClaimAttemptToExternalUserRequestUser": + """Deserialize from a dictionary.""" + try: + return cls( + email=data["email"], + external_id=data["external_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error( + "AgentAdminLinkClaimAttemptToExternalUserRequestUser", e + ) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["email"] = self.email + result["external_id"] = self.external_id + return result diff --git a/src/workos/agents/models/agent_admin_validate_credential_request.py b/src/workos/agents/models/agent_admin_validate_credential_request.py new file mode 100644 index 00000000..99ddde64 --- /dev/null +++ b/src/workos/agents/models/agent_admin_validate_credential_request.py @@ -0,0 +1,44 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos.common.models.agent_admin_validate_credential_request_type import ( + AgentAdminValidateCredentialRequestType, +) + + +@dataclass(slots=True) +class AgentAdminValidateCredentialRequest: + """Agent Admin Validate Credential Request model.""" + + type: "AgentAdminValidateCredentialRequestType" + """The kind of credential being validated — an agent API key or an agent access token.""" + credential: str + """The credential value to validate: the API key value for `api_key`, or the access token (JWT) for `access_token`.""" + audience: Optional[str] = None + """When provided, the access token's `aud` claim is verified against this value. Tokens issued for a different resource are rejected.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentAdminValidateCredentialRequest": + """Deserialize from a dictionary.""" + try: + return cls( + type=AgentAdminValidateCredentialRequestType(data["type"]), + credential=data["credential"], + audience=data.get("audience"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentAdminValidateCredentialRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type.value if isinstance(self.type, Enum) else self.type + result["credential"] = self.credential + if self.audience is not None: + result["audience"] = self.audience + return result diff --git a/src/workos/agents/models/agent_credential_validation.py b/src/workos/agents/models/agent_credential_validation.py new file mode 100644 index 00000000..224debbe --- /dev/null +++ b/src/workos/agents/models/agent_credential_validation.py @@ -0,0 +1,49 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class AgentCredentialValidation: + """Agent Credential Validation model.""" + + valid: bool + """Whether the presented credential is valid.""" + registration_id: Optional[str] + """Identifier of the agent registration the credential belongs to, or `null` when the credential is invalid.""" + expires_at: Optional[datetime] + """The timestamp when the credential expires, or `null` when the credential is invalid.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentCredentialValidation": + """Deserialize from a dictionary.""" + try: + return cls( + valid=data["valid"], + registration_id=data["registration_id"], + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentCredentialValidation", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["valid"] = self.valid + if self.registration_id is not None: + result["registration_id"] = self.registration_id + else: + result["registration_id"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None + return result diff --git a/src/workos/agents/models/agent_registration.py b/src/workos/agents/models/agent_registration.py new file mode 100644 index 00000000..f0d6da4a --- /dev/null +++ b/src/workos/agents/models/agent_registration.py @@ -0,0 +1,77 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import cast +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_agent_identity import AgentRegistrationAgentIdentity +from .agent_registration_claim import AgentRegistrationClaim +from workos.common.models.agent_registration_kind import AgentRegistrationKind +from workos.common.models.agent_registration_status import AgentRegistrationStatus + + +@dataclass(slots=True) +class AgentRegistration: + """Agent Registration model.""" + + id: str + """Unique identifier of the agent registration.""" + agent_identity: "AgentRegistrationAgentIdentity" + """The agent identity associated with this registration.""" + organization_id: str + """Identifier of the organization the agent is registered to.""" + status: "AgentRegistrationStatus" + """The current verification status of the registration.""" + kind: "AgentRegistrationKind" + """The kind of agent registration.""" + claim: Optional["AgentRegistrationClaim"] + """The claim associated with this registration, or `null` if the registration has no claim.""" + created_at: datetime + """The timestamp when the registration was created.""" + updated_at: datetime + """The timestamp when the registration was last updated.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistration": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + agent_identity=AgentRegistrationAgentIdentity.from_dict( + cast(Dict[str, Any], data["agent_identity"]) + ), + organization_id=data["organization_id"], + status=AgentRegistrationStatus(data["status"]), + kind=AgentRegistrationKind(data["kind"]), + claim=AgentRegistrationClaim.from_dict(cast(Dict[str, Any], _v_claim)) + if (_v_claim := data["claim"]) is not None + else None, + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistration", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["agent_identity"] = self.agent_identity.to_dict() + result["organization_id"] = self.organization_id + result["status"] = ( + self.status.value if isinstance(self.status, Enum) else self.status + ) + result["kind"] = self.kind.value if isinstance(self.kind, Enum) else self.kind + if self.claim is not None: + result["claim"] = self.claim.to_dict() + else: + result["claim"] = None + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + return result diff --git a/src/workos/agents/models/agent_registration_agent_identity.py b/src/workos/agents/models/agent_registration_agent_identity.py new file mode 100644 index 00000000..b9170c05 --- /dev/null +++ b/src/workos/agents/models/agent_registration_agent_identity.py @@ -0,0 +1,48 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class AgentRegistrationAgentIdentity: + """The agent identity associated with this registration.""" + + id: str + """Unique identifier of the agent identity.""" + userland_user_id: Optional[str] + """Identifier of the AuthKit user the agent identity is bound to, or `null` when the agent is not associated with a user.""" + created_at: datetime + """The timestamp when the agent identity was created.""" + updated_at: datetime + """The timestamp when the agent identity was last updated.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationAgentIdentity": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + userland_user_id=data["userland_user_id"], + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationAgentIdentity", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + if self.userland_user_id is not None: + result["userland_user_id"] = self.userland_user_id + else: + result["userland_user_id"] = None + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + return result diff --git a/src/workos/agents/models/agent_registration_claim.py b/src/workos/agents/models/agent_registration_claim.py new file mode 100644 index 00000000..7b25babb --- /dev/null +++ b/src/workos/agents/models/agent_registration_claim.py @@ -0,0 +1,61 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_claim_claim_completion import ( + AgentRegistrationClaimClaimCompletion, +) + + +@dataclass(slots=True) +class AgentRegistrationClaim: + """Agent Registration Claim model.""" + + id: str + """Unique identifier of the claim.""" + claim_completion: Optional["AgentRegistrationClaimClaimCompletion"] + """The completion record for the claim, or `null` if the claim has not been completed.""" + created_at: datetime + """The timestamp when the claim was created.""" + updated_at: datetime + """The timestamp when the claim was last updated.""" + expires_at: datetime + """The timestamp when the claim expires.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationClaim": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + claim_completion=AgentRegistrationClaimClaimCompletion.from_dict( + cast(Dict[str, Any], _v_claim_completion) + ) + if (_v_claim_completion := data["claim_completion"]) is not None + else None, + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + expires_at=_parse_datetime(data["expires_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaim", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + if self.claim_completion is not None: + result["claim_completion"] = self.claim_completion.to_dict() + else: + result["claim_completion"] = None + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + result["expires_at"] = _format_datetime(self.expires_at) + return result diff --git a/src/workos/agents/models/agent_registration_claim_claim_completion.py b/src/workos/agents/models/agent_registration_claim_claim_completion.py new file mode 100644 index 00000000..25117f57 --- /dev/null +++ b/src/workos/agents/models/agent_registration_claim_claim_completion.py @@ -0,0 +1,49 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class AgentRegistrationClaimClaimCompletion: + """Agent Registration Claim Claim Completion model.""" + + id: str + """Unique identifier of the claim completion.""" + created_at: datetime + """The timestamp when the claim completion was created.""" + updated_at: datetime + """The timestamp when the claim completion was last updated.""" + expires_at: datetime + """The timestamp when the claim completion expires.""" + claimed_at: datetime + """The timestamp when the claim was completed.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationClaimClaimCompletion": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + expires_at=_parse_datetime(data["expires_at"]), + claimed_at=_parse_datetime(data["claimed_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimClaimCompletion", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + result["expires_at"] = _format_datetime(self.expires_at) + result["claimed_at"] = _format_datetime(self.claimed_at) + return result diff --git a/src/workos/agents/models/claim_view_response.py b/src/workos/agents/models/claim_view_response.py new file mode 100644 index 00000000..df434d8c --- /dev/null +++ b/src/workos/agents/models/claim_view_response.py @@ -0,0 +1,53 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +from typing import cast +from typing import Any, Dict, List +from workos._types import _raise_deserialize_error + +from .claim_view_response_organization import ClaimViewResponseOrganization +from workos.common.models.claim_view_response_status import ClaimViewResponseStatus + + +@dataclass(slots=True) +class ClaimViewResponse: + """Claim View Response model.""" + + id: str + """The agent registration ID.""" + status: "ClaimViewResponseStatus" + """Current status of the agent registration.""" + user_code: str + """The user code the agent needs to complete the claim.""" + organizations: List["ClaimViewResponseOrganization"] + """Organizations the user belongs to, offered as placement choices.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ClaimViewResponse": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + status=ClaimViewResponseStatus(data["status"]), + user_code=data["user_code"], + organizations=[ + ClaimViewResponseOrganization.from_dict(cast(Dict[str, Any], item)) + for item in cast(list[Any], data["organizations"]) + ], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ClaimViewResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["status"] = ( + self.status.value if isinstance(self.status, Enum) else self.status + ) + result["user_code"] = self.user_code + result["organizations"] = [item.to_dict() for item in self.organizations] + return result diff --git a/src/workos/agents/models/claim_view_response_organization.py b/src/workos/agents/models/claim_view_response_organization.py new file mode 100644 index 00000000..2faad8de --- /dev/null +++ b/src/workos/agents/models/claim_view_response_organization.py @@ -0,0 +1,6 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from workos.common.models.actor import Actor + +ClaimViewResponseOrganization: TypeAlias = Actor diff --git a/src/workos/api_keys/_resource.py b/src/workos/api_keys/_resource.py index 49179e5b..d5e9b46a 100644 --- a/src/workos/api_keys/_resource.py +++ b/src/workos/api_keys/_resource.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( ApiKey, ApiKeyValidationResponse, @@ -184,7 +184,7 @@ def create_api_key_expire( self, id: str, *, - expires_at: Optional[str] = None, + expires_at: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ApiKey: """Expire an API key @@ -207,13 +207,9 @@ def create_api_key_expire( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { - k: v - for k, v in { - "expires_at": expires_at, - }.items() - if v is not None - } + body: Dict[str, Any] = {} + if not isinstance(expires_at, NotGiven): + body["expires_at"] = expires_at return self._client.request( method="post", path=("api_keys", str(id), "expire"), @@ -389,7 +385,7 @@ async def create_api_key_expire( self, id: str, *, - expires_at: Optional[str] = None, + expires_at: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ApiKey: """Expire an API key @@ -412,13 +408,9 @@ async def create_api_key_expire( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { - k: v - for k, v in { - "expires_at": expires_at, - }.items() - if v is not None - } + body: Dict[str, Any] = {} + if not isinstance(expires_at, NotGiven): + body["expires_at"] = expires_at return await self._client.request( method="post", path=("api_keys", str(id), "expire"), diff --git a/src/workos/api_keys/models/api_key_validation_response.py b/src/workos/api_keys/models/api_key_validation_response.py index 0dc28eb2..a09843b1 100644 --- a/src/workos/api_keys/models/api_key_validation_response.py +++ b/src/workos/api_keys/models/api_key_validation_response.py @@ -15,6 +15,8 @@ class ApiKeyValidationResponse: """Api Key Validation Response model.""" api_key: Optional["ApiKey"] + agent_registration_id: Optional[str] = None + """The ID of the agent registration this API Key was issued for. Present only when the API Key is assigned to an agent registration.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyValidationResponse": @@ -24,6 +26,7 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyValidationResponse": api_key=ApiKey.from_dict(cast(Dict[str, Any], _v_api_key)) if (_v_api_key := data["api_key"]) is not None else None, + agent_registration_id=data.get("agent_registration_id"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("ApiKeyValidationResponse", e) @@ -35,4 +38,6 @@ def to_dict(self) -> Dict[str, Any]: result["api_key"] = self.api_key.to_dict() else: result["api_key"] = None + if self.agent_registration_id is not None: + result["agent_registration_id"] = self.agent_registration_id return result diff --git a/src/workos/authorization/_resource.py b/src/workos/authorization/_resource.py index fd05ffca..2ccf0073 100644 --- a/src/workos/authorization/_resource.py +++ b/src/workos/authorization/_resource.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( AuthorizationCheck, AuthorizationResource, @@ -819,7 +819,7 @@ def create_organization_role( *, name: str, slug: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Role: @@ -853,11 +853,12 @@ def create_organization_role( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="post", path=("authorization", "organizations", str(organization_id), "roles"), @@ -911,7 +912,7 @@ def update_organization_role( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Role: """Update a custom role @@ -941,10 +942,11 @@ def update_organization_role( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="patch", path=( @@ -1179,7 +1181,7 @@ def update_resource_by_external_id( external_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -1215,10 +1217,11 @@ def update_resource_by_external_id( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -1504,7 +1507,7 @@ def create_resource( name: str, resource_type_slug: str, organization_id: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -1537,16 +1540,13 @@ def create_resource( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "external_id": external_id, - "name": name, - "description": description, - "resource_type_slug": resource_type_slug, - "organization_id": organization_id, - }.items() - if v is not None + "external_id": external_id, + "name": name, + "resource_type_slug": resource_type_slug, + "organization_id": organization_id, } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -1602,7 +1602,7 @@ def update_resource( resource_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -1636,10 +1636,11 @@ def update_resource( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -1845,7 +1846,7 @@ def create_environment_role( *, slug: str, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Role: @@ -1878,11 +1879,12 @@ def create_environment_role( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="post", path=("authorization", "roles"), @@ -1927,7 +1929,7 @@ def update_environment_role( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Role: """Update an environment role @@ -1956,10 +1958,11 @@ def update_environment_role( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="patch", path=("authorization", "roles", str(slug)), @@ -2098,7 +2101,7 @@ def create_permission( *, slug: str, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Permission: @@ -2130,11 +2133,12 @@ def create_permission( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="post", path=("authorization", "permissions"), @@ -2178,7 +2182,7 @@ def update_permission( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> AuthorizationPermission: """Update a permission @@ -2206,10 +2210,11 @@ def update_permission( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="patch", path=("authorization", "permissions", str(slug)), @@ -2991,7 +2996,7 @@ async def create_organization_role( *, name: str, slug: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Role: @@ -3025,11 +3030,12 @@ async def create_organization_role( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="post", path=("authorization", "organizations", str(organization_id), "roles"), @@ -3083,7 +3089,7 @@ async def update_organization_role( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Role: """Update a custom role @@ -3113,10 +3119,11 @@ async def update_organization_role( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="patch", path=( @@ -3351,7 +3358,7 @@ async def update_resource_by_external_id( external_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -3387,10 +3394,11 @@ async def update_resource_by_external_id( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -3676,7 +3684,7 @@ async def create_resource( name: str, resource_type_slug: str, organization_id: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -3709,16 +3717,13 @@ async def create_resource( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "external_id": external_id, - "name": name, - "description": description, - "resource_type_slug": resource_type_slug, - "organization_id": organization_id, - }.items() - if v is not None + "external_id": external_id, + "name": name, + "resource_type_slug": resource_type_slug, + "organization_id": organization_id, } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -3774,7 +3779,7 @@ async def update_resource( resource_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, parent_resource: Optional[ Union[ParentResourceById, ParentResourceByExternalId] ] = None, @@ -3808,10 +3813,11 @@ async def update_resource( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description if parent_resource is not None: if isinstance(parent_resource, ParentResourceById): body["parent_resource_id"] = parent_resource.parent_resource_id @@ -4017,7 +4023,7 @@ async def create_environment_role( *, slug: str, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Role: @@ -4050,11 +4056,12 @@ async def create_environment_role( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="post", path=("authorization", "roles"), @@ -4099,7 +4106,7 @@ async def update_environment_role( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Role: """Update an environment role @@ -4128,10 +4135,11 @@ async def update_environment_role( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="patch", path=("authorization", "roles", str(slug)), @@ -4270,7 +4278,7 @@ async def create_permission( *, slug: str, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> Permission: @@ -4302,11 +4310,12 @@ async def create_permission( for k, v in { "slug": slug, "name": name, - "description": description, "resource_type_slug": resource_type_slug, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="post", path=("authorization", "permissions"), @@ -4350,7 +4359,7 @@ async def update_permission( slug: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> AuthorizationPermission: """Update a permission @@ -4378,10 +4387,11 @@ async def update_permission( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="patch", path=("authorization", "permissions", str(slug)), diff --git a/src/workos/common/__init__.py b/src/workos/common/__init__.py index 0b34bbbb..1d52b1b8 100644 --- a/src/workos/common/__init__.py +++ b/src/workos/common/__init__.py @@ -1,11 +1,58 @@ # This file is auto-generated by oagen. Do not edit. +from .models import ( + AccessTokenAgentRegistrationCredentialIssuedDataDetail as AccessTokenAgentRegistrationCredentialIssuedDataDetail, +) from .models import ActionAuthenticationDenied as ActionAuthenticationDenied from .models import ActionAuthenticationDeniedData as ActionAuthenticationDeniedData from .models import ActionUserRegistrationDenied as ActionUserRegistrationDenied from .models import ActionUserRegistrationDeniedData as ActionUserRegistrationDeniedData from .models import Actor as Actor from .models import AddRolePermission as AddRolePermission +from .models import ( + AgentAdminValidateCredentialRequestType as AgentAdminValidateCredentialRequestType, +) +from .models import ( + AgentRegistrationClaimAttemptCreated as AgentRegistrationClaimAttemptCreated, +) +from .models import ( + AgentRegistrationClaimAttemptCreatedData as AgentRegistrationClaimAttemptCreatedData, +) +from .models import AgentRegistrationClaimCompleted as AgentRegistrationClaimCompleted +from .models import ( + AgentRegistrationClaimCompletedData as AgentRegistrationClaimCompletedData, +) +from .models import ( + AgentRegistrationClaimCompletedDataClaimedBy as AgentRegistrationClaimCompletedDataClaimedBy, +) +from .models import AgentRegistrationCreated as AgentRegistrationCreated +from .models import AgentRegistrationCreatedData as AgentRegistrationCreatedData +from .models import ( + AgentRegistrationCreatedDataAgentIdentity as AgentRegistrationCreatedDataAgentIdentity, +) +from .models import ( + AgentRegistrationCredentialIssued as AgentRegistrationCredentialIssued, +) +from .models import ( + AgentRegistrationCredentialIssuedData as AgentRegistrationCredentialIssuedData, +) +from .models import ( + AgentRegistrationCredentialIssuedDataDetail as AgentRegistrationCredentialIssuedDataDetail, +) +from .models import AgentRegistrationDeleted as AgentRegistrationDeleted +from .models import AgentRegistrationDeletedData as AgentRegistrationDeletedData +from .models import AgentRegistrationExpired as AgentRegistrationExpired +from .models import AgentRegistrationExpiredData as AgentRegistrationExpiredData +from .models import AgentRegistrationKind as AgentRegistrationKind +from .models import ( + AgentRegistrationOrganizationSwitched as AgentRegistrationOrganizationSwitched, +) +from .models import ( + AgentRegistrationOrganizationSwitchedData as AgentRegistrationOrganizationSwitchedData, +) +from .models import AgentRegistrationRevoked as AgentRegistrationRevoked +from .models import AgentRegistrationRevokedData as AgentRegistrationRevokedData +from .models import AgentRegistrationStatus as AgentRegistrationStatus from .models import ApiKeyCreated as ApiKeyCreated from .models import ApiKeyCreatedData as ApiKeyCreatedData from .models import ApiKeyCreatedDataOwner as ApiKeyCreatedDataOwner @@ -103,6 +150,12 @@ from .models import ( AuthenticationRadarRiskDetectedData as AuthenticationRadarRiskDetectedData, ) +from .models import ( + AuthenticationReauthenticationSucceeded as AuthenticationReauthenticationSucceeded, +) +from .models import ( + AuthenticationReauthenticationSucceededData as AuthenticationReauthenticationSucceededData, +) from .models import AuthenticationSSOFailed as AuthenticationSSOFailed from .models import AuthenticationSSOFailedData as AuthenticationSSOFailedData from .models import AuthenticationSSOFailedDataError as AuthenticationSSOFailedDataError @@ -123,6 +176,7 @@ from .models import AuthenticationSSOTimedOutDataSSO as AuthenticationSSOTimedOutDataSSO from .models import AuthMethodMismatchError as AuthMethodMismatchError from .models import AuthorizationPermission as AuthorizationPermission +from .models import ClaimViewResponseStatus as ClaimViewResponseStatus from .models import ConnectApplication as ConnectApplication from .models import ConnectApplicationM2M as ConnectApplicationM2M from .models import ConnectApplicationOAuth as ConnectApplicationOAuth @@ -133,6 +187,7 @@ from .models import ConnectApplicationVariant as ConnectApplicationVariant from .models import ConnectedAccount as ConnectedAccount from .models import ConnectedAccountAuthMethod as ConnectedAccountAuthMethod +from .models import ConnectedAccountInputState as ConnectedAccountInputState from .models import ConnectedAccountState as ConnectedAccountState from .models import ConnectionActivated as ConnectionActivated from .models import ConnectionActivatedData as ConnectionActivatedData @@ -167,6 +222,7 @@ from .models import ConnectionState as ConnectionState from .models import ConnectionStatus as ConnectionStatus from .models import ConnectionType as ConnectionType +from .models import CreateDataIntegrationAuthMethods as CreateDataIntegrationAuthMethods from .models import CreateUserInviteOptionsLocale as CreateUserInviteOptionsLocale from .models import CreateUserPasswordHashType as CreateUserPasswordHashType from .models import CreateWebhookEndpointEvents as CreateWebhookEndpointEvents @@ -176,9 +232,13 @@ from .models import ( DataIntegrationAccessTokenResponseError as DataIntegrationAccessTokenResponseError, ) +from .models import DataIntegrationAuthMethods as DataIntegrationAuthMethods from .models import ( DataIntegrationCredentialsCredentialsType as DataIntegrationCredentialsCredentialsType, ) +from .models import ( + DataIntegrationCredentialsInputType as DataIntegrationCredentialsInputType, +) from .models import ( DataIntegrationCredentialsResponseError as DataIntegrationCredentialsResponseError, ) @@ -377,6 +437,12 @@ from .models import PermissionUpdatedData as PermissionUpdatedData from .models import PipeConnectedAccount as PipeConnectedAccount from .models import PipesConnectedAccountConnected as PipesConnectedAccountConnected +from .models import ( + PipesConnectedAccountConnectionFailed as PipesConnectedAccountConnectionFailed, +) +from .models import ( + PipesConnectedAccountConnectionFailedData as PipesConnectedAccountConnectionFailedData, +) from .models import ( PipesConnectedAccountDisconnected as PipesConnectedAccountDisconnected, ) @@ -384,6 +450,8 @@ PipesConnectedAccountReauthorizationNeeded as PipesConnectedAccountReauthorizationNeeded, ) from .models import ProfileConnectionType as ProfileConnectionType +from .models import RadarChallengeCreated as RadarChallengeCreated +from .models import RadarChallengeCreatedData as RadarChallengeCreatedData from .models import ( RadarStandaloneAssessRequestAction as RadarStandaloneAssessRequestAction, ) @@ -459,6 +527,8 @@ from .models import VaultDekReadData as VaultDekReadData from .models import VaultKekCreated as VaultKekCreated from .models import VaultKekCreatedData as VaultKekCreatedData +from .models import VaultKekDeleted as VaultKekDeleted +from .models import VaultKekDeletedData as VaultKekDeletedData from .models import VaultMetadataRead as VaultMetadataRead from .models import VaultMetadataReadData as VaultMetadataReadData from .models import VaultNamesListed as VaultNamesListed diff --git a/src/workos/common/models/__init__.py b/src/workos/common/models/__init__.py index 051252ec..faf8b74b 100644 --- a/src/workos/common/models/__init__.py +++ b/src/workos/common/models/__init__.py @@ -1,5 +1,8 @@ # This file is auto-generated by oagen. Do not edit. +from .access_token_agent_registration_credential_issued_data_detail import ( + AccessTokenAgentRegistrationCredentialIssuedDataDetail as AccessTokenAgentRegistrationCredentialIssuedDataDetail, +) from .action_authentication_denied import ( ActionAuthenticationDenied as ActionAuthenticationDenied, ) @@ -14,6 +17,70 @@ ) from .actor import Actor as Actor from .add_role_permission import AddRolePermission as AddRolePermission +from .agent_admin_validate_credential_request_type import ( + AgentAdminValidateCredentialRequestType as AgentAdminValidateCredentialRequestType, +) +from .agent_registration_claim_attempt_created import ( + AgentRegistrationClaimAttemptCreated as AgentRegistrationClaimAttemptCreated, +) +from .agent_registration_claim_attempt_created_data import ( + AgentRegistrationClaimAttemptCreatedData as AgentRegistrationClaimAttemptCreatedData, +) +from .agent_registration_claim_completed import ( + AgentRegistrationClaimCompleted as AgentRegistrationClaimCompleted, +) +from .agent_registration_claim_completed_data import ( + AgentRegistrationClaimCompletedData as AgentRegistrationClaimCompletedData, +) +from .agent_registration_claim_completed_data_claimed_by import ( + AgentRegistrationClaimCompletedDataClaimedBy as AgentRegistrationClaimCompletedDataClaimedBy, +) +from .agent_registration_created import ( + AgentRegistrationCreated as AgentRegistrationCreated, +) +from .agent_registration_created_data import ( + AgentRegistrationCreatedData as AgentRegistrationCreatedData, +) +from .agent_registration_created_data_agent_identity import ( + AgentRegistrationCreatedDataAgentIdentity as AgentRegistrationCreatedDataAgentIdentity, +) +from .agent_registration_credential_issued import ( + AgentRegistrationCredentialIssued as AgentRegistrationCredentialIssued, +) +from .agent_registration_credential_issued_data import ( + AgentRegistrationCredentialIssuedData as AgentRegistrationCredentialIssuedData, +) +from .agent_registration_credential_issued_data_detail import ( + AgentRegistrationCredentialIssuedDataDetail as AgentRegistrationCredentialIssuedDataDetail, +) +from .agent_registration_deleted import ( + AgentRegistrationDeleted as AgentRegistrationDeleted, +) +from .agent_registration_deleted_data import ( + AgentRegistrationDeletedData as AgentRegistrationDeletedData, +) +from .agent_registration_expired import ( + AgentRegistrationExpired as AgentRegistrationExpired, +) +from .agent_registration_expired_data import ( + AgentRegistrationExpiredData as AgentRegistrationExpiredData, +) +from .agent_registration_kind import AgentRegistrationKind as AgentRegistrationKind +from .agent_registration_organization_switched import ( + AgentRegistrationOrganizationSwitched as AgentRegistrationOrganizationSwitched, +) +from .agent_registration_organization_switched_data import ( + AgentRegistrationOrganizationSwitchedData as AgentRegistrationOrganizationSwitchedData, +) +from .agent_registration_revoked import ( + AgentRegistrationRevoked as AgentRegistrationRevoked, +) +from .agent_registration_revoked_data import ( + AgentRegistrationRevokedData as AgentRegistrationRevokedData, +) +from .agent_registration_status import ( + AgentRegistrationStatus as AgentRegistrationStatus, +) from .api_key_created import ApiKeyCreated as ApiKeyCreated from .api_key_created_data import ApiKeyCreatedData as ApiKeyCreatedData from .api_key_created_data_owner import ApiKeyCreatedDataOwner as ApiKeyCreatedDataOwner @@ -165,6 +232,12 @@ from .authentication_radar_risk_detected_data import ( AuthenticationRadarRiskDetectedData as AuthenticationRadarRiskDetectedData, ) +from .authentication_reauthentication_succeeded import ( + AuthenticationReauthenticationSucceeded as AuthenticationReauthenticationSucceeded, +) +from .authentication_reauthentication_succeeded_data import ( + AuthenticationReauthenticationSucceededData as AuthenticationReauthenticationSucceededData, +) from .authentication_sso_failed import ( AuthenticationSSOFailed as AuthenticationSSOFailed, ) @@ -211,6 +284,9 @@ AuthMethodMismatchError as AuthMethodMismatchError, ) from .authorization_permission import AuthorizationPermission as AuthorizationPermission +from .claim_view_response_status import ( + ClaimViewResponseStatus as ClaimViewResponseStatus, +) from .connect_application import ConnectApplication as ConnectApplication from .connect_application_m2m import ConnectApplicationM2M as ConnectApplicationM2M from .connect_application_oauth import ( @@ -225,6 +301,9 @@ from .connected_account_auth_method import ( ConnectedAccountAuthMethod as ConnectedAccountAuthMethod, ) +from .connected_account_input_state import ( + ConnectedAccountInputState as ConnectedAccountInputState, +) from .connected_account_state import ConnectedAccountState as ConnectedAccountState from .connection_activated_data_connection_type import * # noqa: F401,F403 from .connection_activated_data_state import * # noqa: F401,F403 @@ -279,6 +358,9 @@ from .connection_state import ConnectionState as ConnectionState from .connection_status import ConnectionStatus as ConnectionStatus from .connection_type import ConnectionType as ConnectionType +from .create_data_integration_auth_methods import ( + CreateDataIntegrationAuthMethods as CreateDataIntegrationAuthMethods, +) from .create_user_invite_options_locale import ( CreateUserInviteOptionsLocale as CreateUserInviteOptionsLocale, ) @@ -295,9 +377,15 @@ from .data_integration_access_token_response_error import ( DataIntegrationAccessTokenResponseError as DataIntegrationAccessTokenResponseError, ) +from .data_integration_auth_methods import ( + DataIntegrationAuthMethods as DataIntegrationAuthMethods, +) from .data_integration_credentials_credentials_type import ( DataIntegrationCredentialsCredentialsType as DataIntegrationCredentialsCredentialsType, ) +from .data_integration_credentials_input_type import ( + DataIntegrationCredentialsInputType as DataIntegrationCredentialsInputType, +) from .data_integration_credentials_response_error import ( DataIntegrationCredentialsResponseError as DataIntegrationCredentialsResponseError, ) @@ -620,6 +708,12 @@ from .pipes_connected_account_connected import ( PipesConnectedAccountConnected as PipesConnectedAccountConnected, ) +from .pipes_connected_account_connection_failed import ( + PipesConnectedAccountConnectionFailed as PipesConnectedAccountConnectionFailed, +) +from .pipes_connected_account_connection_failed_data import ( + PipesConnectedAccountConnectionFailedData as PipesConnectedAccountConnectionFailedData, +) from .pipes_connected_account_disconnected import ( PipesConnectedAccountDisconnected as PipesConnectedAccountDisconnected, ) @@ -627,6 +721,10 @@ PipesConnectedAccountReauthorizationNeeded as PipesConnectedAccountReauthorizationNeeded, ) from .profile_connection_type import ProfileConnectionType as ProfileConnectionType +from .radar_challenge_created import RadarChallengeCreated as RadarChallengeCreated +from .radar_challenge_created_data import ( + RadarChallengeCreatedData as RadarChallengeCreatedData, +) from .radar_standalone_assess_request_action import ( RadarStandaloneAssessRequestAction as RadarStandaloneAssessRequestAction, ) @@ -748,6 +846,8 @@ from .vault_dek_read_data import VaultDekReadData as VaultDekReadData from .vault_kek_created import VaultKekCreated as VaultKekCreated from .vault_kek_created_data import VaultKekCreatedData as VaultKekCreatedData +from .vault_kek_deleted import VaultKekDeleted as VaultKekDeleted +from .vault_kek_deleted_data import VaultKekDeletedData as VaultKekDeletedData from .vault_metadata_read import VaultMetadataRead as VaultMetadataRead from .vault_metadata_read_data import VaultMetadataReadData as VaultMetadataReadData from .vault_names_listed import VaultNamesListed as VaultNamesListed diff --git a/src/workos/common/models/access_token_agent_registration_credential_issued_data_detail.py b/src/workos/common/models/access_token_agent_registration_credential_issued_data_detail.py new file mode 100644 index 00000000..80463f26 --- /dev/null +++ b/src/workos/common/models/access_token_agent_registration_credential_issued_data_detail.py @@ -0,0 +1,43 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal, Optional, Union +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AccessTokenAgentRegistrationCredentialIssuedDataDetail: + """Access Token Agent Registration Credential Issued Data Detail model.""" + + kind: Literal["access_token"] + """The kind of credential issued.""" + jti: str + """The JWT ID of the issued access token.""" + expires_at: Union[str, Optional[Literal["null"]]] + """The timestamp when the access token expires.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AccessTokenAgentRegistrationCredentialIssuedDataDetail": + """Deserialize from a dictionary.""" + try: + return cls( + kind=data.get("kind", "access_token"), + jti=data["jti"], + expires_at=data["expires_at"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error( + "AccessTokenAgentRegistrationCredentialIssuedDataDetail", e + ) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["kind"] = self.kind + result["jti"] = self.jti + result["expires_at"] = self.expires_at + return result diff --git a/src/workos/common/models/agent_admin_validate_credential_request_type.py b/src/workos/common/models/agent_admin_validate_credential_request_type.py new file mode 100644 index 00000000..09e0a046 --- /dev/null +++ b/src/workos/common/models/agent_admin_validate_credential_request_type.py @@ -0,0 +1,32 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of agent admin validate credential request type values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class AgentAdminValidateCredentialRequestType(str, Enum): + """Known values for AgentAdminValidateCredentialRequestType.""" + + API_KEY = "api_key" + ACCESS_TOKEN = "access_token" + + @classmethod + def _missing_( + cls, value: object + ) -> Optional["AgentAdminValidateCredentialRequestType"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +AgentAdminValidateCredentialRequestTypeLiteral: TypeAlias = Literal[ + "api_key", "access_token" +] diff --git a/src/workos/common/models/agent_registration_claim_attempt_created.py b/src/workos/common/models/agent_registration_claim_attempt_created.py new file mode 100644 index 00000000..e1a2cfd3 --- /dev/null +++ b/src/workos/common/models/agent_registration_claim_attempt_created.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_claim_attempt_created_data import ( + AgentRegistrationClaimAttemptCreatedData, +) +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationClaimAttemptCreated: + """Agent Registration Claim Attempt Created model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.claim.attempt.created"] + data: "AgentRegistrationClaimAttemptCreatedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationClaimAttemptCreated": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.claim.attempt.created"), + data=AgentRegistrationClaimAttemptCreatedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimAttemptCreated", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_claim_attempt_created_data.py b/src/workos/common/models/agent_registration_claim_attempt_created_data.py new file mode 100644 index 00000000..af59cd23 --- /dev/null +++ b/src/workos/common/models/agent_registration_claim_attempt_created_data.py @@ -0,0 +1,61 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationClaimAttemptCreatedData: + """The event payload.""" + + object: Literal["agent_registration_claim_attempt"] + """Distinguishes the agent registration claim attempt object.""" + id: str + """Unique identifier of the agent registration claim attempt.""" + agent_registration_id: str + """The ID of the agent registration.""" + agent_registration_claim_id: str + """The ID of the agent registration claim.""" + login_hint: str + """The login hint for the claim attempt.""" + expires_at: str + """The timestamp when the claim attempt expires.""" + created_at: str + """The timestamp when the claim attempt was created.""" + updated_at: str + """The timestamp when the claim attempt was last updated.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentRegistrationClaimAttemptCreatedData": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "agent_registration_claim_attempt"), + id=data["id"], + agent_registration_id=data["agent_registration_id"], + agent_registration_claim_id=data["agent_registration_claim_id"], + login_hint=data["login_hint"], + expires_at=data["expires_at"], + created_at=data["created_at"], + updated_at=data["updated_at"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimAttemptCreatedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["agent_registration_id"] = self.agent_registration_id + result["agent_registration_claim_id"] = self.agent_registration_claim_id + result["login_hint"] = self.login_hint + result["expires_at"] = self.expires_at + result["created_at"] = self.created_at + result["updated_at"] = self.updated_at + return result diff --git a/src/workos/common/models/agent_registration_claim_completed.py b/src/workos/common/models/agent_registration_claim_completed.py new file mode 100644 index 00000000..14242075 --- /dev/null +++ b/src/workos/common/models/agent_registration_claim_completed.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_claim_completed_data import AgentRegistrationClaimCompletedData +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationClaimCompleted: + """Agent Registration Claim Completed model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.claim.completed"] + data: "AgentRegistrationClaimCompletedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationClaimCompleted": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.claim.completed"), + data=AgentRegistrationClaimCompletedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimCompleted", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_claim_completed_data.py b/src/workos/common/models/agent_registration_claim_completed_data.py new file mode 100644 index 00000000..aee5d615 --- /dev/null +++ b/src/workos/common/models/agent_registration_claim_completed_data.py @@ -0,0 +1,66 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error + +from .agent_registration_claim_completed_data_claimed_by import ( + AgentRegistrationClaimCompletedDataClaimedBy, +) + + +@dataclass(slots=True) +class AgentRegistrationClaimCompletedData: + """The event payload.""" + + object: Literal["agent_registration_claim"] + """Distinguishes the agent registration claim object.""" + id: str + """Unique identifier of the agent registration claim.""" + agent_registration_id: str + """The ID of the agent registration.""" + completed_by_attempt_id: str + """The ID of the claim attempt that completed the claim.""" + claimed_by: "AgentRegistrationClaimCompletedDataClaimedBy" + """The user who completed the claim.""" + completed_at: str + """The timestamp when the claim was completed.""" + created_at: str + """The timestamp when the claim was created.""" + updated_at: str + """The timestamp when the claim was last updated.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationClaimCompletedData": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "agent_registration_claim"), + id=data["id"], + agent_registration_id=data["agent_registration_id"], + completed_by_attempt_id=data["completed_by_attempt_id"], + claimed_by=AgentRegistrationClaimCompletedDataClaimedBy.from_dict( + cast(Dict[str, Any], data["claimed_by"]) + ), + completed_at=data["completed_at"], + created_at=data["created_at"], + updated_at=data["updated_at"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimCompletedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["agent_registration_id"] = self.agent_registration_id + result["completed_by_attempt_id"] = self.completed_by_attempt_id + result["claimed_by"] = self.claimed_by.to_dict() + result["completed_at"] = self.completed_at + result["created_at"] = self.created_at + result["updated_at"] = self.updated_at + return result diff --git a/src/workos/common/models/agent_registration_claim_completed_data_claimed_by.py b/src/workos/common/models/agent_registration_claim_completed_data_claimed_by.py new file mode 100644 index 00000000..dc41efac --- /dev/null +++ b/src/workos/common/models/agent_registration_claim_completed_data_claimed_by.py @@ -0,0 +1,37 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal, Optional, Union +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationClaimCompletedDataClaimedBy: + """The user who completed the claim.""" + + user_id: str + """The ID of the user who completed the claim.""" + organization_id: Union[str, Optional[Literal["null"]]] + """The ID of the organization the claiming user belongs to.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentRegistrationClaimCompletedDataClaimedBy": + """Deserialize from a dictionary.""" + try: + return cls( + user_id=data["user_id"], + organization_id=data["organization_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationClaimCompletedDataClaimedBy", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["user_id"] = self.user_id + result["organization_id"] = self.organization_id + return result diff --git a/src/workos/common/models/agent_registration_created.py b/src/workos/common/models/agent_registration_created.py new file mode 100644 index 00000000..1916c277 --- /dev/null +++ b/src/workos/common/models/agent_registration_created.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_created_data import AgentRegistrationCreatedData +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationCreated: + """Agent Registration Created model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.created"] + data: "AgentRegistrationCreatedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationCreated": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.created"), + data=AgentRegistrationCreatedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCreated", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_created_data.py b/src/workos/common/models/agent_registration_created_data.py new file mode 100644 index 00000000..f19988af --- /dev/null +++ b/src/workos/common/models/agent_registration_created_data.py @@ -0,0 +1,78 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +from typing import cast +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error + +from .agent_registration_created_data_agent_identity import ( + AgentRegistrationCreatedDataAgentIdentity, +) +from .agent_registration_created_data_kind import AgentRegistrationCreatedDataKind +from .agent_registration_created_data_method import AgentRegistrationCreatedDataMethod +from .agent_registration_created_data_status import AgentRegistrationCreatedDataStatus + + +@dataclass(slots=True) +class AgentRegistrationCreatedData: + """The event payload.""" + + object: Literal["agent_registration"] + """Distinguishes the agent registration object.""" + id: str + """Unique identifier of the agent registration.""" + agent_identity: "AgentRegistrationCreatedDataAgentIdentity" + """The agent identity for this registration.""" + organization_id: str + """The ID of the organization the registration belongs to.""" + status: "AgentRegistrationCreatedDataStatus" + """The current status of the registration.""" + kind: "AgentRegistrationCreatedDataKind" + """The kind of the registration.""" + method: "AgentRegistrationCreatedDataMethod" + """The authentication method of the registration.""" + created_at: str + """The timestamp when the registration was created.""" + updated_at: str + """The timestamp when the registration was last updated.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationCreatedData": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "agent_registration"), + id=data["id"], + agent_identity=AgentRegistrationCreatedDataAgentIdentity.from_dict( + cast(Dict[str, Any], data["agent_identity"]) + ), + organization_id=data["organization_id"], + status=AgentRegistrationCreatedDataStatus(data["status"]), + kind=AgentRegistrationCreatedDataKind(data["kind"]), + method=AgentRegistrationCreatedDataMethod(data["method"]), + created_at=data["created_at"], + updated_at=data["updated_at"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCreatedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["agent_identity"] = self.agent_identity.to_dict() + result["organization_id"] = self.organization_id + result["status"] = ( + self.status.value if isinstance(self.status, Enum) else self.status + ) + result["kind"] = self.kind.value if isinstance(self.kind, Enum) else self.kind + result["method"] = ( + self.method.value if isinstance(self.method, Enum) else self.method + ) + result["created_at"] = self.created_at + result["updated_at"] = self.updated_at + return result diff --git a/src/workos/common/models/agent_registration_created_data_agent_identity.py b/src/workos/common/models/agent_registration_created_data_agent_identity.py new file mode 100644 index 00000000..307cad94 --- /dev/null +++ b/src/workos/common/models/agent_registration_created_data_agent_identity.py @@ -0,0 +1,41 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal, Optional, Union +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationCreatedDataAgentIdentity: + """The agent identity for this registration.""" + + object: Literal["agent_identity"] + """Distinguishes the agent identity object.""" + id: str + """Unique identifier of the agent identity.""" + userland_user_id: Union[str, Optional[Literal["null"]]] + """The ID of the userland user bound to this agent identity.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentRegistrationCreatedDataAgentIdentity": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "agent_identity"), + id=data["id"], + userland_user_id=data["userland_user_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCreatedDataAgentIdentity", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["userland_user_id"] = self.userland_user_id + return result diff --git a/src/workos/common/models/agent_registration_created_data_kind.py b/src/workos/common/models/agent_registration_created_data_kind.py new file mode 100644 index 00000000..d779c734 --- /dev/null +++ b/src/workos/common/models/agent_registration_created_data_kind.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of agent registration created data kind values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class AgentRegistrationCreatedDataKind(str, Enum): + """Known values for AgentRegistrationCreatedDataKind.""" + + ANONYMOUS = "anonymous" + SERVICE_AUTH = "service_auth" + IDENTITY_ASSERTION = "identity_assertion" + + @classmethod + def _missing_(cls, value: object) -> Optional["AgentRegistrationCreatedDataKind"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +AgentRegistrationCreatedDataKindLiteral: TypeAlias = Literal[ + "anonymous", "service_auth", "identity_assertion" +] diff --git a/src/workos/common/models/agent_registration_created_data_method.py b/src/workos/common/models/agent_registration_created_data_method.py new file mode 100644 index 00000000..c25ec748 --- /dev/null +++ b/src/workos/common/models/agent_registration_created_data_method.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of agent registration created data method values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class AgentRegistrationCreatedDataMethod(str, Enum): + """Known values for AgentRegistrationCreatedDataMethod.""" + + ANONYMOUS = "anonymous" + SERVICE_AUTH = "service_auth" + ID_JAG = "id_jag" + + @classmethod + def _missing_(cls, value: object) -> Optional["AgentRegistrationCreatedDataMethod"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +AgentRegistrationCreatedDataMethodLiteral: TypeAlias = Literal[ + "anonymous", "service_auth", "id_jag" +] diff --git a/src/workos/common/models/agent_registration_created_data_status.py b/src/workos/common/models/agent_registration_created_data_status.py new file mode 100644 index 00000000..8bd7209d --- /dev/null +++ b/src/workos/common/models/agent_registration_created_data_status.py @@ -0,0 +1,32 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of agent registration created data status values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class AgentRegistrationCreatedDataStatus(str, Enum): + """Known values for AgentRegistrationCreatedDataStatus.""" + + UNVERIFIED = "unverified" + VERIFIED = "verified" + EXPIRED = "expired" + REVOKED = "revoked" + + @classmethod + def _missing_(cls, value: object) -> Optional["AgentRegistrationCreatedDataStatus"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +AgentRegistrationCreatedDataStatusLiteral: TypeAlias = Literal[ + "unverified", "verified", "expired", "revoked" +] diff --git a/src/workos/common/models/agent_registration_credential_issued.py b/src/workos/common/models/agent_registration_credential_issued.py new file mode 100644 index 00000000..12cede1e --- /dev/null +++ b/src/workos/common/models/agent_registration_credential_issued.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_credential_issued_data import ( + AgentRegistrationCredentialIssuedData, +) +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationCredentialIssued: + """Agent Registration Credential Issued model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.credential.issued"] + data: "AgentRegistrationCredentialIssuedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationCredentialIssued": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.credential.issued"), + data=AgentRegistrationCredentialIssuedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCredentialIssued", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_credential_issued_data.py b/src/workos/common/models/agent_registration_credential_issued_data.py new file mode 100644 index 00000000..136cadbc --- /dev/null +++ b/src/workos/common/models/agent_registration_credential_issued_data.py @@ -0,0 +1,75 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, Literal, Union +from workos._types import _raise_deserialize_error + +from .access_token_agent_registration_credential_issued_data_detail import ( + AccessTokenAgentRegistrationCredentialIssuedDataDetail, +) +from .agent_registration_credential_issued_data_detail import ( + AgentRegistrationCredentialIssuedDataDetail, +) + + +@dataclass(slots=True) +class AgentRegistrationCredentialIssuedData: + """The event payload.""" + + object: Literal["agent_registration_credential"] + """Distinguishes the agent registration credential object.""" + id: str + """Unique identifier of the agent registration credential.""" + agent_registration_id: str + """The ID of the agent registration.""" + detail: Union[ + "AgentRegistrationCredentialIssuedDataDetail", + "AccessTokenAgentRegistrationCredentialIssuedDataDetail", + ] + """Details of the issued credential.""" + created_at: str + """The timestamp when the credential was issued.""" + updated_at: str + """The timestamp when the credential was last updated.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationCredentialIssuedData": + """Deserialize from a dictionary.""" + try: + _detail_raw = data["detail"] + _detail_data = cast(Dict[str, Any], _detail_raw) + _detail_disc = cast(str, _detail_data.get("kind")) + _detail_disc_map: Dict[str, Any] = { + "api_key": AgentRegistrationCredentialIssuedDataDetail, + "access_token": AccessTokenAgentRegistrationCredentialIssuedDataDetail, + } + _detail_cls = _detail_disc_map.get(_detail_disc) + if _detail_cls is None: + raise ValueError( + f"Unknown discriminator 'kind' for AgentRegistrationCredentialIssuedData.detail: {_detail_disc!r}. " + f"Expected one of {sorted(_detail_disc_map)}." + ) + return cls( + object=data.get("object", "agent_registration_credential"), + id=data["id"], + agent_registration_id=data["agent_registration_id"], + detail=_detail_cls.from_dict(_detail_data), + created_at=data["created_at"], + updated_at=data["updated_at"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCredentialIssuedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["agent_registration_id"] = self.agent_registration_id + result["detail"] = self.detail.to_dict() + result["created_at"] = self.created_at + result["updated_at"] = self.updated_at + return result diff --git a/src/workos/common/models/agent_registration_credential_issued_data_detail.py b/src/workos/common/models/agent_registration_credential_issued_data_detail.py new file mode 100644 index 00000000..a4e02872 --- /dev/null +++ b/src/workos/common/models/agent_registration_credential_issued_data_detail.py @@ -0,0 +1,37 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationCredentialIssuedDataDetail: + """Agent Registration Credential Issued Data Detail model.""" + + kind: Literal["api_key"] + """The kind of credential issued.""" + api_key_id: str + """The ID of the issued API key.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentRegistrationCredentialIssuedDataDetail": + """Deserialize from a dictionary.""" + try: + return cls( + kind=data.get("kind", "api_key"), + api_key_id=data["api_key_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationCredentialIssuedDataDetail", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["kind"] = self.kind + result["api_key_id"] = self.api_key_id + return result diff --git a/src/workos/common/models/agent_registration_deleted.py b/src/workos/common/models/agent_registration_deleted.py new file mode 100644 index 00000000..f6f18958 --- /dev/null +++ b/src/workos/common/models/agent_registration_deleted.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_deleted_data import AgentRegistrationDeletedData +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationDeleted: + """Agent Registration Deleted model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.deleted"] + data: "AgentRegistrationDeletedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationDeleted": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.deleted"), + data=AgentRegistrationDeletedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationDeleted", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_deleted_data.py b/src/workos/common/models/agent_registration_deleted_data.py new file mode 100644 index 00000000..37cc2aed --- /dev/null +++ b/src/workos/common/models/agent_registration_deleted_data.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationDeletedData: + """The event payload.""" + + agent_registration_id: str + """The agent registration that was deleted.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationDeletedData": + """Deserialize from a dictionary.""" + try: + return cls( + agent_registration_id=data["agent_registration_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationDeletedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["agent_registration_id"] = self.agent_registration_id + return result diff --git a/src/workos/common/models/agent_registration_expired.py b/src/workos/common/models/agent_registration_expired.py new file mode 100644 index 00000000..1f94fcff --- /dev/null +++ b/src/workos/common/models/agent_registration_expired.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_expired_data import AgentRegistrationExpiredData +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationExpired: + """Agent Registration Expired model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.expired"] + data: "AgentRegistrationExpiredData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationExpired": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.expired"), + data=AgentRegistrationExpiredData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationExpired", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_expired_data.py b/src/workos/common/models/agent_registration_expired_data.py new file mode 100644 index 00000000..1d4cd1b4 --- /dev/null +++ b/src/workos/common/models/agent_registration_expired_data.py @@ -0,0 +1,6 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .agent_registration_deleted_data import AgentRegistrationDeletedData + +AgentRegistrationExpiredData: TypeAlias = AgentRegistrationDeletedData diff --git a/src/workos/common/models/agent_registration_kind.py b/src/workos/common/models/agent_registration_kind.py new file mode 100644 index 00000000..ef7d3910 --- /dev/null +++ b/src/workos/common/models/agent_registration_kind.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .agent_registration_created_data_kind import AgentRegistrationCreatedDataKind + +AgentRegistrationKind: TypeAlias = AgentRegistrationCreatedDataKind +__all__ = ["AgentRegistrationKind"] diff --git a/src/workos/common/models/agent_registration_organization_switched.py b/src/workos/common/models/agent_registration_organization_switched.py new file mode 100644 index 00000000..54ab8178 --- /dev/null +++ b/src/workos/common/models/agent_registration_organization_switched.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_organization_switched_data import ( + AgentRegistrationOrganizationSwitchedData, +) +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationOrganizationSwitched: + """Agent Registration Organization Switched model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.organization.switched"] + data: "AgentRegistrationOrganizationSwitchedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationOrganizationSwitched": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.organization.switched"), + data=AgentRegistrationOrganizationSwitchedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationOrganizationSwitched", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_organization_switched_data.py b/src/workos/common/models/agent_registration_organization_switched_data.py new file mode 100644 index 00000000..b4caf4cc --- /dev/null +++ b/src/workos/common/models/agent_registration_organization_switched_data.py @@ -0,0 +1,41 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AgentRegistrationOrganizationSwitchedData: + """The event payload.""" + + agent_registration_id: str + """The agent registration that was moved.""" + from_organization_id: str + """The agent-created organization the registration is moving off of. Migrate its resources to `to_organization_id`, then delete it.""" + to_organization_id: str + """The organization the registration now belongs to.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AgentRegistrationOrganizationSwitchedData": + """Deserialize from a dictionary.""" + try: + return cls( + agent_registration_id=data["agent_registration_id"], + from_organization_id=data["from_organization_id"], + to_organization_id=data["to_organization_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationOrganizationSwitchedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["agent_registration_id"] = self.agent_registration_id + result["from_organization_id"] = self.from_organization_id + result["to_organization_id"] = self.to_organization_id + return result diff --git a/src/workos/common/models/agent_registration_revoked.py b/src/workos/common/models/agent_registration_revoked.py new file mode 100644 index 00000000..a0e3cd42 --- /dev/null +++ b/src/workos/common/models/agent_registration_revoked.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .agent_registration_revoked_data import AgentRegistrationRevokedData +from .event_context import EventContext + + +@dataclass(slots=True) +class AgentRegistrationRevoked: + """Agent Registration Revoked model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["agent.registration.revoked"] + data: "AgentRegistrationRevokedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AgentRegistrationRevoked": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "agent.registration.revoked"), + data=AgentRegistrationRevokedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AgentRegistrationRevoked", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/agent_registration_revoked_data.py b/src/workos/common/models/agent_registration_revoked_data.py new file mode 100644 index 00000000..55091ff6 --- /dev/null +++ b/src/workos/common/models/agent_registration_revoked_data.py @@ -0,0 +1,6 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .agent_registration_deleted_data import AgentRegistrationDeletedData + +AgentRegistrationRevokedData: TypeAlias = AgentRegistrationDeletedData diff --git a/src/workos/common/models/agent_registration_status.py b/src/workos/common/models/agent_registration_status.py new file mode 100644 index 00000000..89aa376e --- /dev/null +++ b/src/workos/common/models/agent_registration_status.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .agent_registration_created_data_status import AgentRegistrationCreatedDataStatus + +AgentRegistrationStatus: TypeAlias = AgentRegistrationCreatedDataStatus +__all__ = ["AgentRegistrationStatus"] diff --git a/src/workos/common/models/authentication_reauthentication_succeeded.py b/src/workos/common/models/authentication_reauthentication_succeeded.py new file mode 100644 index 00000000..6c165996 --- /dev/null +++ b/src/workos/common/models/authentication_reauthentication_succeeded.py @@ -0,0 +1,64 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .authentication_reauthentication_succeeded_data import ( + AuthenticationReauthenticationSucceededData, +) +from .event_context import EventContext + + +@dataclass(slots=True) +class AuthenticationReauthenticationSucceeded: + """Authentication Reauthentication Succeeded model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["authentication.reauthentication_succeeded"] + data: "AuthenticationReauthenticationSucceededData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AuthenticationReauthenticationSucceeded": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "authentication.reauthentication_succeeded"), + data=AuthenticationReauthenticationSucceededData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AuthenticationReauthenticationSucceeded", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/authentication_reauthentication_succeeded_data.py b/src/workos/common/models/authentication_reauthentication_succeeded_data.py new file mode 100644 index 00000000..bc7438bb --- /dev/null +++ b/src/workos/common/models/authentication_reauthentication_succeeded_data.py @@ -0,0 +1,57 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AuthenticationReauthenticationSucceededData: + """The event payload.""" + + type: Literal["reauthentication"] + status: Literal["succeeded"] + ip_address: Optional[str] + """The IP address of the request.""" + user_agent: Optional[str] + """The user agent of the request.""" + user_id: str + """The ID of the user.""" + email: str + """The email address of the user.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "AuthenticationReauthenticationSucceededData": + """Deserialize from a dictionary.""" + try: + return cls( + type=data.get("type", "reauthentication"), + status=data.get("status", "succeeded"), + ip_address=data["ip_address"], + user_agent=data["user_agent"], + user_id=data["user_id"], + email=data["email"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AuthenticationReauthenticationSucceededData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type + result["status"] = self.status + if self.ip_address is not None: + result["ip_address"] = self.ip_address + else: + result["ip_address"] = None + if self.user_agent is not None: + result["user_agent"] = self.user_agent + else: + result["user_agent"] = None + result["user_id"] = self.user_id + result["email"] = self.email + return result diff --git a/src/workos/common/models/claim_view_response_status.py b/src/workos/common/models/claim_view_response_status.py new file mode 100644 index 00000000..785bf6b1 --- /dev/null +++ b/src/workos/common/models/claim_view_response_status.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .agent_registration_created_data_status import AgentRegistrationCreatedDataStatus + +ClaimViewResponseStatus: TypeAlias = AgentRegistrationCreatedDataStatus +__all__ = ["ClaimViewResponseStatus"] diff --git a/src/workos/common/models/connected_account_input_state.py b/src/workos/common/models/connected_account_input_state.py new file mode 100644 index 00000000..362be4e0 --- /dev/null +++ b/src/workos/common/models/connected_account_input_state.py @@ -0,0 +1,30 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of connected account input state values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class ConnectedAccountInputState(str, Enum): + """Known values for ConnectedAccountInputState.""" + + CONNECTED = "connected" + NEEDS_REAUTHORIZATION = "needs_reauthorization" + + @classmethod + def _missing_(cls, value: object) -> Optional["ConnectedAccountInputState"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +ConnectedAccountInputStateLiteral: TypeAlias = Literal[ + "connected", "needs_reauthorization" +] diff --git a/src/workos/common/models/connected_account_state.py b/src/workos/common/models/connected_account_state.py index e36328ef..743b7d0b 100644 --- a/src/workos/common/models/connected_account_state.py +++ b/src/workos/common/models/connected_account_state.py @@ -14,6 +14,7 @@ class ConnectedAccountState(str, Enum): CONNECTED = "connected" NEEDS_REAUTHORIZATION = "needs_reauthorization" + DISCONNECTED = "disconnected" @classmethod def _missing_(cls, value: object) -> Optional["ConnectedAccountState"]: @@ -25,4 +26,6 @@ def _missing_(cls, value: object) -> Optional["ConnectedAccountState"]: return unknown -ConnectedAccountStateLiteral: TypeAlias = Literal["connected", "needs_reauthorization"] +ConnectedAccountStateLiteral: TypeAlias = Literal[ + "connected", "needs_reauthorization", "disconnected" +] diff --git a/src/workos/common/models/create_data_integration_auth_methods.py b/src/workos/common/models/create_data_integration_auth_methods.py new file mode 100644 index 00000000..045091aa --- /dev/null +++ b/src/workos/common/models/create_data_integration_auth_methods.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .connected_account_auth_method import ConnectedAccountAuthMethod + +CreateDataIntegrationAuthMethods: TypeAlias = ConnectedAccountAuthMethod +__all__ = ["CreateDataIntegrationAuthMethods"] diff --git a/src/workos/common/models/create_user_password_hash_type.py b/src/workos/common/models/create_user_password_hash_type.py index 3d0643fc..a36abbce 100644 --- a/src/workos/common/models/create_user_password_hash_type.py +++ b/src/workos/common/models/create_user_password_hash_type.py @@ -15,6 +15,7 @@ class CreateUserPasswordHashType(str, Enum): BCRYPT = "bcrypt" FIREBASE_SCRYPT = "firebase-scrypt" SSHA = "ssha" + SSHA_256 = "ssha256" SCRYPT = "scrypt" PBKDF_2 = "pbkdf2" ARGON_2 = "argon2" @@ -30,5 +31,5 @@ def _missing_(cls, value: object) -> Optional["CreateUserPasswordHashType"]: CreateUserPasswordHashTypeLiteral: TypeAlias = Literal[ - "bcrypt", "firebase-scrypt", "ssha", "scrypt", "pbkdf2", "argon2" + "bcrypt", "firebase-scrypt", "ssha", "ssha256", "scrypt", "pbkdf2", "argon2" ] diff --git a/src/workos/common/models/create_webhook_endpoint_events.py b/src/workos/common/models/create_webhook_endpoint_events.py index 9b47703e..eb5742b0 100644 --- a/src/workos/common/models/create_webhook_endpoint_events.py +++ b/src/workos/common/models/create_webhook_endpoint_events.py @@ -18,9 +18,12 @@ class CreateWebhookEndpointEvents(str, Enum): ) AGENT_REGISTRATION_CLAIM_COMPLETED = "agent.registration.claim.completed" AGENT_REGISTRATION_CREDENTIAL_ISSUED = "agent.registration.credential.issued" + AGENT_REGISTRATION_DELETED = "agent.registration.deleted" + AGENT_REGISTRATION_EXPIRED = "agent.registration.expired" AGENT_REGISTRATION_ORGANIZATION_SWITCHED = ( "agent.registration.organization.switched" ) + AGENT_REGISTRATION_REVOKED = "agent.registration.revoked" AUTHENTICATION_EMAIL_VERIFICATION_SUCCEEDED = ( "authentication.email_verification_succeeded" ) @@ -37,6 +40,7 @@ class CreateWebhookEndpointEvents(str, Enum): AUTHENTICATION_SSO_STARTED = "authentication.sso_started" AUTHENTICATION_SSO_SUCCEEDED = "authentication.sso_succeeded" AUTHENTICATION_SSO_TIMED_OUT = "authentication.sso_timed_out" + RADAR_CHALLENGE_CREATED = "radar.challenge_created" AUTHENTICATION_RADAR_RISK_DETECTED = "authentication.radar_risk_detected" AUTHENTICATION_REAUTHENTICATION_SUCCEEDED = ( "authentication.reauthentication_succeeded" @@ -130,7 +134,10 @@ def _missing_(cls, value: object) -> Optional["CreateWebhookEndpointEvents"]: "agent.registration.claim.attempt.created", "agent.registration.claim.completed", "agent.registration.credential.issued", + "agent.registration.deleted", + "agent.registration.expired", "agent.registration.organization.switched", + "agent.registration.revoked", "authentication.email_verification_succeeded", "authentication.magic_auth_failed", "authentication.magic_auth_succeeded", @@ -145,6 +152,7 @@ def _missing_(cls, value: object) -> Optional["CreateWebhookEndpointEvents"]: "authentication.sso_started", "authentication.sso_succeeded", "authentication.sso_timed_out", + "radar.challenge_created", "authentication.radar_risk_detected", "authentication.reauthentication_succeeded", "api_key.created", diff --git a/src/workos/common/models/data_integration_auth_methods.py b/src/workos/common/models/data_integration_auth_methods.py new file mode 100644 index 00000000..aa25436d --- /dev/null +++ b/src/workos/common/models/data_integration_auth_methods.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .connected_account_auth_method import ConnectedAccountAuthMethod + +DataIntegrationAuthMethods: TypeAlias = ConnectedAccountAuthMethod +__all__ = ["DataIntegrationAuthMethods"] diff --git a/src/workos/common/models/data_integration_credentials_input_type.py b/src/workos/common/models/data_integration_credentials_input_type.py new file mode 100644 index 00000000..4d832a70 --- /dev/null +++ b/src/workos/common/models/data_integration_credentials_input_type.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .data_integration_credential_type import DataIntegrationCredentialType + +DataIntegrationCredentialsInputType: TypeAlias = DataIntegrationCredentialType +__all__ = ["DataIntegrationCredentialsInputType"] diff --git a/src/workos/common/models/data_integrations_list_response_data_connected_account_state.py b/src/workos/common/models/data_integrations_list_response_data_connected_account_state.py index e10aa638..718e5709 100644 --- a/src/workos/common/models/data_integrations_list_response_data_connected_account_state.py +++ b/src/workos/common/models/data_integrations_list_response_data_connected_account_state.py @@ -1,33 +1,7 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of data integrations list response data connected account state values.""" +from typing import TypeAlias +from .connected_account_state import ConnectedAccountState -from __future__ import annotations - -from enum import Enum -from typing import Optional -from typing import Literal, TypeAlias - - -class DataIntegrationsListResponseDataConnectedAccountState(str, Enum): - """Known values for DataIntegrationsListResponseDataConnectedAccountState.""" - - CONNECTED = "connected" - NEEDS_REAUTHORIZATION = "needs_reauthorization" - DISCONNECTED = "disconnected" - - @classmethod - def _missing_( - cls, value: object - ) -> Optional["DataIntegrationsListResponseDataConnectedAccountState"]: - if not isinstance(value, str): - return None - unknown = str.__new__(cls, value) - unknown._name_ = value.upper() - unknown._value_ = value - return unknown - - -DataIntegrationsListResponseDataConnectedAccountStateLiteral: TypeAlias = Literal[ - "connected", "needs_reauthorization", "disconnected" -] +DataIntegrationsListResponseDataConnectedAccountState: TypeAlias = ConnectedAccountState +__all__ = ["DataIntegrationsListResponseDataConnectedAccountState"] diff --git a/src/workos/common/models/permission_created_data.py b/src/workos/common/models/permission_created_data.py index c9cf5fe2..061d1b97 100644 --- a/src/workos/common/models/permission_created_data.py +++ b/src/workos/common/models/permission_created_data.py @@ -1,64 +1,6 @@ # This file is auto-generated by oagen. Do not edit. -from __future__ import annotations +from typing import TypeAlias +from .authorization_permission import AuthorizationPermission -from dataclasses import dataclass -from datetime import datetime -from typing import Any, Dict, Literal, Optional -from workos._types import _raise_deserialize_error -from workos._types import _format_datetime, _parse_datetime - - -@dataclass(slots=True) -class PermissionCreatedData: - """The event payload.""" - - object: Literal["permission"] - """Distinguishes the permission object.""" - id: str - """Unique identifier of the permission.""" - slug: str - """The slug identifier of the permission.""" - name: str - """The name of the permission.""" - description: Optional[str] - """A description of the permission.""" - system: bool - """Whether the permission is a system permission.""" - created_at: datetime - """An ISO 8601 timestamp.""" - updated_at: datetime - """An ISO 8601 timestamp.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "PermissionCreatedData": - """Deserialize from a dictionary.""" - try: - return cls( - object=data.get("object", "permission"), - id=data["id"], - slug=data["slug"], - name=data["name"], - description=data["description"], - system=data["system"], - created_at=_parse_datetime(data["created_at"]), - updated_at=_parse_datetime(data["updated_at"]), - ) - except (KeyError, ValueError) as e: - _raise_deserialize_error("PermissionCreatedData", e) - - def to_dict(self) -> Dict[str, Any]: - """Serialize to a dictionary.""" - result: Dict[str, Any] = {} - result["object"] = self.object - result["id"] = self.id - result["slug"] = self.slug - result["name"] = self.name - if self.description is not None: - result["description"] = self.description - else: - result["description"] = None - result["system"] = self.system - result["created_at"] = _format_datetime(self.created_at) - result["updated_at"] = _format_datetime(self.updated_at) - return result +PermissionCreatedData: TypeAlias = AuthorizationPermission diff --git a/src/workos/common/models/permission_deleted_data.py b/src/workos/common/models/permission_deleted_data.py index 02ec1189..9fcb76a3 100644 --- a/src/workos/common/models/permission_deleted_data.py +++ b/src/workos/common/models/permission_deleted_data.py @@ -1,6 +1,6 @@ # This file is auto-generated by oagen. Do not edit. from typing import TypeAlias -from .permission_created_data import PermissionCreatedData +from .authorization_permission import AuthorizationPermission -PermissionDeletedData: TypeAlias = PermissionCreatedData +PermissionDeletedData: TypeAlias = AuthorizationPermission diff --git a/src/workos/common/models/permission_updated_data.py b/src/workos/common/models/permission_updated_data.py index 1785b37a..feb74da6 100644 --- a/src/workos/common/models/permission_updated_data.py +++ b/src/workos/common/models/permission_updated_data.py @@ -1,6 +1,6 @@ # This file is auto-generated by oagen. Do not edit. from typing import TypeAlias -from .permission_created_data import PermissionCreatedData +from .authorization_permission import AuthorizationPermission -PermissionUpdatedData: TypeAlias = PermissionCreatedData +PermissionUpdatedData: TypeAlias = AuthorizationPermission diff --git a/src/workos/common/models/pipe_connected_account_state.py b/src/workos/common/models/pipe_connected_account_state.py index 7a91ca62..42270799 100644 --- a/src/workos/common/models/pipe_connected_account_state.py +++ b/src/workos/common/models/pipe_connected_account_state.py @@ -1,30 +1,7 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of pipe connected account state values.""" +from typing import TypeAlias +from .connected_account_input_state import ConnectedAccountInputState -from __future__ import annotations - -from enum import Enum -from typing import Optional -from typing import Literal, TypeAlias - - -class PipeConnectedAccountState(str, Enum): - """Known values for PipeConnectedAccountState.""" - - CONNECTED = "connected" - NEEDS_REAUTHORIZATION = "needs_reauthorization" - - @classmethod - def _missing_(cls, value: object) -> Optional["PipeConnectedAccountState"]: - if not isinstance(value, str): - return None - unknown = str.__new__(cls, value) - unknown._name_ = value.upper() - unknown._value_ = value - return unknown - - -PipeConnectedAccountStateLiteral: TypeAlias = Literal[ - "connected", "needs_reauthorization" -] +PipeConnectedAccountState: TypeAlias = ConnectedAccountInputState +__all__ = ["PipeConnectedAccountState"] diff --git a/src/workos/common/models/pipes_connected_account_connection_failed.py b/src/workos/common/models/pipes_connected_account_connection_failed.py new file mode 100644 index 00000000..5f72dd98 --- /dev/null +++ b/src/workos/common/models/pipes_connected_account_connection_failed.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .pipes_connected_account_connection_failed_data import ( + PipesConnectedAccountConnectionFailedData, +) + + +@dataclass(slots=True) +class PipesConnectedAccountConnectionFailed: + """Pipes Connected Account Connection Failed model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["pipes.connected_account.connection_failed"] + data: "PipesConnectedAccountConnectionFailedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "PipesConnectedAccountConnectionFailed": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "pipes.connected_account.connection_failed"), + data=PipesConnectedAccountConnectionFailedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipesConnectedAccountConnectionFailed", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/pipes_connected_account_connection_failed_data.py b/src/workos/common/models/pipes_connected_account_connection_failed_data.py new file mode 100644 index 00000000..f6a5c129 --- /dev/null +++ b/src/workos/common/models/pipes_connected_account_connection_failed_data.py @@ -0,0 +1,86 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class PipesConnectedAccountConnectionFailedData: + """The event payload.""" + + object: Literal["connection_failed"] + """The object type.""" + data_integration_id: str + """The unique ID of the data integration.""" + provider_slug: str + """The provider slug for this connection attempt.""" + user_id: Optional[str] + """The ID of the User the connection attempt belongs to.""" + organization_id: Optional[str] + """The ID of the Organization the connection attempt belongs to.""" + error_code: str + """A machine-readable error code for the failure.""" + error_reason: Optional[str] + """A human-readable explanation of the failure.""" + provider_error: Optional[str] + """The raw error code returned by the OAuth provider.""" + provider_error_description: Optional[str] + """The raw error description returned by the OAuth provider.""" + created_at: datetime + """An ISO 8601 timestamp.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "PipesConnectedAccountConnectionFailedData": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "connection_failed"), + data_integration_id=data["data_integration_id"], + provider_slug=data["provider_slug"], + user_id=data["user_id"], + organization_id=data["organization_id"], + error_code=data["error_code"], + error_reason=data["error_reason"], + provider_error=data["provider_error"], + provider_error_description=data["provider_error_description"], + created_at=_parse_datetime(data["created_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipesConnectedAccountConnectionFailedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["data_integration_id"] = self.data_integration_id + result["provider_slug"] = self.provider_slug + if self.user_id is not None: + result["user_id"] = self.user_id + else: + result["user_id"] = None + if self.organization_id is not None: + result["organization_id"] = self.organization_id + else: + result["organization_id"] = None + result["error_code"] = self.error_code + if self.error_reason is not None: + result["error_reason"] = self.error_reason + else: + result["error_reason"] = None + if self.provider_error is not None: + result["provider_error"] = self.provider_error + else: + result["provider_error"] = None + if self.provider_error_description is not None: + result["provider_error_description"] = self.provider_error_description + else: + result["provider_error_description"] = None + result["created_at"] = _format_datetime(self.created_at) + return result diff --git a/src/workos/common/models/radar_challenge_created.py b/src/workos/common/models/radar_challenge_created.py new file mode 100644 index 00000000..8c566104 --- /dev/null +++ b/src/workos/common/models/radar_challenge_created.py @@ -0,0 +1,60 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .radar_challenge_created_data import RadarChallengeCreatedData + + +@dataclass(slots=True) +class RadarChallengeCreated: + """Radar Challenge Created model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["radar.challenge_created"] + data: "RadarChallengeCreatedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "RadarChallengeCreated": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "radar.challenge_created"), + data=RadarChallengeCreatedData.from_dict( + cast(Dict[str, Any], data["data"]) + ), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("RadarChallengeCreated", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/radar_challenge_created_data.py b/src/workos/common/models/radar_challenge_created_data.py new file mode 100644 index 00000000..b4ee14ba --- /dev/null +++ b/src/workos/common/models/radar_challenge_created_data.py @@ -0,0 +1,43 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class RadarChallengeCreatedData: + """The event payload.""" + + type: Literal["email"] + """The type of the Radar challenge.""" + radar_challenge_id: str + """The ID of the Radar challenge.""" + user_id: str + """The ID of the user.""" + email: str + """The email address of the user.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "RadarChallengeCreatedData": + """Deserialize from a dictionary.""" + try: + return cls( + type=data.get("type", "email"), + radar_challenge_id=data["radar_challenge_id"], + user_id=data["user_id"], + email=data["email"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("RadarChallengeCreatedData", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type + result["radar_challenge_id"] = self.radar_challenge_id + result["user_id"] = self.user_id + result["email"] = self.email + return result diff --git a/src/workos/common/models/vault_kek_deleted.py b/src/workos/common/models/vault_kek_deleted.py new file mode 100644 index 00000000..0f1c36de --- /dev/null +++ b/src/workos/common/models/vault_kek_deleted.py @@ -0,0 +1,58 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .vault_kek_deleted_data import VaultKekDeletedData + + +@dataclass(slots=True) +class VaultKekDeleted: + """Vault Kek Deleted model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["vault.kek.deleted"] + data: "VaultKekDeletedData" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "VaultKekDeleted": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "vault.kek.deleted"), + data=VaultKekDeletedData.from_dict(cast(Dict[str, Any], data["data"])), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("VaultKekDeleted", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/vault_kek_deleted_data.py b/src/workos/common/models/vault_kek_deleted_data.py new file mode 100644 index 00000000..23a40507 --- /dev/null +++ b/src/workos/common/models/vault_kek_deleted_data.py @@ -0,0 +1,6 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .vault_kek_created_data import VaultKekCreatedData + +VaultKekDeletedData: TypeAlias = VaultKekCreatedData diff --git a/src/workos/common/models/vault_kek_deleted_data_actor_source.py b/src/workos/common/models/vault_kek_deleted_data_actor_source.py new file mode 100644 index 00000000..29c62e1e --- /dev/null +++ b/src/workos/common/models/vault_kek_deleted_data_actor_source.py @@ -0,0 +1,7 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .vault_data_created_data_actor_source import VaultDataCreatedDataActorSource + +VaultKekDeletedDataActorSource: TypeAlias = VaultDataCreatedDataActorSource +__all__ = ["VaultKekDeletedDataActorSource"] diff --git a/src/workos/connect/_resource.py b/src/workos/connect/_resource.py index 0e38c262..2cea71f8 100644 --- a/src/workos/connect/_resource.py +++ b/src/workos/connect/_resource.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( ApplicationCredentialsListItem, CreateM2MApplication, @@ -20,6 +20,7 @@ ) from workos.common.models.connect_application import ConnectApplication from workos.common.models.connect_application import ConnectApplicationVariant +from .models import ApplicationsRegistrationTypes from workos.common.models.pagination_order import PaginationOrder from .._pagination import AsyncPage, SyncPage @@ -96,6 +97,9 @@ def list_applications( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + registration_types: Optional[ + List[Union[ApplicationsRegistrationTypes, str]] + ] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[ConnectApplicationVariant]: @@ -108,6 +112,7 @@ def list_applications( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. + registration_types: Filter Connect Applications by registration type. Specify multiple as a comma-separated list (e.g. `registration_types=dynamic,authenticated`). Defaults to `authenticated` only when not specified. organization_id: Filter Connect Applications by organization ID. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -127,6 +132,9 @@ def list_applications( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "registration_types": ",".join(str(v) for v in registration_types) + if registration_types is not None + else None, "organization_id": organization_id, }.items() if v is not None @@ -287,9 +295,9 @@ def update_application( id: str, *, name: Optional[str] = None, - description: Optional[str] = None, - scopes: Optional[List[str]] = None, - redirect_uris: Optional[List[RedirectUriInput]] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + redirect_uris: Union[List[RedirectUriInput], None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ConnectApplicationVariant: """Update a Connect Application @@ -318,14 +326,19 @@ def update_application( k: v for k, v in { "name": name, - "description": description, - "scopes": scopes, - "redirect_uris": [item.to_dict() for item in redirect_uris] - if redirect_uris is not None - else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes + if not isinstance(redirect_uris, NotGiven): + body["redirect_uris"] = ( + [item.to_dict() for item in redirect_uris] + if redirect_uris is not None + else None + ) return cast( ConnectApplicationVariant, self._client.request( @@ -528,6 +541,9 @@ async def list_applications( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + registration_types: Optional[ + List[Union[ApplicationsRegistrationTypes, str]] + ] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[ConnectApplicationVariant]: @@ -540,6 +556,7 @@ async def list_applications( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. + registration_types: Filter Connect Applications by registration type. Specify multiple as a comma-separated list (e.g. `registration_types=dynamic,authenticated`). Defaults to `authenticated` only when not specified. organization_id: Filter Connect Applications by organization ID. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -559,6 +576,9 @@ async def list_applications( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "registration_types": ",".join(str(v) for v in registration_types) + if registration_types is not None + else None, "organization_id": organization_id, }.items() if v is not None @@ -719,9 +739,9 @@ async def update_application( id: str, *, name: Optional[str] = None, - description: Optional[str] = None, - scopes: Optional[List[str]] = None, - redirect_uris: Optional[List[RedirectUriInput]] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + redirect_uris: Union[List[RedirectUriInput], None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ConnectApplicationVariant: """Update a Connect Application @@ -750,14 +770,19 @@ async def update_application( k: v for k, v in { "name": name, - "description": description, - "scopes": scopes, - "redirect_uris": [item.to_dict() for item in redirect_uris] - if redirect_uris is not None - else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes + if not isinstance(redirect_uris, NotGiven): + body["redirect_uris"] = ( + [item.to_dict() for item in redirect_uris] + if redirect_uris is not None + else None + ) return cast( ConnectApplicationVariant, await self._client.request( diff --git a/src/workos/connect/models/__init__.py b/src/workos/connect/models/__init__.py index 46445679..7aa852b4 100644 --- a/src/workos/connect/models/__init__.py +++ b/src/workos/connect/models/__init__.py @@ -3,6 +3,9 @@ from .application_credentials_list_item import ( ApplicationCredentialsListItem as ApplicationCredentialsListItem, ) +from .applications_registration_types import ( + ApplicationsRegistrationTypes as ApplicationsRegistrationTypes, +) from workos.common.models.connect_application import ( ConnectApplication as ConnectApplication, ) diff --git a/src/workos/connect/models/applications_registration_types.py b/src/workos/connect/models/applications_registration_types.py new file mode 100644 index 00000000..b7f239e0 --- /dev/null +++ b/src/workos/connect/models/applications_registration_types.py @@ -0,0 +1,28 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of applications registration types values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class ApplicationsRegistrationTypes(str, Enum): + """Known values for ApplicationsRegistrationTypes.""" + + DYNAMIC = "dynamic" + AUTHENTICATED = "authenticated" + + @classmethod + def _missing_(cls, value: object) -> Optional["ApplicationsRegistrationTypes"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +ApplicationsRegistrationTypesLiteral: TypeAlias = Literal["dynamic", "authenticated"] diff --git a/src/workos/directory_sync/_resource.py b/src/workos/directory_sync/_resource.py index 1227b8df..c994f751 100644 --- a/src/workos/directory_sync/_resource.py +++ b/src/workos/directory_sync/_resource.py @@ -229,6 +229,8 @@ def list_users( order: Optional[Union[PaginationOrder, str]] = "desc", directory: Optional[str] = None, group: Optional[str] = None, + idp_id: Optional[str] = None, + email: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[DirectoryUserWithGroups]: """List Directory Users @@ -242,6 +244,8 @@ def list_users( order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. directory: Unique identifier of the WorkOS Directory. This value can be obtained from the WorkOS dashboard or from the WorkOS API. group: Unique identifier of the WorkOS Directory Group. This value can be obtained from the WorkOS API. + idp_id: Filter Directory Users by the identity provider's unique identifier (`idp_id`). Requires the `directory` parameter to also be provided. + email: Filter Directory Users by their primary email address. Requires the `directory` parameter to also be provided. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -264,6 +268,8 @@ def list_users( "order": enum_value(order) if order is not None else None, "directory": directory, "group": group, + "idp_id": idp_id, + "email": email, }.items() if v is not None } @@ -522,6 +528,8 @@ async def list_users( order: Optional[Union[PaginationOrder, str]] = "desc", directory: Optional[str] = None, group: Optional[str] = None, + idp_id: Optional[str] = None, + email: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[DirectoryUserWithGroups]: """List Directory Users @@ -535,6 +543,8 @@ async def list_users( order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. directory: Unique identifier of the WorkOS Directory. This value can be obtained from the WorkOS dashboard or from the WorkOS API. group: Unique identifier of the WorkOS Directory Group. This value can be obtained from the WorkOS API. + idp_id: Filter Directory Users by the identity provider's unique identifier (`idp_id`). Requires the `directory` parameter to also be provided. + email: Filter Directory Users by their primary email address. Requires the `directory` parameter to also be provided. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -557,6 +567,8 @@ async def list_users( "order": enum_value(order) if order is not None else None, "directory": directory, "group": group, + "idp_id": idp_id, + "email": email, }.items() if v is not None } diff --git a/src/workos/events/models/event_schema.py b/src/workos/events/models/event_schema.py index f95c895d..736902f0 100644 --- a/src/workos/events/models/event_schema.py +++ b/src/workos/events/models/event_schema.py @@ -10,6 +10,22 @@ from workos.common.models.action_user_registration_denied import ( ActionUserRegistrationDenied, ) +from workos.common.models.agent_registration_claim_attempt_created import ( + AgentRegistrationClaimAttemptCreated, +) +from workos.common.models.agent_registration_claim_completed import ( + AgentRegistrationClaimCompleted, +) +from workos.common.models.agent_registration_created import AgentRegistrationCreated +from workos.common.models.agent_registration_credential_issued import ( + AgentRegistrationCredentialIssued, +) +from workos.common.models.agent_registration_deleted import AgentRegistrationDeleted +from workos.common.models.agent_registration_expired import AgentRegistrationExpired +from workos.common.models.agent_registration_organization_switched import ( + AgentRegistrationOrganizationSwitched, +) +from workos.common.models.agent_registration_revoked import AgentRegistrationRevoked from workos.common.models.api_key_created import ApiKeyCreated from workos.common.models.api_key_revoked import ApiKeyRevoked from workos.common.models.api_key_updated import ApiKeyUpdated @@ -46,6 +62,9 @@ from workos.common.models.authentication_radar_risk_detected import ( AuthenticationRadarRiskDetected, ) +from workos.common.models.authentication_reauthentication_succeeded import ( + AuthenticationReauthenticationSucceeded, +) from workos.common.models.authentication_sso_failed import AuthenticationSSOFailed from workos.common.models.authentication_sso_started import AuthenticationSSOStarted from workos.common.models.authentication_sso_succeeded import AuthenticationSSOSucceeded @@ -116,12 +135,16 @@ from workos.common.models.pipes_connected_account_connected import ( PipesConnectedAccountConnected, ) +from workos.common.models.pipes_connected_account_connection_failed import ( + PipesConnectedAccountConnectionFailed, +) from workos.common.models.pipes_connected_account_disconnected import ( PipesConnectedAccountDisconnected, ) from workos.common.models.pipes_connected_account_reauthorization_needed import ( PipesConnectedAccountReauthorizationNeeded, ) +from workos.common.models.radar_challenge_created import RadarChallengeCreated from workos.common.models.role_created import RoleCreated from workos.common.models.role_deleted import RoleDeleted from workos.common.models.role_updated import RoleUpdated @@ -141,6 +164,7 @@ from workos.common.models.vault_dek_decrypted import VaultDekDecrypted from workos.common.models.vault_dek_read import VaultDekRead from workos.common.models.vault_kek_created import VaultKekCreated +from workos.common.models.vault_kek_deleted import VaultKekDeleted from workos.common.models.vault_metadata_read import VaultMetadataRead from workos.common.models.vault_names_listed import VaultNamesListed from workos.common.models.waitlist_user_approved import WaitlistUserApproved @@ -168,6 +192,14 @@ def to_dict(self) -> Dict[str, Any]: EventSchemaVariant = Union[ ActionAuthenticationDenied, ActionUserRegistrationDenied, + AgentRegistrationClaimAttemptCreated, + AgentRegistrationClaimCompleted, + AgentRegistrationCreated, + AgentRegistrationCredentialIssued, + AgentRegistrationDeleted, + AgentRegistrationExpired, + AgentRegistrationOrganizationSwitched, + AgentRegistrationRevoked, ApiKeyCreated, ApiKeyRevoked, ApiKeyUpdated, @@ -184,6 +216,7 @@ def to_dict(self) -> Dict[str, Any]: AuthenticationPasswordFailed, AuthenticationPasswordSucceeded, AuthenticationRadarRiskDetected, + AuthenticationReauthenticationSucceeded, AuthenticationSSOFailed, AuthenticationSSOStarted, AuthenticationSSOSucceeded, @@ -240,8 +273,10 @@ def to_dict(self) -> Dict[str, Any]: PermissionDeleted, PermissionUpdated, PipesConnectedAccountConnected, + PipesConnectedAccountConnectionFailed, PipesConnectedAccountDisconnected, PipesConnectedAccountReauthorizationNeeded, + RadarChallengeCreated, RoleCreated, RoleDeleted, RoleUpdated, @@ -259,6 +294,7 @@ def to_dict(self) -> Dict[str, Any]: VaultDekDecrypted, VaultDekRead, VaultKekCreated, + VaultKekDeleted, VaultMetadataRead, VaultNamesListed, WaitlistUserApproved, @@ -274,6 +310,14 @@ class EventSchema: _DISPATCH: ClassVar[Dict[str, type]] = { "action.authentication.denied": ActionAuthenticationDenied, "action.user_registration.denied": ActionUserRegistrationDenied, + "agent.registration.claim.attempt.created": AgentRegistrationClaimAttemptCreated, + "agent.registration.claim.completed": AgentRegistrationClaimCompleted, + "agent.registration.created": AgentRegistrationCreated, + "agent.registration.credential.issued": AgentRegistrationCredentialIssued, + "agent.registration.deleted": AgentRegistrationDeleted, + "agent.registration.expired": AgentRegistrationExpired, + "agent.registration.organization.switched": AgentRegistrationOrganizationSwitched, + "agent.registration.revoked": AgentRegistrationRevoked, "api_key.created": ApiKeyCreated, "api_key.revoked": ApiKeyRevoked, "api_key.updated": ApiKeyUpdated, @@ -290,6 +334,7 @@ class EventSchema: "authentication.password_failed": AuthenticationPasswordFailed, "authentication.password_succeeded": AuthenticationPasswordSucceeded, "authentication.radar_risk_detected": AuthenticationRadarRiskDetected, + "authentication.reauthentication_succeeded": AuthenticationReauthenticationSucceeded, "authentication.sso_failed": AuthenticationSSOFailed, "authentication.sso_started": AuthenticationSSOStarted, "authentication.sso_succeeded": AuthenticationSSOSucceeded, @@ -346,8 +391,10 @@ class EventSchema: "permission.deleted": PermissionDeleted, "permission.updated": PermissionUpdated, "pipes.connected_account.connected": PipesConnectedAccountConnected, + "pipes.connected_account.connection_failed": PipesConnectedAccountConnectionFailed, "pipes.connected_account.disconnected": PipesConnectedAccountDisconnected, "pipes.connected_account.reauthorization_needed": PipesConnectedAccountReauthorizationNeeded, + "radar.challenge_created": RadarChallengeCreated, "role.created": RoleCreated, "role.deleted": RoleDeleted, "role.updated": RoleUpdated, @@ -365,6 +412,7 @@ class EventSchema: "vault.dek.decrypted": VaultDekDecrypted, "vault.dek.read": VaultDekRead, "vault.kek.created": VaultKekCreated, + "vault.kek.deleted": VaultKekDeleted, "vault.metadata.read": VaultMetadataRead, "vault.names.listed": VaultNamesListed, "waitlist_user.approved": WaitlistUserApproved, diff --git a/src/workos/groups/_resource.py b/src/workos/groups/_resource.py index 95440ff6..4cda1eab 100644 --- a/src/workos/groups/_resource.py +++ b/src/workos/groups/_resource.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from workos.common.models.group import Group from workos.common.models.user_organization_membership_base_list_data import ( UserOrganizationMembershipBaseListData, @@ -77,7 +77,7 @@ def create_organization_group( organization_id: str, *, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Group: """Create a group @@ -103,13 +103,10 @@ def create_organization_group( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "name": name, - "description": description, - }.items() - if v is not None + "name": name, } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="post", path=("organizations", str(organization_id), "groups"), @@ -157,7 +154,7 @@ def update_organization_group( group_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Group: """Update a group @@ -187,10 +184,11 @@ def update_organization_group( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return self._client.request( method="patch", path=("organizations", str(organization_id), "groups", str(group_id)), @@ -433,7 +431,7 @@ async def create_organization_group( organization_id: str, *, name: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Group: """Create a group @@ -459,13 +457,10 @@ async def create_organization_group( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "name": name, - "description": description, - }.items() - if v is not None + "name": name, } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="post", path=("organizations", str(organization_id), "groups"), @@ -513,7 +508,7 @@ async def update_organization_group( group_id: str, *, name: Optional[str] = None, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Group: """Update a group @@ -543,10 +538,11 @@ async def update_organization_group( k: v for k, v in { "name": name, - "description": description, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description return await self._client.request( method="patch", path=("organizations", str(organization_id), "groups", str(group_id)), diff --git a/src/workos/organization_domains/_resource.py b/src/workos/organization_domains/_resource.py index 19d1ba0c..7639d8df 100644 --- a/src/workos/organization_domains/_resource.py +++ b/src/workos/organization_domains/_resource.py @@ -8,7 +8,6 @@ from .._client import AsyncWorkOSClient, WorkOSClient from .._types import RequestOptions -from .models import OrganizationDomainStandAlone from workos.common.models.organization_domain import OrganizationDomain @@ -60,7 +59,7 @@ def get_organization_domain( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> OrganizationDomainStandAlone: + ) -> OrganizationDomain: """Get an Organization Domain Get the details of an existing organization domain. @@ -70,7 +69,7 @@ def get_organization_domain( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - OrganizationDomainStandAlone + OrganizationDomain Raises: NotFoundError: If the resource is not found (404). @@ -81,7 +80,7 @@ def get_organization_domain( return self._client.request( method="get", path=("organization_domains", str(id)), - model=OrganizationDomainStandAlone, + model=OrganizationDomain, request_options=request_options, ) @@ -116,7 +115,7 @@ def verify_organization_domain( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> OrganizationDomainStandAlone: + ) -> OrganizationDomain: """Verify an Organization Domain Initiates verification process for an Organization Domain. @@ -126,7 +125,7 @@ def verify_organization_domain( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - OrganizationDomainStandAlone + OrganizationDomain Raises: BadRequestError: If the request is malformed (400). @@ -137,7 +136,7 @@ def verify_organization_domain( return self._client.request( method="post", path=("organization_domains", str(id), "verify"), - model=OrganizationDomainStandAlone, + model=OrganizationDomain, request_options=request_options, ) @@ -190,7 +189,7 @@ async def get_organization_domain( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> OrganizationDomainStandAlone: + ) -> OrganizationDomain: """Get an Organization Domain Get the details of an existing organization domain. @@ -200,7 +199,7 @@ async def get_organization_domain( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - OrganizationDomainStandAlone + OrganizationDomain Raises: NotFoundError: If the resource is not found (404). @@ -211,7 +210,7 @@ async def get_organization_domain( return await self._client.request( method="get", path=("organization_domains", str(id)), - model=OrganizationDomainStandAlone, + model=OrganizationDomain, request_options=request_options, ) @@ -246,7 +245,7 @@ async def verify_organization_domain( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> OrganizationDomainStandAlone: + ) -> OrganizationDomain: """Verify an Organization Domain Initiates verification process for an Organization Domain. @@ -256,7 +255,7 @@ async def verify_organization_domain( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - OrganizationDomainStandAlone + OrganizationDomain Raises: BadRequestError: If the request is malformed (400). @@ -267,6 +266,6 @@ async def verify_organization_domain( return await self._client.request( method="post", path=("organization_domains", str(id), "verify"), - model=OrganizationDomainStandAlone, + model=OrganizationDomain, request_options=request_options, ) diff --git a/src/workos/organizations/_resource.py b/src/workos/organizations/_resource.py index 43c7ccf4..90e22331 100644 --- a/src/workos/organizations/_resource.py +++ b/src/workos/organizations/_resource.py @@ -7,8 +7,13 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value -from .models import AuditLogConfiguration, Organization, OrganizationDomainData +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven +from .models import ( + AuditLogConfiguration, + Organization, + OrganizationAuthorizedConnectApplicationListData, + OrganizationDomainData, +) from workos.common.models.pagination_order import PaginationOrder from .._pagination import AsyncPage, SyncPage @@ -81,8 +86,8 @@ def create_organization( allow_profiles_outside_organization: Optional[bool] = None, domains: Optional[List[str]] = None, domain_data: Optional[List[OrganizationDomainData]] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Organization: """Create an Organization @@ -118,11 +123,13 @@ def create_organization( "domain_data": [item.to_dict() for item in domain_data] if domain_data is not None else None, - "metadata": metadata, - "external_id": external_id, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id return self._client.request( method="post", path=("organizations",), @@ -200,8 +207,8 @@ def update_organization( domains: Optional[List[str]] = None, domain_data: Optional[List[OrganizationDomainData]] = None, stripe_customer_id: Optional[str] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Organization: """Update an Organization @@ -242,11 +249,13 @@ def update_organization( if domain_data is not None else None, "stripe_customer_id": stripe_customer_id, - "metadata": metadata, - "external_id": external_id, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id return self._client.request( method="put", path=("organizations", str(id)), @@ -311,6 +320,56 @@ def get_audit_log_configuration( request_options=request_options, ) + def list_authorized_applications( + self, + organization_id: str, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + request_options: Optional[RequestOptions] = None, + ) -> SyncPage[OrganizationAuthorizedConnectApplicationListData]: + """List authorized applications + + Get a list of all Connect applications that users in the organization have authorized. + + Args: + organization_id: The ID of the organization. + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + SyncPage[OrganizationAuthorizedConnectApplicationListData] + + Raises: + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + }.items() + if v is not None + } + return self._client.request_page( + method="get", + path=("organizations", str(organization_id), "authorized_applications"), + model=OrganizationAuthorizedConnectApplicationListData, + params=params, + request_options=request_options, + ) + class AsyncOrganizations: """Organizations API resources (async).""" @@ -380,8 +439,8 @@ async def create_organization( allow_profiles_outside_organization: Optional[bool] = None, domains: Optional[List[str]] = None, domain_data: Optional[List[OrganizationDomainData]] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Organization: """Create an Organization @@ -417,11 +476,13 @@ async def create_organization( "domain_data": [item.to_dict() for item in domain_data] if domain_data is not None else None, - "metadata": metadata, - "external_id": external_id, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id return await self._client.request( method="post", path=("organizations",), @@ -499,8 +560,8 @@ async def update_organization( domains: Optional[List[str]] = None, domain_data: Optional[List[OrganizationDomainData]] = None, stripe_customer_id: Optional[str] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> Organization: """Update an Organization @@ -541,11 +602,13 @@ async def update_organization( if domain_data is not None else None, "stripe_customer_id": stripe_customer_id, - "metadata": metadata, - "external_id": external_id, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id return await self._client.request( method="put", path=("organizations", str(id)), @@ -609,3 +672,53 @@ async def get_audit_log_configuration( model=AuditLogConfiguration, request_options=request_options, ) + + async def list_authorized_applications( + self, + organization_id: str, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + request_options: Optional[RequestOptions] = None, + ) -> AsyncPage[OrganizationAuthorizedConnectApplicationListData]: + """List authorized applications + + Get a list of all Connect applications that users in the organization have authorized. + + Args: + organization_id: The ID of the organization. + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AsyncPage[OrganizationAuthorizedConnectApplicationListData] + + Raises: + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + }.items() + if v is not None + } + return await self._client.request_page( + method="get", + path=("organizations", str(organization_id), "authorized_applications"), + model=OrganizationAuthorizedConnectApplicationListData, + params=params, + request_options=request_options, + ) diff --git a/src/workos/organizations/models/__init__.py b/src/workos/organizations/models/__init__.py index 5cf3c16b..5533e02a 100644 --- a/src/workos/organizations/models/__init__.py +++ b/src/workos/organizations/models/__init__.py @@ -6,6 +6,9 @@ ) from .audit_logs_retention import AuditLogsRetention as AuditLogsRetention from .organization import Organization as Organization +from .organization_authorized_connect_application_list_data import ( + OrganizationAuthorizedConnectApplicationListData as OrganizationAuthorizedConnectApplicationListData, +) from .organization_domain_data import OrganizationDomainData as OrganizationDomainData from .organization_input import OrganizationInput as OrganizationInput from .update_audit_logs_retention import ( diff --git a/src/workos/organizations/models/organization_authorized_connect_application_list_data.py b/src/workos/organizations/models/organization_authorized_connect_application_list_data.py new file mode 100644 index 00000000..5bfeef20 --- /dev/null +++ b/src/workos/organizations/models/organization_authorized_connect_application_list_data.py @@ -0,0 +1,63 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, List, Literal, Optional +from workos._types import _raise_deserialize_error + +from workos.common.models.connect_application import ( + ConnectApplication, + ConnectApplicationVariant, +) + + +@dataclass(slots=True) +class OrganizationAuthorizedConnectApplicationListData: + """Organization Authorized Connect Application List Data model.""" + + object: Literal["authorized_connect_application"] + """Distinguishes the authorized connect application object.""" + id: str + """The unique ID of the authorized connect application.""" + granted_scopes: List[str] + """The scopes granted by the user to the application.""" + application: "ConnectApplicationVariant" + user_id: str + """The ID of the user who authorized the application.""" + oauth_resource: Optional[str] = None + """The OAuth resource associated with the authorized connect application, if one was requested.""" + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "OrganizationAuthorizedConnectApplicationListData": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "authorized_connect_application"), + id=data["id"], + granted_scopes=data["granted_scopes"], + application=ConnectApplication.from_dict( + cast(Dict[str, Any], data["application"]) + ), + user_id=data["user_id"], + oauth_resource=data.get("oauth_resource"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error( + "OrganizationAuthorizedConnectApplicationListData", e + ) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["granted_scopes"] = self.granted_scopes + result["application"] = self.application.to_dict() + result["user_id"] = self.user_id + if self.oauth_resource is not None: + result["oauth_resource"] = self.oauth_resource + return result diff --git a/src/workos/pipes/_resource.py b/src/workos/pipes/_resource.py index 98812210..49733025 100644 --- a/src/workos/pipes/_resource.py +++ b/src/workos/pipes/_resource.py @@ -7,19 +7,25 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( + ApiKeyInstallation, CustomProviderDefinition, DataIntegration, DataIntegrationAccessTokenResponse, DataIntegrationAuthorizeUrlResponse, - DataIntegrationCredentialsDto, + DataIntegrationCredentialsInput, DataIntegrationCredentialsResponse, DataIntegrationsListResponse, UpdateCustomProviderDefinition, ) from workos.common.models.connected_account import ConnectedAccount -from workos.common.models.connected_account_state import ConnectedAccountState +from workos.common.models.connected_account_input_state import ( + ConnectedAccountInputState, +) +from workos.common.models.create_data_integration_auth_methods import ( + CreateDataIntegrationAuthMethods, +) from workos.common.models.pagination_order import PaginationOrder from .._pagination import AsyncPage, SyncPage @@ -41,7 +47,7 @@ def list_data_integrations( ) -> SyncPage[DataIntegration]: """List data integrations - Lists the environment's data integrations configured with `custom` or `organization` credentials, including custom providers. + Lists the environment's data integrations configured with `custom` or `organization` credentials, including custom providers and API key integrations. Args: limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. @@ -80,23 +86,29 @@ def create_data_integration( self, *, provider: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, - credentials: Optional[DataIntegrationCredentialsDto] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + auth_methods: Optional[ + List[Union[CreateDataIntegrationAuthMethods, str]] + ] = None, + credentials: Optional[DataIntegrationCredentialsInput] = None, + api_key: Optional[ApiKeyInstallation] = None, custom_provider: Optional[CustomProviderDefinition] = None, request_options: Optional[RequestOptions] = None, ) -> DataIntegration: """Create a data integration - Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials, or `organization` to have each organization supply its own. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition. + Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials or `organization` to have each organization supply its own. Set `auth_methods` to `["api_key"]` to create an API key integration; you may optionally supply an `api_key` block to install a first tenant in the same call. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition. Args: provider: The provider to create a Data Integration for. For a built-in provider use its slug (e.g. `github`, `slack`). For a custom provider, this is the new provider slug and `custom_provider` must be supplied. A custom provider slug cannot shadow an existing global provider slug. description: An optional description of the Data Integration. enabled: Whether the Data Integration is enabled. Defaults to `false`. scopes: The OAuth scopes to request for the Data Integration. Defaults to the provider's configured scopes when omitted. - credentials: The credentials to configure for the Data Integration. Required for both built-in and custom providers. + auth_methods: How accounts authenticate with the provider. Defaults to `["oauth"]`. Use `["api_key"]` to declare an API key integration; `credentials` is then not required and keys are supplied per-tenant (optionally via `api_key` on this request). + credentials: The OAuth credentials to configure for the Data Integration. Required for OAuth integrations; omit when `auth_methods` is `["api_key"]`. + api_key: An optional API key to install for the first tenant on an `api_key` integration. Omit to declare a keyless integration; tenants can be added later via the per-installation API key path. custom_provider: The OAuth definition for a custom provider. Supply this to define a custom provider; omit it to create an integration for a built-in provider. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -106,7 +118,9 @@ def create_data_integration( Raises: BadRequestError: If the request is malformed (400). AuthenticationError: If the API key is invalid (401). + AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). UnprocessableEntityError: If the request data is unprocessable (422). RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. @@ -115,18 +129,22 @@ def create_data_integration( k: v for k, v in { "provider": provider, - "description": description, "enabled": enabled, - "scopes": scopes, + "auth_methods": auth_methods, "credentials": credentials.to_dict() if credentials is not None else None, + "api_key": api_key.to_dict() if api_key is not None else None, "custom_provider": custom_provider.to_dict() if custom_provider is not None else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return self._client.request( method="post", path=("data-integrations",), @@ -169,10 +187,11 @@ def update_data_integration( self, slug: str, *, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, - credentials: Optional[DataIntegrationCredentialsDto] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + credentials: Optional[DataIntegrationCredentialsInput] = None, + api_key: Optional[ApiKeyInstallation] = None, custom_provider: Optional[UpdateCustomProviderDefinition] = None, request_options: Optional[RequestOptions] = None, ) -> DataIntegration: @@ -185,7 +204,8 @@ def update_data_integration( description: An optional description of the Data Integration. enabled: Whether the Data Integration is enabled. scopes: The OAuth scopes to request for the Data Integration. Pass `null` to reset to the provider's configured scopes. - credentials: New credentials for the Data Integration. When provided, rotates the stored client secret. + credentials: New OAuth credentials for the Data Integration. When provided, rotates the stored client secret. Mutually exclusive with `api_key`. + api_key: An API key to install or rotate for a tenant on an `api_key` integration. Upserts the tenant installation identified by `user_id` (and optional `organization_id`). custom_provider: Updates to a custom provider's OAuth definition. Only valid for custom-provider integrations. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -195,6 +215,7 @@ def update_data_integration( Raises: BadRequestError: If the request is malformed (400). AuthenticationError: If the API key is invalid (401). + AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). UnprocessableEntityError: If the request data is unprocessable (422). RateLimitExceededError: If rate limited (429). @@ -203,18 +224,21 @@ def update_data_integration( body: Dict[str, Any] = { k: v for k, v in { - "description": description, "enabled": enabled, - "scopes": scopes, "credentials": credentials.to_dict() if credentials is not None else None, + "api_key": api_key.to_dict() if api_key is not None else None, "custom_provider": custom_provider.to_dict() if custom_provider is not None else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return self._client.request( method="put", path=("data-integrations", str(slug)), @@ -395,7 +419,7 @@ def get_access_token( provider: str, *, user_id: str, - organization_id: Optional[str] = None, + organization_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> DataIntegrationAccessTokenResponse: """Get an access token for a connected account @@ -420,13 +444,10 @@ def get_access_token( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "user_id": user_id, - "organization_id": organization_id, - }.items() - if v is not None + "user_id": user_id, } + if not isinstance(organization_id, NotGiven): + body["organization_id"] = organization_id return self._client.request( method="post", path=("data-integrations", str(provider), "token"), @@ -492,7 +513,7 @@ def create_user_connected_account( refresh_token: Optional[str] = None, expires_at: Optional[str] = None, scopes: Optional[List[str]] = None, - state: Optional[Union[ConnectedAccountState, str]] = None, + state: Optional[Union[ConnectedAccountInputState, str]] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> ConnectedAccount: @@ -564,7 +585,7 @@ def update_user_connected_account( refresh_token: Optional[str] = None, expires_at: Optional[str] = None, scopes: Optional[List[str]] = None, - state: Optional[Union[ConnectedAccountState, str]] = None, + state: Optional[Union[ConnectedAccountInputState, str]] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> ConnectedAccount: @@ -727,7 +748,7 @@ async def list_data_integrations( ) -> AsyncPage[DataIntegration]: """List data integrations - Lists the environment's data integrations configured with `custom` or `organization` credentials, including custom providers. + Lists the environment's data integrations configured with `custom` or `organization` credentials, including custom providers and API key integrations. Args: limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. @@ -766,23 +787,29 @@ async def create_data_integration( self, *, provider: str, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, - credentials: Optional[DataIntegrationCredentialsDto] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + auth_methods: Optional[ + List[Union[CreateDataIntegrationAuthMethods, str]] + ] = None, + credentials: Optional[DataIntegrationCredentialsInput] = None, + api_key: Optional[ApiKeyInstallation] = None, custom_provider: Optional[CustomProviderDefinition] = None, request_options: Optional[RequestOptions] = None, ) -> DataIntegration: """Create a data integration - Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials, or `organization` to have each organization supply its own. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition. + Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials or `organization` to have each organization supply its own. Set `auth_methods` to `["api_key"]` to create an API key integration; you may optionally supply an `api_key` block to install a first tenant in the same call. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition. Args: provider: The provider to create a Data Integration for. For a built-in provider use its slug (e.g. `github`, `slack`). For a custom provider, this is the new provider slug and `custom_provider` must be supplied. A custom provider slug cannot shadow an existing global provider slug. description: An optional description of the Data Integration. enabled: Whether the Data Integration is enabled. Defaults to `false`. scopes: The OAuth scopes to request for the Data Integration. Defaults to the provider's configured scopes when omitted. - credentials: The credentials to configure for the Data Integration. Required for both built-in and custom providers. + auth_methods: How accounts authenticate with the provider. Defaults to `["oauth"]`. Use `["api_key"]` to declare an API key integration; `credentials` is then not required and keys are supplied per-tenant (optionally via `api_key` on this request). + credentials: The OAuth credentials to configure for the Data Integration. Required for OAuth integrations; omit when `auth_methods` is `["api_key"]`. + api_key: An optional API key to install for the first tenant on an `api_key` integration. Omit to declare a keyless integration; tenants can be added later via the per-installation API key path. custom_provider: The OAuth definition for a custom provider. Supply this to define a custom provider; omit it to create an integration for a built-in provider. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -792,7 +819,9 @@ async def create_data_integration( Raises: BadRequestError: If the request is malformed (400). AuthenticationError: If the API key is invalid (401). + AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). UnprocessableEntityError: If the request data is unprocessable (422). RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. @@ -801,18 +830,22 @@ async def create_data_integration( k: v for k, v in { "provider": provider, - "description": description, "enabled": enabled, - "scopes": scopes, + "auth_methods": auth_methods, "credentials": credentials.to_dict() if credentials is not None else None, + "api_key": api_key.to_dict() if api_key is not None else None, "custom_provider": custom_provider.to_dict() if custom_provider is not None else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return await self._client.request( method="post", path=("data-integrations",), @@ -855,10 +888,11 @@ async def update_data_integration( self, slug: str, *, - description: Optional[str] = None, + description: Union[str, None, NotGiven] = NOT_GIVEN, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, - credentials: Optional[DataIntegrationCredentialsDto] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, + credentials: Optional[DataIntegrationCredentialsInput] = None, + api_key: Optional[ApiKeyInstallation] = None, custom_provider: Optional[UpdateCustomProviderDefinition] = None, request_options: Optional[RequestOptions] = None, ) -> DataIntegration: @@ -871,7 +905,8 @@ async def update_data_integration( description: An optional description of the Data Integration. enabled: Whether the Data Integration is enabled. scopes: The OAuth scopes to request for the Data Integration. Pass `null` to reset to the provider's configured scopes. - credentials: New credentials for the Data Integration. When provided, rotates the stored client secret. + credentials: New OAuth credentials for the Data Integration. When provided, rotates the stored client secret. Mutually exclusive with `api_key`. + api_key: An API key to install or rotate for a tenant on an `api_key` integration. Upserts the tenant installation identified by `user_id` (and optional `organization_id`). custom_provider: Updates to a custom provider's OAuth definition. Only valid for custom-provider integrations. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -881,6 +916,7 @@ async def update_data_integration( Raises: BadRequestError: If the request is malformed (400). AuthenticationError: If the API key is invalid (401). + AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). UnprocessableEntityError: If the request data is unprocessable (422). RateLimitExceededError: If rate limited (429). @@ -889,18 +925,21 @@ async def update_data_integration( body: Dict[str, Any] = { k: v for k, v in { - "description": description, "enabled": enabled, - "scopes": scopes, "credentials": credentials.to_dict() if credentials is not None else None, + "api_key": api_key.to_dict() if api_key is not None else None, "custom_provider": custom_provider.to_dict() if custom_provider is not None else None, }.items() if v is not None } + if not isinstance(description, NotGiven): + body["description"] = description + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return await self._client.request( method="put", path=("data-integrations", str(slug)), @@ -1081,7 +1120,7 @@ async def get_access_token( provider: str, *, user_id: str, - organization_id: Optional[str] = None, + organization_id: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> DataIntegrationAccessTokenResponse: """Get an access token for a connected account @@ -1106,13 +1145,10 @@ async def get_access_token( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "user_id": user_id, - "organization_id": organization_id, - }.items() - if v is not None + "user_id": user_id, } + if not isinstance(organization_id, NotGiven): + body["organization_id"] = organization_id return await self._client.request( method="post", path=("data-integrations", str(provider), "token"), @@ -1178,7 +1214,7 @@ async def create_user_connected_account( refresh_token: Optional[str] = None, expires_at: Optional[str] = None, scopes: Optional[List[str]] = None, - state: Optional[Union[ConnectedAccountState, str]] = None, + state: Optional[Union[ConnectedAccountInputState, str]] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> ConnectedAccount: @@ -1250,7 +1286,7 @@ async def update_user_connected_account( refresh_token: Optional[str] = None, expires_at: Optional[str] = None, scopes: Optional[List[str]] = None, - state: Optional[Union[ConnectedAccountState, str]] = None, + state: Optional[Union[ConnectedAccountInputState, str]] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> ConnectedAccount: diff --git a/src/workos/pipes/models/__init__.py b/src/workos/pipes/models/__init__.py index b27bad02..70e054f6 100644 --- a/src/workos/pipes/models/__init__.py +++ b/src/workos/pipes/models/__init__.py @@ -1,8 +1,10 @@ # This file is auto-generated by oagen. Do not edit. +from .api_key_installation import ApiKeyInstallation as ApiKeyInstallation from .connected_account import * # noqa: F401,F403 from .connected_account_dto import * # noqa: F401,F403 from workos.common.models.connected_account import ConnectedAccount as ConnectedAccount +from .connected_account_input import ConnectedAccountInput as ConnectedAccountInput from .create_data_integration import CreateDataIntegration as CreateDataIntegration from .custom_provider_definition import ( CustomProviderDefinition as CustomProviderDefinition, @@ -21,6 +23,9 @@ from .data_integration_credential import ( DataIntegrationCredential as DataIntegrationCredential, ) +from .data_integration_credentials_input import ( + DataIntegrationCredentialsInput as DataIntegrationCredentialsInput, +) from .data_integration_credentials_response import ( DataIntegrationCredentialsResponse as DataIntegrationCredentialsResponse, ) @@ -30,6 +35,9 @@ from .data_integration_custom_provider import ( DataIntegrationCustomProvider as DataIntegrationCustomProvider, ) +from .data_integration_installation import ( + DataIntegrationInstallation as DataIntegrationInstallation, +) from .data_integrations_get_data_integration_authorize_url_request import ( DataIntegrationsGetDataIntegrationAuthorizeUrlRequest as DataIntegrationsGetDataIntegrationAuthorizeUrlRequest, ) diff --git a/src/workos/pipes/models/api_key_installation.py b/src/workos/pipes/models/api_key_installation.py new file mode 100644 index 00000000..05b9c32e --- /dev/null +++ b/src/workos/pipes/models/api_key_installation.py @@ -0,0 +1,8 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .data_integrations_upsert_api_key_request import ( + DataIntegrationsUpsertApiKeyRequest, +) + +ApiKeyInstallation: TypeAlias = DataIntegrationsUpsertApiKeyRequest diff --git a/src/workos/pipes/models/connected_account_input.py b/src/workos/pipes/models/connected_account_input.py new file mode 100644 index 00000000..b33d8239 --- /dev/null +++ b/src/workos/pipes/models/connected_account_input.py @@ -0,0 +1,64 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Any, Dict, List, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime +from workos.common.models.connected_account_input_state import ( + ConnectedAccountInputState, +) + + +@dataclass(slots=True) +class ConnectedAccountInput: + """Connected Account Input model.""" + + access_token: Optional[str] = None + """The OAuth access token for the connected account.""" + refresh_token: Optional[str] = None + """The OAuth refresh token for the connected account.""" + expires_at: Optional[datetime] = None + """The ISO-8601 timestamp when the access token expires. Required when `access_token` is provided for tokens that expire.""" + scopes: Optional[List[str]] = None + """The OAuth scopes granted for this connection.""" + state: Optional["ConnectedAccountInputState"] = None + """Explicitly set the state of the connected account. When omitted, the state is derived from the token combination provided.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ConnectedAccountInput": + """Deserialize from a dictionary.""" + try: + return cls( + access_token=data.get("access_token"), + refresh_token=data.get("refresh_token"), + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data.get("expires_at")) is not None + else None, + scopes=data.get("scopes"), + state=ConnectedAccountInputState(_v_state) + if (_v_state := data.get("state")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ConnectedAccountInput", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + if self.access_token is not None: + result["access_token"] = self.access_token + if self.refresh_token is not None: + result["refresh_token"] = self.refresh_token + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + if self.scopes is not None: + result["scopes"] = self.scopes + if self.state is not None: + result["state"] = ( + self.state.value if isinstance(self.state, Enum) else self.state + ) + return result diff --git a/src/workos/pipes/models/create_data_integration.py b/src/workos/pipes/models/create_data_integration.py index 2a4e0d00..5c3736d4 100644 --- a/src/workos/pipes/models/create_data_integration.py +++ b/src/workos/pipes/models/create_data_integration.py @@ -3,12 +3,17 @@ from __future__ import annotations from dataclasses import dataclass +from enum import Enum from typing import cast from typing import Any, Dict, List, Optional from workos._types import _raise_deserialize_error +from .api_key_installation import ApiKeyInstallation from .custom_provider_definition import CustomProviderDefinition -from .data_integration_credentials_dto import DataIntegrationCredentialsDto +from .data_integration_credentials_input import DataIntegrationCredentialsInput +from workos.common.models.create_data_integration_auth_methods import ( + CreateDataIntegrationAuthMethods, +) @dataclass(slots=True) @@ -23,8 +28,12 @@ class CreateDataIntegration: """Whether the Data Integration is enabled. Defaults to `false`.""" scopes: Optional[List[str]] = None """The OAuth scopes to request for the Data Integration. Defaults to the provider's configured scopes when omitted.""" - credentials: Optional["DataIntegrationCredentialsDto"] = None - """The credentials to configure for the Data Integration. Required for both built-in and custom providers.""" + auth_methods: Optional[List["CreateDataIntegrationAuthMethods"]] = None + """How accounts authenticate with the provider. Defaults to `["oauth"]`. Use `["api_key"]` to declare an API key integration; `credentials` is then not required and keys are supplied per-tenant (optionally via `api_key` on this request).""" + credentials: Optional["DataIntegrationCredentialsInput"] = None + """The OAuth credentials to configure for the Data Integration. Required for OAuth integrations; omit when `auth_methods` is `["api_key"]`.""" + api_key: Optional["ApiKeyInstallation"] = None + """An optional API key to install for the first tenant on an `api_key` integration. Omit to declare a keyless integration; tenants can be added later via the per-installation API key path.""" custom_provider: Optional["CustomProviderDefinition"] = None """The OAuth definition for a custom provider. Supply this to define a custom provider; omit it to create an integration for a built-in provider.""" @@ -37,11 +46,20 @@ def from_dict(cls, data: Dict[str, Any]) -> "CreateDataIntegration": description=data.get("description"), enabled=data.get("enabled"), scopes=data.get("scopes"), - credentials=DataIntegrationCredentialsDto.from_dict( + auth_methods=[ + CreateDataIntegrationAuthMethods(item) + for item in cast(list[Any], _v_auth_methods) + ] + if (_v_auth_methods := data.get("auth_methods")) is not None + else None, + credentials=DataIntegrationCredentialsInput.from_dict( cast(Dict[str, Any], _v_credentials) ) if (_v_credentials := data.get("credentials")) is not None else None, + api_key=ApiKeyInstallation.from_dict(cast(Dict[str, Any], _v_api_key)) + if (_v_api_key := data.get("api_key")) is not None + else None, custom_provider=CustomProviderDefinition.from_dict( cast(Dict[str, Any], _v_custom_provider) ) @@ -65,8 +83,15 @@ def to_dict(self) -> Dict[str, Any]: result["scopes"] = self.scopes else: result["scopes"] = None + if self.auth_methods is not None: + result["auth_methods"] = [ + item.value if isinstance(item, Enum) else item + for item in self.auth_methods + ] if self.credentials is not None: result["credentials"] = self.credentials.to_dict() + if self.api_key is not None: + result["api_key"] = self.api_key.to_dict() if self.custom_provider is not None: result["custom_provider"] = self.custom_provider.to_dict() return result diff --git a/src/workos/pipes/models/data_integration.py b/src/workos/pipes/models/data_integration.py index 3ea6db62..7f4514f4 100644 --- a/src/workos/pipes/models/data_integration.py +++ b/src/workos/pipes/models/data_integration.py @@ -12,6 +12,10 @@ from .data_integration_credential import DataIntegrationCredential from .data_integration_custom_provider import DataIntegrationCustomProvider +from .data_integration_installation import DataIntegrationInstallation +from workos.common.models.data_integration_auth_methods import ( + DataIntegrationAuthMethods, +) from workos.common.models.data_integration_state import DataIntegrationState @@ -37,8 +41,12 @@ class DataIntegration: """The OAuth scopes configured for the Data Integration. `null` when the provider's configured scopes are used.""" redirect_uri: str """The OAuth redirect URI to register with the provider when configuring the custom application.""" + auth_methods: List["DataIntegrationAuthMethods"] + """How accounts authenticate with the provider for this Data Integration.""" credentials: "DataIntegrationCredential" """The credentials configured for the Data Integration.""" + installation: Optional["DataIntegrationInstallation"] + """The tenant installation created when an API key was supplied at creation time; `null` otherwise. Not populated on list/get responses.""" custom_provider: Optional["DataIntegrationCustomProvider"] """The OAuth definition when this is a custom provider; `null` for built-in providers.""" created_at: datetime @@ -60,9 +68,18 @@ def from_dict(cls, data: Dict[str, Any]) -> "DataIntegration": state=DataIntegrationState(data["state"]), scopes=data["scopes"], redirect_uri=data["redirect_uri"], + auth_methods=[ + DataIntegrationAuthMethods(item) + for item in cast(list[Any], data["auth_methods"]) + ], credentials=DataIntegrationCredential.from_dict( cast(Dict[str, Any], data["credentials"]) ), + installation=DataIntegrationInstallation.from_dict( + cast(Dict[str, Any], _v_installation) + ) + if (_v_installation := data["installation"]) is not None + else None, custom_provider=DataIntegrationCustomProvider.from_dict( cast(Dict[str, Any], _v_custom_provider) ) @@ -94,7 +111,14 @@ def to_dict(self) -> Dict[str, Any]: else: result["scopes"] = None result["redirect_uri"] = self.redirect_uri + result["auth_methods"] = [ + item.value if isinstance(item, Enum) else item for item in self.auth_methods + ] result["credentials"] = self.credentials.to_dict() + if self.installation is not None: + result["installation"] = self.installation.to_dict() + else: + result["installation"] = None if self.custom_provider is not None: result["custom_provider"] = self.custom_provider.to_dict() else: diff --git a/src/workos/pipes/models/data_integration_credentials_input.py b/src/workos/pipes/models/data_integration_credentials_input.py new file mode 100644 index 00000000..c926c97f --- /dev/null +++ b/src/workos/pipes/models/data_integration_credentials_input.py @@ -0,0 +1,45 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos.common.models.data_integration_credentials_input_type import ( + DataIntegrationCredentialsInputType, +) + + +@dataclass(slots=True) +class DataIntegrationCredentialsInput: + """Data Integration Credentials Input model.""" + + type: "DataIntegrationCredentialsInputType" + """The credentials type. `custom` uses your own OAuth app credentials; `organization` has each organization supply its own credentials (configured per-organization).""" + client_id: Optional[str] = None + """OAuth client ID for the provider app. Required when `type` is `custom`; omit for `organization`.""" + client_secret: Optional[str] = None + """OAuth client secret for the provider app. Required when `type` is `custom`; omit for `organization`.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "DataIntegrationCredentialsInput": + """Deserialize from a dictionary.""" + try: + return cls( + type=DataIntegrationCredentialsInputType(data["type"]), + client_id=data.get("client_id"), + client_secret=data.get("client_secret"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("DataIntegrationCredentialsInput", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type.value if isinstance(self.type, Enum) else self.type + if self.client_id is not None: + result["client_id"] = self.client_id + if self.client_secret is not None: + result["client_secret"] = self.client_secret + return result diff --git a/src/workos/pipes/models/data_integration_installation.py b/src/workos/pipes/models/data_integration_installation.py new file mode 100644 index 00000000..4a81cf39 --- /dev/null +++ b/src/workos/pipes/models/data_integration_installation.py @@ -0,0 +1,49 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class DataIntegrationInstallation: + """Data Integration Installation model.""" + + id: str + """Unique identifier of the installation.""" + user_id: str + """The User the API key was installed for.""" + organization_id: Optional[str] + """The Organization the installation is scoped to, or null when unscoped.""" + api_key_last_4: Optional[str] + """The last four characters of the stored API key. The full key is never returned.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "DataIntegrationInstallation": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + user_id=data["user_id"], + organization_id=data["organization_id"], + api_key_last_4=data["api_key_last_4"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("DataIntegrationInstallation", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["user_id"] = self.user_id + if self.organization_id is not None: + result["organization_id"] = self.organization_id + else: + result["organization_id"] = None + if self.api_key_last_4 is not None: + result["api_key_last_4"] = self.api_key_last_4 + else: + result["api_key_last_4"] = None + return result diff --git a/src/workos/pipes/models/update_data_integration.py b/src/workos/pipes/models/update_data_integration.py index 6d7e957a..0591ac8f 100644 --- a/src/workos/pipes/models/update_data_integration.py +++ b/src/workos/pipes/models/update_data_integration.py @@ -7,7 +7,8 @@ from typing import Any, Dict, List, Optional from workos._types import _raise_deserialize_error -from .data_integration_credentials_dto import DataIntegrationCredentialsDto +from .api_key_installation import ApiKeyInstallation +from .data_integration_credentials_input import DataIntegrationCredentialsInput from .update_custom_provider_definition import UpdateCustomProviderDefinition @@ -21,8 +22,10 @@ class UpdateDataIntegration: """Whether the Data Integration is enabled.""" scopes: Optional[List[str]] = None """The OAuth scopes to request for the Data Integration. Pass `null` to reset to the provider's configured scopes.""" - credentials: Optional["DataIntegrationCredentialsDto"] = None - """New credentials for the Data Integration. When provided, rotates the stored client secret.""" + credentials: Optional["DataIntegrationCredentialsInput"] = None + """New OAuth credentials for the Data Integration. When provided, rotates the stored client secret. Mutually exclusive with `api_key`.""" + api_key: Optional["ApiKeyInstallation"] = None + """An API key to install or rotate for a tenant on an `api_key` integration. Upserts the tenant installation identified by `user_id` (and optional `organization_id`).""" custom_provider: Optional["UpdateCustomProviderDefinition"] = None """Updates to a custom provider's OAuth definition. Only valid for custom-provider integrations.""" @@ -34,11 +37,14 @@ def from_dict(cls, data: Dict[str, Any]) -> "UpdateDataIntegration": description=data.get("description"), enabled=data.get("enabled"), scopes=data.get("scopes"), - credentials=DataIntegrationCredentialsDto.from_dict( + credentials=DataIntegrationCredentialsInput.from_dict( cast(Dict[str, Any], _v_credentials) ) if (_v_credentials := data.get("credentials")) is not None else None, + api_key=ApiKeyInstallation.from_dict(cast(Dict[str, Any], _v_api_key)) + if (_v_api_key := data.get("api_key")) is not None + else None, custom_provider=UpdateCustomProviderDefinition.from_dict( cast(Dict[str, Any], _v_custom_provider) ) @@ -63,6 +69,8 @@ def to_dict(self) -> Dict[str, Any]: result["scopes"] = None if self.credentials is not None: result["credentials"] = self.credentials.to_dict() + if self.api_key is not None: + result["api_key"] = self.api_key.to_dict() if self.custom_provider is not None: result["custom_provider"] = self.custom_provider.to_dict() return result diff --git a/src/workos/pipes_provider/_resource.py b/src/workos/pipes_provider/_resource.py index efa7698f..04e96389 100644 --- a/src/workos/pipes_provider/_resource.py +++ b/src/workos/pipes_provider/_resource.py @@ -2,12 +2,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions +from .._types import RequestOptions, NOT_GIVEN, NotGiven from .models import ( DataIntegrationConfigurationListResponse, DataIntegrationConfigurationResponse, @@ -60,7 +60,7 @@ def update_organization_data_integration_configuration( slug: str, *, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, client_id: Optional[str] = None, client_secret: Optional[str] = None, request_options: Optional[RequestOptions] = None, @@ -93,12 +93,13 @@ def update_organization_data_integration_configuration( k: v for k, v in { "enabled": enabled, - "scopes": scopes, "client_id": client_id, "client_secret": client_secret, }.items() if v is not None } + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return self._client.request( method="put", path=( @@ -159,7 +160,7 @@ async def update_organization_data_integration_configuration( slug: str, *, enabled: Optional[bool] = None, - scopes: Optional[List[str]] = None, + scopes: Union[List[str], None, NotGiven] = NOT_GIVEN, client_id: Optional[str] = None, client_secret: Optional[str] = None, request_options: Optional[RequestOptions] = None, @@ -192,12 +193,13 @@ async def update_organization_data_integration_configuration( k: v for k, v in { "enabled": enabled, - "scopes": scopes, "client_id": client_id, "client_secret": client_secret, }.items() if v is not None } + if not isinstance(scopes, NotGiven): + body["scopes"] = scopes return await self._client.request( method="put", path=( diff --git a/src/workos/sso/_resource.py b/src/workos/sso/_resource.py index 00b110c3..ab643e07 100644 --- a/src/workos/sso/_resource.py +++ b/src/workos/sso/_resource.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Union if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient @@ -154,6 +154,7 @@ def get_authorization_url( domain_hint: Optional[str] = None, login_hint: Optional[str] = None, nonce: Optional[str] = None, + prompt: Optional[Literal["login"]] = None, request_options: Optional[RequestOptions] = None, ) -> str: """Initiate SSO @@ -174,6 +175,7 @@ def get_authorization_url( domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. + prompt: If set to `login`, forces re-authentication at the identity provider. For SAML connections this sets `ForceAuthn="true"` in the SAML request. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -200,6 +202,7 @@ def get_authorization_url( "domain_hint": domain_hint, "login_hint": login_hint, "nonce": nonce, + "prompt": prompt, }.items() if v is not None } @@ -571,6 +574,7 @@ def get_authorization_url( domain_hint: Optional[str] = None, login_hint: Optional[str] = None, nonce: Optional[str] = None, + prompt: Optional[Literal["login"]] = None, request_options: Optional[RequestOptions] = None, ) -> str: """Initiate SSO @@ -591,6 +595,7 @@ def get_authorization_url( domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. + prompt: If set to `login`, forces re-authentication at the identity provider. For SAML connections this sets `ForceAuthn="true"` in the SAML request. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -617,6 +622,7 @@ def get_authorization_url( "domain_hint": domain_hint, "login_hint": login_hint, "nonce": nonce, + "prompt": prompt, }.items() if v is not None } diff --git a/src/workos/sso/models/connection.py b/src/workos/sso/models/connection.py index 5f208bfe..0c513b04 100644 --- a/src/workos/sso/models/connection.py +++ b/src/workos/sso/models/connection.py @@ -11,7 +11,6 @@ from workos._types import _format_datetime, _parse_datetime from .connection_domain import ConnectionDomain -from .connection_option import ConnectionOption from workos.common.models.connection_state import ConnectionState from workos.common.models.connection_status import ConnectionStatus from workos.common.models.connection_type import ConnectionType @@ -43,8 +42,8 @@ class Connection: """Deprecated. Use `state` instead. .. deprecated:: This field is deprecated.""" - options: Optional["ConnectionOption"] = None - """Configuration options for SAML connections. Only present for SAML connection types.""" + callback_endpoint: Optional[str] = None + """The immutable callback endpoint for this Connection. For SAML connections this is the ACS URL; for OIDC connections this is the redirect URI.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "Connection": @@ -66,9 +65,7 @@ def from_dict(cls, data: Dict[str, Any]) -> "Connection": status=ConnectionStatus(_v_status) if (_v_status := data.get("status")) is not None else None, - options=ConnectionOption.from_dict(cast(Dict[str, Any], _v_options)) - if (_v_options := data.get("options")) is not None - else None, + callback_endpoint=data.get("callback_endpoint"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("Connection", e) @@ -96,6 +93,6 @@ def to_dict(self) -> Dict[str, Any]: result["status"] = ( self.status.value if isinstance(self.status, Enum) else self.status ) - if self.options is not None: - result["options"] = self.options.to_dict() + if self.callback_endpoint is not None: + result["callback_endpoint"] = self.callback_endpoint return result diff --git a/src/workos/types/agents/__init__.py b/src/workos/types/agents/__init__.py new file mode 100644 index 00000000..7a33b078 --- /dev/null +++ b/src/workos/types/agents/__init__.py @@ -0,0 +1,3 @@ +# This file is auto-generated by oagen. Do not edit. + +from workos.agents.models import * # noqa: F401,F403 diff --git a/src/workos/user_management/_resource.py b/src/workos/user_management/_resource.py index 6cd1386f..5595fd77 100644 --- a/src/workos/user_management/_resource.py +++ b/src/workos/user_management/_resource.py @@ -7,35 +7,36 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( AuthenticateResponse, AuthorizationCodeSessionAuthenticateRequest, AuthorizedConnectApplicationListData, CORSOriginResponse, DeviceAuthorizationResponse, + DeviceCodeSessionAuthenticateRequest, EmailChange, EmailChangeConfirmation, EmailVerification, + EmailVerificationCodeSessionAuthenticateRequest, Invitation, JWTTemplateResponse, JwksResponse, MagicAuth, + MagicAuthCodeSessionAuthenticateRequest, MagicAuthSendMagicAuthCodeAndReturnResponse, + MFATotpSessionAuthenticateRequest, + OrganizationSelectionSessionAuthenticateRequest, PasswordReset, PasswordSessionAuthenticateRequest, + RadarChallenge, + RadarEmailChallengeCodeSessionAuthenticateRequest, + RadarSmsChallengeCodeSessionAuthenticateRequest, RedirectUri, RefreshTokenSessionAuthenticateRequest, ResetPasswordResponse, SendRadarSmsChallengeResponse, SendVerificationEmailResponse, - DeviceCodeSessionAuthenticateRequest, - EmailVerificationCodeSessionAuthenticateRequest, - MagicAuthCodeSessionAuthenticateRequest, - MFATotpSessionAuthenticateRequest, - OrganizationSelectionSessionAuthenticateRequest, - RadarEmailChallengeCodeSessionAuthenticateRequest, - RadarSmsChallengeCodeSessionAuthenticateRequest, UserApiKey, UserApiKeyWithValue, UserCreateResponse, @@ -710,6 +711,36 @@ def create_radar_challenge( request_options=request_options, ) + def get_radar_challenge( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> RadarChallenge: + """Get Radar Challenge details + + Get the details of an existing Radar Challenge, including the OTP code. + + Args: + id: The unique ID of the Radar Challenge. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + RadarChallenge + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("user_management", "radar_challenges", str(id)), + model=RadarChallenge, + request_options=request_options, + ) + def get_logout_url( self, *, @@ -829,7 +860,7 @@ def create_cors_origin( ) -> CORSOriginResponse: """Create a CORS origin - Creates a new CORS origin for the current environment. CORS origins allow browser-based applications to make requests to the WorkOS API. + Creates a new CORS origin for the API key's application. CORS origins allow browser-based applications to make requests to the WorkOS API. Args: origin: The origin URL to allow for CORS requests. @@ -1052,14 +1083,14 @@ def create_user( self, *, email: str, - first_name: Optional[str] = None, - last_name: Optional[str] = None, - name: Optional[str] = None, - email_verified: Optional[bool] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, - ip_address: Optional[str] = None, - user_agent: Optional[str] = None, + first_name: Union[str, None, NotGiven] = NOT_GIVEN, + last_name: Union[str, None, NotGiven] = NOT_GIVEN, + name: Union[str, None, NotGiven] = NOT_GIVEN, + email_verified: Union[bool, None, NotGiven] = NOT_GIVEN, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, + ip_address: Union[str, None, NotGiven] = NOT_GIVEN, + user_agent: Union[str, None, NotGiven] = NOT_GIVEN, signals_id: Optional[str] = None, password: Optional[Union[PasswordPlaintext, PasswordHashed]] = None, request_options: Optional[RequestOptions] = None, @@ -1097,18 +1128,26 @@ def create_user( k: v for k, v in { "email": email, - "first_name": first_name, - "last_name": last_name, - "name": name, - "email_verified": email_verified, - "metadata": metadata, - "external_id": external_id, - "ip_address": ip_address, - "user_agent": user_agent, "signals_id": signals_id, }.items() if v is not None } + if not isinstance(first_name, NotGiven): + body["first_name"] = first_name + if not isinstance(last_name, NotGiven): + body["last_name"] = last_name + if not isinstance(name, NotGiven): + body["name"] = name + if not isinstance(email_verified, NotGiven): + body["email_verified"] = email_verified + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id + if not isinstance(ip_address, NotGiven): + body["ip_address"] = ip_address + if not isinstance(user_agent, NotGiven): + body["user_agent"] = user_agent if password is not None: if isinstance(password, PasswordPlaintext): body["password"] = password.password @@ -1192,9 +1231,9 @@ def update_user( last_name: Optional[str] = None, name: Optional[str] = None, email_verified: Optional[bool] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, - locale: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, + locale: Union[str, None, NotGiven] = NOT_GIVEN, password: Optional[Union[PasswordPlaintext, PasswordHashed]] = None, request_options: Optional[RequestOptions] = None, ) -> User: @@ -1233,12 +1272,15 @@ def update_user( "last_name": last_name, "name": name, "email_verified": email_verified, - "metadata": metadata, - "external_id": external_id, - "locale": locale, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id + if not isinstance(locale, NotGiven): + body["locale"] = locale if password is not None: if isinstance(password, PasswordPlaintext): body["password"] = password.password @@ -2002,6 +2044,33 @@ def create_redirect_uri( request_options=request_options, ) + def delete_redirect_uris( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete a redirect URI + + Deletes a redirect URI from an application. + + Args: + id: The ID of the redirect URI to delete. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + AuthenticationError: If the API key is invalid (401). + NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + self._client.request( + method="delete", + path=("user_management", "redirect_uris", str(id)), + request_options=request_options, + ) + def list_user_authorized_applications( self, user_id: str, @@ -3001,6 +3070,36 @@ async def create_radar_challenge( request_options=request_options, ) + async def get_radar_challenge( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> RadarChallenge: + """Get Radar Challenge details + + Get the details of an existing Radar Challenge, including the OTP code. + + Args: + id: The unique ID of the Radar Challenge. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + RadarChallenge + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("user_management", "radar_challenges", str(id)), + model=RadarChallenge, + request_options=request_options, + ) + def get_logout_url( self, *, @@ -3120,7 +3219,7 @@ async def create_cors_origin( ) -> CORSOriginResponse: """Create a CORS origin - Creates a new CORS origin for the current environment. CORS origins allow browser-based applications to make requests to the WorkOS API. + Creates a new CORS origin for the API key's application. CORS origins allow browser-based applications to make requests to the WorkOS API. Args: origin: The origin URL to allow for CORS requests. @@ -3343,14 +3442,14 @@ async def create_user( self, *, email: str, - first_name: Optional[str] = None, - last_name: Optional[str] = None, - name: Optional[str] = None, - email_verified: Optional[bool] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, - ip_address: Optional[str] = None, - user_agent: Optional[str] = None, + first_name: Union[str, None, NotGiven] = NOT_GIVEN, + last_name: Union[str, None, NotGiven] = NOT_GIVEN, + name: Union[str, None, NotGiven] = NOT_GIVEN, + email_verified: Union[bool, None, NotGiven] = NOT_GIVEN, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, + ip_address: Union[str, None, NotGiven] = NOT_GIVEN, + user_agent: Union[str, None, NotGiven] = NOT_GIVEN, signals_id: Optional[str] = None, password: Optional[Union[PasswordPlaintext, PasswordHashed]] = None, request_options: Optional[RequestOptions] = None, @@ -3388,18 +3487,26 @@ async def create_user( k: v for k, v in { "email": email, - "first_name": first_name, - "last_name": last_name, - "name": name, - "email_verified": email_verified, - "metadata": metadata, - "external_id": external_id, - "ip_address": ip_address, - "user_agent": user_agent, "signals_id": signals_id, }.items() if v is not None } + if not isinstance(first_name, NotGiven): + body["first_name"] = first_name + if not isinstance(last_name, NotGiven): + body["last_name"] = last_name + if not isinstance(name, NotGiven): + body["name"] = name + if not isinstance(email_verified, NotGiven): + body["email_verified"] = email_verified + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id + if not isinstance(ip_address, NotGiven): + body["ip_address"] = ip_address + if not isinstance(user_agent, NotGiven): + body["user_agent"] = user_agent if password is not None: if isinstance(password, PasswordPlaintext): body["password"] = password.password @@ -3483,9 +3590,9 @@ async def update_user( last_name: Optional[str] = None, name: Optional[str] = None, email_verified: Optional[bool] = None, - metadata: Optional[Dict[str, str]] = None, - external_id: Optional[str] = None, - locale: Optional[str] = None, + metadata: Union[Dict[str, str], None, NotGiven] = NOT_GIVEN, + external_id: Union[str, None, NotGiven] = NOT_GIVEN, + locale: Union[str, None, NotGiven] = NOT_GIVEN, password: Optional[Union[PasswordPlaintext, PasswordHashed]] = None, request_options: Optional[RequestOptions] = None, ) -> User: @@ -3524,12 +3631,15 @@ async def update_user( "last_name": last_name, "name": name, "email_verified": email_verified, - "metadata": metadata, - "external_id": external_id, - "locale": locale, }.items() if v is not None } + if not isinstance(metadata, NotGiven): + body["metadata"] = metadata + if not isinstance(external_id, NotGiven): + body["external_id"] = external_id + if not isinstance(locale, NotGiven): + body["locale"] = locale if password is not None: if isinstance(password, PasswordPlaintext): body["password"] = password.password @@ -4293,6 +4403,33 @@ async def create_redirect_uri( request_options=request_options, ) + async def delete_redirect_uris( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete a redirect URI + + Deletes a redirect URI from an application. + + Args: + id: The ID of the redirect URI to delete. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + AuthenticationError: If the API key is invalid (401). + NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + await self._client.request( + method="delete", + path=("user_management", "redirect_uris", str(id)), + request_options=request_options, + ) + async def list_user_authorized_applications( self, user_id: str, diff --git a/src/workos/user_management/models/__init__.py b/src/workos/user_management/models/__init__.py index 6d7da6dc..8a8759d8 100644 --- a/src/workos/user_management/models/__init__.py +++ b/src/workos/user_management/models/__init__.py @@ -32,6 +32,9 @@ from .device_authorization_response import ( DeviceAuthorizationResponse as DeviceAuthorizationResponse, ) +from .device_code_session_authenticate_request import ( + DeviceCodeSessionAuthenticateRequest as DeviceCodeSessionAuthenticateRequest, +) from .email_change import EmailChange as EmailChange from .email_change_confirmation import ( EmailChangeConfirmation as EmailChangeConfirmation, @@ -40,18 +43,37 @@ EmailChangeConfirmationUser as EmailChangeConfirmationUser, ) from .email_verification import EmailVerification as EmailVerification +from .email_verification_code_session_authenticate_request import ( + EmailVerificationCodeSessionAuthenticateRequest as EmailVerificationCodeSessionAuthenticateRequest, +) from .invitation import Invitation as Invitation from .jwks_response import JwksResponse as JwksResponse from .jwks_response_keys import JwksResponseKeys as JwksResponseKeys from .jwt_template_response import JWTTemplateResponse as JWTTemplateResponse from .magic_auth import MagicAuth as MagicAuth +from .magic_auth_code_session_authenticate_request import ( + MagicAuthCodeSessionAuthenticateRequest as MagicAuthCodeSessionAuthenticateRequest, +) from .magic_auth_send_magic_auth_code_and_return_response import ( MagicAuthSendMagicAuthCodeAndReturnResponse as MagicAuthSendMagicAuthCodeAndReturnResponse, ) +from .mfa_totp_session_authenticate_request import ( + MFATotpSessionAuthenticateRequest as MFATotpSessionAuthenticateRequest, +) +from .organization_selection_session_authenticate_request import ( + OrganizationSelectionSessionAuthenticateRequest as OrganizationSelectionSessionAuthenticateRequest, +) from .password_reset import PasswordReset as PasswordReset from .password_session_authenticate_request import ( PasswordSessionAuthenticateRequest as PasswordSessionAuthenticateRequest, ) +from .radar_challenge import RadarChallenge as RadarChallenge +from .radar_email_challenge_code_session_authenticate_request import ( + RadarEmailChallengeCodeSessionAuthenticateRequest as RadarEmailChallengeCodeSessionAuthenticateRequest, +) +from .radar_sms_challenge_code_session_authenticate_request import ( + RadarSmsChallengeCodeSessionAuthenticateRequest as RadarSmsChallengeCodeSessionAuthenticateRequest, +) from .redirect_uri import RedirectUri as RedirectUri from .refresh_token_session_authenticate_request import ( RefreshTokenSessionAuthenticateRequest as RefreshTokenSessionAuthenticateRequest, @@ -74,27 +96,6 @@ ) from .update_jwt_template import UpdateJWTTemplate as UpdateJWTTemplate from .update_user import UpdateUser as UpdateUser -from .device_code_session_authenticate_request import ( - DeviceCodeSessionAuthenticateRequest as DeviceCodeSessionAuthenticateRequest, -) -from .email_verification_code_session_authenticate_request import ( - EmailVerificationCodeSessionAuthenticateRequest as EmailVerificationCodeSessionAuthenticateRequest, -) -from .magic_auth_code_session_authenticate_request import ( - MagicAuthCodeSessionAuthenticateRequest as MagicAuthCodeSessionAuthenticateRequest, -) -from .mfa_totp_session_authenticate_request import ( - MFATotpSessionAuthenticateRequest as MFATotpSessionAuthenticateRequest, -) -from .organization_selection_session_authenticate_request import ( - OrganizationSelectionSessionAuthenticateRequest as OrganizationSelectionSessionAuthenticateRequest, -) -from .radar_email_challenge_code_session_authenticate_request import ( - RadarEmailChallengeCodeSessionAuthenticateRequest as RadarEmailChallengeCodeSessionAuthenticateRequest, -) -from .radar_sms_challenge_code_session_authenticate_request import ( - RadarSmsChallengeCodeSessionAuthenticateRequest as RadarSmsChallengeCodeSessionAuthenticateRequest, -) from workos.common.models.user import User as User from .user_api_key import UserApiKey as UserApiKey from .user_api_key_owner import UserApiKeyOwner as UserApiKeyOwner diff --git a/src/workos/user_management/models/radar_challenge.py b/src/workos/user_management/models/radar_challenge.py new file mode 100644 index 00000000..eed29c21 --- /dev/null +++ b/src/workos/user_management/models/radar_challenge.py @@ -0,0 +1,65 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, Literal +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class RadarChallenge: + """Radar Challenge model.""" + + object: Literal["radar_challenge"] + """Distinguishes the Radar Challenge object.""" + id: str + """The unique ID of the Radar Challenge.""" + type: Literal["email"] + """The type of the Radar challenge.""" + user_id: str + """The unique ID of the user.""" + email: str + """The email address of the user.""" + expires_at: datetime + """The timestamp when the Radar Challenge code expires.""" + created_at: datetime + """An ISO 8601 timestamp.""" + updated_at: datetime + """An ISO 8601 timestamp.""" + code: str + """The code used to verify the Radar Challenge.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "RadarChallenge": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "radar_challenge"), + id=data["id"], + type=data.get("type", "email"), + user_id=data["user_id"], + email=data["email"], + expires_at=_parse_datetime(data["expires_at"]), + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + code=data["code"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("RadarChallenge", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["type"] = self.type + result["user_id"] = self.user_id + result["email"] = self.email + result["expires_at"] = _format_datetime(self.expires_at) + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + result["code"] = self.code + return result diff --git a/src/workos/vault/_resource.py b/src/workos/vault/_resource.py index 2c47d589..23f07fe4 100644 --- a/src/workos/vault/_resource.py +++ b/src/workos/vault/_resource.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value +from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven from .models import ( CreateDataKeyResponse, DecryptResponse, @@ -391,7 +391,7 @@ def update_kv( id: str, *, value: str, - version_check: Optional[str] = None, + version_check: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ObjectWithoutValue: """Update an object @@ -415,13 +415,10 @@ def update_kv( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "value": value, - "version_check": version_check, - }.items() - if v is not None + "value": value, } + if not isinstance(version_check, NotGiven): + body["version_check"] = version_check return self._client.request( method="put", path=("vault", "v1", "kv", str(id)), @@ -855,7 +852,7 @@ async def update_kv( id: str, *, value: str, - version_check: Optional[str] = None, + version_check: Union[str, None, NotGiven] = NOT_GIVEN, request_options: Optional[RequestOptions] = None, ) -> ObjectWithoutValue: """Update an object @@ -879,13 +876,10 @@ async def update_kv( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "value": value, - "version_check": version_check, - }.items() - if v is not None + "value": value, } + if not isinstance(version_check, NotGiven): + body["version_check"] = version_check return await self._client.request( method="put", path=("vault", "v1", "kv", str(id)), diff --git a/src/workos/widgets/_resource.py b/src/workos/widgets/_resource.py index 0834e1ea..db0937a0 100644 --- a/src/workos/widgets/_resource.py +++ b/src/workos/widgets/_resource.py @@ -21,17 +21,17 @@ def __init__(self, client: "WorkOSClient") -> None: def create_token( self, *, - organization_id: str, + organization_id: Optional[str] = None, user_id: Optional[str] = None, scopes: Optional[List[Union[WidgetSessionTokenScopes, str]]] = None, request_options: Optional[RequestOptions] = None, ) -> WidgetSessionTokenResponse: """Generate a widget token - Generate a widget token scoped to an organization and user with the specified scopes. + Generate a widget token for a user, optionally scoped to an organization. When an organization is specified, org-scoped widgets are enabled; omitting it issues a user-only token for widgets like `UserProfile` and `UserSecurity`. Args: - organization_id: The ID of the organization to scope the widget session to. + organization_id: The ID of the organization to scope the widget session to. Required when scopes are provided. Optional when issuing a token for user-only widgets (e.g. `UserProfile`, `UserSecurity`) that do not require organization context. user_id: The ID of the user to issue the widget session token for. scopes: The scopes to grant the widget session. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -74,17 +74,17 @@ def __init__(self, client: "AsyncWorkOSClient") -> None: async def create_token( self, *, - organization_id: str, + organization_id: Optional[str] = None, user_id: Optional[str] = None, scopes: Optional[List[Union[WidgetSessionTokenScopes, str]]] = None, request_options: Optional[RequestOptions] = None, ) -> WidgetSessionTokenResponse: """Generate a widget token - Generate a widget token scoped to an organization and user with the specified scopes. + Generate a widget token for a user, optionally scoped to an organization. When an organization is specified, org-scoped widgets are enabled; omitting it issues a user-only token for widgets like `UserProfile` and `UserSecurity`. Args: - organization_id: The ID of the organization to scope the widget session to. + organization_id: The ID of the organization to scope the widget session to. Required when scopes are provided. Optional when issuing a token for user-only widgets (e.g. `UserProfile`, `UserSecurity`) that do not require organization context. user_id: The ID of the user to issue the widget session token for. scopes: The scopes to grant the widget session. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. diff --git a/src/workos/widgets/models/widget_session_token.py b/src/workos/widgets/models/widget_session_token.py index 5a19c7c1..801b9724 100644 --- a/src/workos/widgets/models/widget_session_token.py +++ b/src/workos/widgets/models/widget_session_token.py @@ -14,8 +14,8 @@ class WidgetSessionToken: """Widget Session Token model.""" - organization_id: str - """The ID of the organization to scope the widget session to.""" + organization_id: Optional[str] = None + """The ID of the organization to scope the widget session to. Required when scopes are provided. Optional when issuing a token for user-only widgets (e.g. `UserProfile`, `UserSecurity`) that do not require organization context.""" user_id: Optional[str] = None """The ID of the user to issue the widget session token for.""" scopes: Optional[List["WidgetSessionTokenScopes"]] = None @@ -26,7 +26,7 @@ def from_dict(cls, data: Dict[str, Any]) -> "WidgetSessionToken": """Deserialize from a dictionary.""" try: return cls( - organization_id=data["organization_id"], + organization_id=data.get("organization_id"), user_id=data.get("user_id"), scopes=[ WidgetSessionTokenScopes(item) @@ -41,7 +41,8 @@ def from_dict(cls, data: Dict[str, Any]) -> "WidgetSessionToken": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} - result["organization_id"] = self.organization_id + if self.organization_id is not None: + result["organization_id"] = self.organization_id if self.user_id is not None: result["user_id"] = self.user_id if self.scopes is not None: diff --git a/tests/fixtures/access_token_agent_registration_credential_issued_data_detail.json b/tests/fixtures/access_token_agent_registration_credential_issued_data_detail.json new file mode 100644 index 00000000..25bd69de --- /dev/null +++ b/tests/fixtures/access_token_agent_registration_credential_issued_data_detail.json @@ -0,0 +1,5 @@ +{ + "kind": "access_token", + "jti": "jti_01EHWNCE74X7JSDV0X3SZ3KJNY", + "expires_at": "2024-01-15T11:30:00.000Z" +} diff --git a/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request.json b/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request.json new file mode 100644 index 00000000..b59ca2a1 --- /dev/null +++ b/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request.json @@ -0,0 +1,9 @@ +{ + "type": "link_external_user", + "claim_attempt_token": "cla_tkn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "email": "alice@example.com", + "external_id": "user_abc123" + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY" +} diff --git a/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request_user.json b/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request_user.json new file mode 100644 index 00000000..aace69e2 --- /dev/null +++ b/tests/fixtures/agent_admin_link_claim_attempt_to_external_user_request_user.json @@ -0,0 +1,4 @@ +{ + "email": "alice@example.com", + "external_id": "user_abc123" +} diff --git a/tests/fixtures/agent_admin_validate_credential_request.json b/tests/fixtures/agent_admin_validate_credential_request.json new file mode 100644 index 00000000..62dc1418 --- /dev/null +++ b/tests/fixtures/agent_admin_validate_credential_request.json @@ -0,0 +1,5 @@ +{ + "type": "api_key", + "credential": "sk_agent_example_1234567890", + "audience": "https://api.example.com" +} diff --git a/tests/fixtures/agent_credential_validation.json b/tests/fixtures/agent_credential_validation.json new file mode 100644 index 00000000..438916fa --- /dev/null +++ b/tests/fixtures/agent_credential_validation.json @@ -0,0 +1,5 @@ +{ + "valid": true, + "registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "expires_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/agent_registration.json b/tests/fixtures/agent_registration.json new file mode 100644 index 00000000..cb6c56d6 --- /dev/null +++ b/tests/fixtures/agent_registration.json @@ -0,0 +1,27 @@ +{ + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + }, + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "status": "verified", + "kind": "service_auth", + "claim": { + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claim_completion": { + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + "claimed_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/agent_registration_agent_identity.json b/tests/fixtures/agent_registration_agent_identity.json new file mode 100644 index 00000000..a8edf67b --- /dev/null +++ b/tests/fixtures/agent_registration_agent_identity.json @@ -0,0 +1,6 @@ +{ + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/agent_registration_claim.json b/tests/fixtures/agent_registration_claim.json new file mode 100644 index 00000000..7a12f260 --- /dev/null +++ b/tests/fixtures/agent_registration_claim.json @@ -0,0 +1,13 @@ +{ + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claim_completion": { + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + "claimed_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/agent_registration_claim_attempt_created.json b/tests/fixtures/agent_registration_claim_attempt_created.json new file mode 100644 index 00000000..10ad64f8 --- /dev/null +++ b/tests/fixtures/agent_registration_claim_attempt_created.json @@ -0,0 +1,36 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.attempt.created", + "data": { + "object": "agent_registration_claim_attempt", + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_claim_id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "login_hint": "jane@example.com", + "expires_at": "2024-01-15T10:35:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_claim_attempt_created_data.json b/tests/fixtures/agent_registration_claim_attempt_created_data.json new file mode 100644 index 00000000..c1a95b59 --- /dev/null +++ b/tests/fixtures/agent_registration_claim_attempt_created_data.json @@ -0,0 +1,10 @@ +{ + "object": "agent_registration_claim_attempt", + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_claim_id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "login_hint": "jane@example.com", + "expires_at": "2024-01-15T10:35:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z" +} diff --git a/tests/fixtures/agent_registration_claim_claim_completion.json b/tests/fixtures/agent_registration_claim_claim_completion.json new file mode 100644 index 00000000..30aaf5df --- /dev/null +++ b/tests/fixtures/agent_registration_claim_claim_completion.json @@ -0,0 +1,7 @@ +{ + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + "claimed_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/agent_registration_claim_completed.json b/tests/fixtures/agent_registration_claim_completed.json new file mode 100644 index 00000000..af38aac7 --- /dev/null +++ b/tests/fixtures/agent_registration_claim_completed.json @@ -0,0 +1,39 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.completed", + "data": { + "object": "agent_registration_claim", + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "completed_by_attempt_id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claimed_by": { + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": null + }, + "completed_at": "2024-01-15T10:32:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:32:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_claim_completed_data.json b/tests/fixtures/agent_registration_claim_completed_data.json new file mode 100644 index 00000000..a2d1b41c --- /dev/null +++ b/tests/fixtures/agent_registration_claim_completed_data.json @@ -0,0 +1,13 @@ +{ + "object": "agent_registration_claim", + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "completed_by_attempt_id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claimed_by": { + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": null + }, + "completed_at": "2024-01-15T10:32:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:32:00.000Z" +} diff --git a/tests/fixtures/agent_registration_claim_completed_data_claimed_by.json b/tests/fixtures/agent_registration_claim_completed_data_claimed_by.json new file mode 100644 index 00000000..05842c25 --- /dev/null +++ b/tests/fixtures/agent_registration_claim_completed_data_claimed_by.json @@ -0,0 +1,4 @@ +{ + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": null +} diff --git a/tests/fixtures/agent_registration_created.json b/tests/fixtures/agent_registration_created.json new file mode 100644 index 00000000..25b84d31 --- /dev/null +++ b/tests/fixtures/agent_registration_created.json @@ -0,0 +1,41 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.created", + "data": { + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": null + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_created_data.json b/tests/fixtures/agent_registration_created_data.json new file mode 100644 index 00000000..193c09a9 --- /dev/null +++ b/tests/fixtures/agent_registration_created_data.json @@ -0,0 +1,15 @@ +{ + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": null + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z" +} diff --git a/tests/fixtures/agent_registration_created_data_agent_identity.json b/tests/fixtures/agent_registration_created_data_agent_identity.json new file mode 100644 index 00000000..8e358ebc --- /dev/null +++ b/tests/fixtures/agent_registration_created_data_agent_identity.json @@ -0,0 +1,5 @@ +{ + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": null +} diff --git a/tests/fixtures/agent_registration_credential_issued.json b/tests/fixtures/agent_registration_credential_issued.json new file mode 100644 index 00000000..9bcb88b9 --- /dev/null +++ b/tests/fixtures/agent_registration_credential_issued.json @@ -0,0 +1,37 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.credential.issued", + "data": { + "object": "agent_registration_credential", + "id": "agent_reg_credential_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "detail": { + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV" + }, + "created_at": "2024-01-15T10:33:00.000Z", + "updated_at": "2024-01-15T10:33:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_credential_issued_data.json b/tests/fixtures/agent_registration_credential_issued_data.json new file mode 100644 index 00000000..17274490 --- /dev/null +++ b/tests/fixtures/agent_registration_credential_issued_data.json @@ -0,0 +1,11 @@ +{ + "object": "agent_registration_credential", + "id": "agent_reg_credential_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "detail": { + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV" + }, + "created_at": "2024-01-15T10:33:00.000Z", + "updated_at": "2024-01-15T10:33:00.000Z" +} diff --git a/tests/fixtures/agent_registration_credential_issued_data_detail.json b/tests/fixtures/agent_registration_credential_issued_data_detail.json new file mode 100644 index 00000000..ff7590a0 --- /dev/null +++ b/tests/fixtures/agent_registration_credential_issued_data_detail.json @@ -0,0 +1,4 @@ +{ + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV" +} diff --git a/tests/fixtures/agent_registration_deleted.json b/tests/fixtures/agent_registration_deleted.json new file mode 100644 index 00000000..719abd44 --- /dev/null +++ b/tests/fixtures/agent_registration_deleted.json @@ -0,0 +1,29 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.deleted", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_deleted_data.json b/tests/fixtures/agent_registration_deleted_data.json new file mode 100644 index 00000000..f7cb2dcb --- /dev/null +++ b/tests/fixtures/agent_registration_deleted_data.json @@ -0,0 +1,3 @@ +{ + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" +} diff --git a/tests/fixtures/agent_registration_expired.json b/tests/fixtures/agent_registration_expired.json new file mode 100644 index 00000000..b1bcab92 --- /dev/null +++ b/tests/fixtures/agent_registration_expired.json @@ -0,0 +1,29 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.expired", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_expired_data.json b/tests/fixtures/agent_registration_expired_data.json new file mode 100644 index 00000000..f7cb2dcb --- /dev/null +++ b/tests/fixtures/agent_registration_expired_data.json @@ -0,0 +1,3 @@ +{ + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" +} diff --git a/tests/fixtures/agent_registration_organization_switched.json b/tests/fixtures/agent_registration_organization_switched.json new file mode 100644 index 00000000..0d11e1a5 --- /dev/null +++ b/tests/fixtures/agent_registration_organization_switched.json @@ -0,0 +1,31 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.organization.switched", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "from_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "to_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNZ" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_organization_switched_data.json b/tests/fixtures/agent_registration_organization_switched_data.json new file mode 100644 index 00000000..e6d09385 --- /dev/null +++ b/tests/fixtures/agent_registration_organization_switched_data.json @@ -0,0 +1,5 @@ +{ + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "from_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "to_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNZ" +} diff --git a/tests/fixtures/agent_registration_revoked.json b/tests/fixtures/agent_registration_revoked.json new file mode 100644 index 00000000..59c5b58e --- /dev/null +++ b/tests/fixtures/agent_registration_revoked.json @@ -0,0 +1,29 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.revoked", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/agent_registration_revoked_data.json b/tests/fixtures/agent_registration_revoked_data.json new file mode 100644 index 00000000..f7cb2dcb --- /dev/null +++ b/tests/fixtures/agent_registration_revoked_data.json @@ -0,0 +1,3 @@ +{ + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" +} diff --git a/tests/fixtures/api_key_installation.json b/tests/fixtures/api_key_installation.json new file mode 100644 index 00000000..3506192b --- /dev/null +++ b/tests/fixtures/api_key_installation.json @@ -0,0 +1,5 @@ +{ + "secret": "sk-1234567890abcdef", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/tests/fixtures/api_key_validation_response.json b/tests/fixtures/api_key_validation_response.json index 77549bf9..01e025ac 100644 --- a/tests/fixtures/api_key_validation_response.json +++ b/tests/fixtures/api_key_validation_response.json @@ -16,5 +16,6 @@ ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" - } + }, + "agent_registration_id": "agent_reg_01EHZNVPK3SFK441A1RGBFSHRT" } diff --git a/tests/fixtures/authentication_reauthentication_succeeded.json b/tests/fixtures/authentication_reauthentication_succeeded.json new file mode 100644 index 00000000..a50a0f1d --- /dev/null +++ b/tests/fixtures/authentication_reauthentication_succeeded.json @@ -0,0 +1,34 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.reauthentication_succeeded", + "data": { + "type": "reauthentication", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/authentication_reauthentication_succeeded_data.json b/tests/fixtures/authentication_reauthentication_succeeded_data.json new file mode 100644 index 00000000..7db4bda5 --- /dev/null +++ b/tests/fixtures/authentication_reauthentication_succeeded_data.json @@ -0,0 +1,8 @@ +{ + "type": "reauthentication", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com" +} diff --git a/tests/fixtures/claim_view_response.json b/tests/fixtures/claim_view_response.json new file mode 100644 index 00000000..81792898 --- /dev/null +++ b/tests/fixtures/claim_view_response.json @@ -0,0 +1,11 @@ +{ + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "user_code": "BCDF-GHJK", + "organizations": [ + { + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Corp" + } + ] +} diff --git a/tests/fixtures/claim_view_response_organization.json b/tests/fixtures/claim_view_response_organization.json new file mode 100644 index 00000000..8ccf492c --- /dev/null +++ b/tests/fixtures/claim_view_response_organization.json @@ -0,0 +1,4 @@ +{ + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Corp" +} diff --git a/tests/fixtures/connected_account_input.json b/tests/fixtures/connected_account_input.json new file mode 100644 index 00000000..d04b7e83 --- /dev/null +++ b/tests/fixtures/connected_account_input.json @@ -0,0 +1,10 @@ +{ + "access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a", + "refresh_token": "ghr_xxxxxxxxxxxxxxxxxxxx", + "expires_at": "2025-12-31T23:59:59.000Z", + "scopes": [ + "repo", + "user:email" + ], + "state": "connected" +} diff --git a/tests/fixtures/connection.json b/tests/fixtures/connection.json index 2caf9273..5d7d3b2c 100644 --- a/tests/fixtures/connection.json +++ b/tests/fixtures/connection.json @@ -13,9 +13,7 @@ "domain": "foo-corp.com" } ], - "options": { - "signing_cert": null - }, + "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/create_data_integration.json b/tests/fixtures/create_data_integration.json index 8051c136..2a37e387 100644 --- a/tests/fixtures/create_data_integration.json +++ b/tests/fixtures/create_data_integration.json @@ -6,11 +6,19 @@ "repo", "read:org" ], + "auth_methods": [ + "oauth" + ], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "client_secret": "secret_…" }, + "api_key": { + "secret": "sk-1234567890abcdef", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" + }, "custom_provider": { "name": "My OAuth App", "authorization_url": "https://provider.example.com/oauth/authorize", diff --git a/tests/fixtures/data_integration.json b/tests/fixtures/data_integration.json index 997363ae..afb71c86 100644 --- a/tests/fixtures/data_integration.json +++ b/tests/fixtures/data_integration.json @@ -11,11 +11,15 @@ "read:org" ], "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + "auth_methods": [ + "oauth" + ], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "redacted_client_secret": "6789" }, + "installation": null, "custom_provider": { "name": "My OAuth App", "authorization_url": "https://provider.example.com/oauth/authorize", diff --git a/tests/fixtures/data_integration_credentials_input.json b/tests/fixtures/data_integration_credentials_input.json new file mode 100644 index 00000000..e5098765 --- /dev/null +++ b/tests/fixtures/data_integration_credentials_input.json @@ -0,0 +1,5 @@ +{ + "type": "custom", + "client_id": "Iv1.abc123", + "client_secret": "secret_…" +} diff --git a/tests/fixtures/data_integration_installation.json b/tests/fixtures/data_integration_installation.json new file mode 100644 index 00000000..394d135d --- /dev/null +++ b/tests/fixtures/data_integration_installation.json @@ -0,0 +1,6 @@ +{ + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": null, + "api_key_last_4": "cdef" +} diff --git a/tests/fixtures/list_connection.json b/tests/fixtures/list_connection.json index ace19723..36fec9bc 100644 --- a/tests/fixtures/list_connection.json +++ b/tests/fixtures/list_connection.json @@ -15,9 +15,7 @@ "domain": "foo-corp.com" } ], - "options": { - "signing_cert": null - }, + "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/list_data_integration.json b/tests/fixtures/list_data_integration.json index 13639f77..f5e15218 100644 --- a/tests/fixtures/list_data_integration.json +++ b/tests/fixtures/list_data_integration.json @@ -13,11 +13,15 @@ "read:org" ], "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + "auth_methods": [ + "oauth" + ], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "redacted_client_secret": "6789" }, + "installation": null, "custom_provider": { "name": "My OAuth App", "authorization_url": "https://provider.example.com/oauth/authorize", diff --git a/tests/fixtures/list_organization_authorized_connect_application_list_data.json b/tests/fixtures/list_organization_authorized_connect_application_list_data.json new file mode 100644 index 00000000..8ec105c8 --- /dev/null +++ b/tests/fixtures/list_organization_authorized_connect_application_list_data.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "object": "authorized_connect_application", + "id": "authorized_connect_app_01HXYZ123456789ABCDEFGHIJ", + "granted_scopes": [ + "openid", + "profile", + "email" + ], + "oauth_resource": "https://api.example.com/resource", + "application": { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": [ + "openid", + "profile", + "email" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" + }, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/fixtures/list_redirect_uri.json b/tests/fixtures/list_redirect_uri.json index 420055be..f6be9da8 100644 --- a/tests/fixtures/list_redirect_uri.json +++ b/tests/fixtures/list_redirect_uri.json @@ -2,7 +2,7 @@ "data": [ { "object": "redirect_uri", - "id": "ruri_01EHZNVPK3SFK441A1RGBFSHRT", + "id": "redir_01EHZNVPK3SFK441A1RGBFSHRT", "uri": "https://example.com/callback", "default": true, "created_at": "2026-01-15T12:00:00.000Z", diff --git a/tests/fixtures/organization_authorized_connect_application_list_data.json b/tests/fixtures/organization_authorized_connect_application_list_data.json new file mode 100644 index 00000000..ed45b7c8 --- /dev/null +++ b/tests/fixtures/organization_authorized_connect_application_list_data.json @@ -0,0 +1,36 @@ +{ + "object": "authorized_connect_application", + "id": "authorized_connect_app_01HXYZ123456789ABCDEFGHIJ", + "granted_scopes": [ + "openid", + "profile", + "email" + ], + "oauth_resource": "https://api.example.com/resource", + "application": { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": [ + "openid", + "profile", + "email" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" + }, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5" +} diff --git a/tests/fixtures/permission_created.json b/tests/fixtures/permission_created.json index f991b655..7d84a43f 100644 --- a/tests/fixtures/permission_created.json +++ b/tests/fixtures/permission_created.json @@ -9,6 +9,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }, diff --git a/tests/fixtures/permission_created_data.json b/tests/fixtures/permission_created_data.json index b17cbcbe..5f6836ca 100644 --- a/tests/fixtures/permission_created_data.json +++ b/tests/fixtures/permission_created_data.json @@ -5,6 +5,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/permission_deleted.json b/tests/fixtures/permission_deleted.json index ee636f8e..b0459ff7 100644 --- a/tests/fixtures/permission_deleted.json +++ b/tests/fixtures/permission_deleted.json @@ -9,6 +9,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }, diff --git a/tests/fixtures/permission_deleted_data.json b/tests/fixtures/permission_deleted_data.json index b17cbcbe..5f6836ca 100644 --- a/tests/fixtures/permission_deleted_data.json +++ b/tests/fixtures/permission_deleted_data.json @@ -5,6 +5,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/permission_updated.json b/tests/fixtures/permission_updated.json index 17ddb1d5..bce477c3 100644 --- a/tests/fixtures/permission_updated.json +++ b/tests/fixtures/permission_updated.json @@ -9,6 +9,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }, diff --git a/tests/fixtures/permission_updated_data.json b/tests/fixtures/permission_updated_data.json index b17cbcbe..5f6836ca 100644 --- a/tests/fixtures/permission_updated_data.json +++ b/tests/fixtures/permission_updated_data.json @@ -5,6 +5,7 @@ "name": "Manage Billing", "description": "Allows managing billing settings.", "system": false, + "resource_type_slug": "organization", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/pipes_connected_account_connection_failed.json b/tests/fixtures/pipes_connected_account_connection_failed.json new file mode 100644 index 00000000..db36784b --- /dev/null +++ b/tests/fixtures/pipes_connected_account_connection_failed.json @@ -0,0 +1,38 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connection_failed", + "data": { + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "error_code": "authorization_code_exchange_error", + "error_reason": "The authorization code has expired.", + "provider_error": "access_denied", + "provider_error_description": "The user denied the authorization request.", + "created_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/pipes_connected_account_connection_failed_data.json b/tests/fixtures/pipes_connected_account_connection_failed_data.json new file mode 100644 index 00000000..cd5f1fc6 --- /dev/null +++ b/tests/fixtures/pipes_connected_account_connection_failed_data.json @@ -0,0 +1,12 @@ +{ + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "error_code": "authorization_code_exchange_error", + "error_reason": "The authorization code has expired.", + "provider_error": "access_denied", + "provider_error_description": "The user denied the authorization request.", + "created_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/radar_challenge.json b/tests/fixtures/radar_challenge.json new file mode 100644 index 00000000..a99b3c72 --- /dev/null +++ b/tests/fixtures/radar_challenge.json @@ -0,0 +1,11 @@ +{ + "object": "radar_challenge", + "id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "type": "email", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "code": "123456" +} diff --git a/tests/fixtures/radar_challenge_created.json b/tests/fixtures/radar_challenge_created.json new file mode 100644 index 00000000..6b43f6b0 --- /dev/null +++ b/tests/fixtures/radar_challenge_created.json @@ -0,0 +1,32 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "radar.challenge_created", + "data": { + "type": "email", + "radar_challenge_id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/radar_challenge_created_data.json b/tests/fixtures/radar_challenge_created_data.json new file mode 100644 index 00000000..cacae19c --- /dev/null +++ b/tests/fixtures/radar_challenge_created_data.json @@ -0,0 +1,6 @@ +{ + "type": "email", + "radar_challenge_id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com" +} diff --git a/tests/fixtures/redirect_uri.json b/tests/fixtures/redirect_uri.json index dcd6ad8d..4dc50064 100644 --- a/tests/fixtures/redirect_uri.json +++ b/tests/fixtures/redirect_uri.json @@ -1,6 +1,6 @@ { "object": "redirect_uri", - "id": "ruri_01EHZNVPK3SFK441A1RGBFSHRT", + "id": "redir_01EHZNVPK3SFK441A1RGBFSHRT", "uri": "https://example.com/callback", "default": true, "created_at": "2026-01-15T12:00:00.000Z", diff --git a/tests/fixtures/update_data_integration.json b/tests/fixtures/update_data_integration.json index 8996a29c..9578d105 100644 --- a/tests/fixtures/update_data_integration.json +++ b/tests/fixtures/update_data_integration.json @@ -10,6 +10,11 @@ "client_id": "Iv1.abc123", "client_secret": "secret_…" }, + "api_key": { + "secret": "sk-1234567890abcdef", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" + }, "custom_provider": { "name": "My OAuth App", "authorization_url": "https://provider.example.com/oauth/authorize", diff --git a/tests/fixtures/vault_kek_deleted.json b/tests/fixtures/vault_kek_deleted.json new file mode 100644 index 00000000..f60018a9 --- /dev/null +++ b/tests/fixtures/vault_kek_deleted.json @@ -0,0 +1,33 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.kek.deleted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/vault_kek_deleted_data.json b/tests/fixtures/vault_kek_deleted_data.json new file mode 100644 index 00000000..91d90957 --- /dev/null +++ b/tests/fixtures/vault_kek_deleted_data.json @@ -0,0 +1,7 @@ +{ + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY" +} diff --git a/tests/test_agents.py b/tests/test_agents.py new file mode 100644 index 00000000..5de11c65 --- /dev/null +++ b/tests/test_agents.py @@ -0,0 +1,389 @@ +# This file is auto-generated by oagen. Do not edit. + +import json + +import pytest +from workos import WorkOSClient, AsyncWorkOSClient +from tests.generated_helpers import load_fixture + +from workos.agents.models import ( + AgentAdminLinkClaimAttemptToExternalUserRequestUser, + AgentCredentialValidation, + AgentRegistration, + ClaimViewResponse, +) +from workos.common.models import AgentAdminValidateCredentialRequestType +from workos._errors import ( + AuthenticationError, + BadRequestError, + NotFoundError, + RateLimitExceededError, + ServerError, + UnprocessableEntityError, +) + + +class TestAgents: + def test_update_attempts(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("claim_view_response.json"), + ) + result = workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + assert isinstance(result, ClaimViewResponse) + assert result.id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + assert result.status == "unverified" + request = httpx_mock.get_request() + assert request.method == "PATCH" + assert request.url.path.endswith("/agents/claims/attempts") + body = json.loads(request.content) + assert body["type"] == "link_external_user" + assert body["claim_attempt_token"] == "test_claim_attempt_token" + assert "user" in body + + def test_create_validate(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("agent_credential_validation.json"), + ) + result = workos.agents.create_validate( + type=AgentAdminValidateCredentialRequestType("api_key"), + credential="test_credential", + ) + assert isinstance(result, AgentCredentialValidation) + assert result.valid is True + assert result.registration_id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + request = httpx_mock.get_request() + assert request.method == "POST" + assert request.url.path.endswith("/agents/credentials/validate") + body = json.loads(request.content) + assert body["type"] == AgentAdminValidateCredentialRequestType("api_key") + assert body["credential"] == "test_credential" + + def test_get_registration(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("agent_registration.json"), + ) + result = workos.agents.get_registration("test_id") + assert isinstance(result, AgentRegistration) + assert result.id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + assert result.organization_id == "org_01EHQMYV6MBK39QC5PZXHY59C3" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/agents/registrations/test_id") + + def test_update_attempts_with_request_options(self, workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("claim_view_response.json")) + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + request_options={"extra_headers": {"X-Custom": "value"}}, + ) + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" + + def test_update_attempts_unauthorized(self, workos, httpx_mock): + httpx_mock.add_response( + status_code=401, + json={"message": "Unauthorized"}, + ) + with pytest.raises(AuthenticationError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + + def test_update_attempts_not_found(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=404, json={"message": "Not found"}) + with pytest.raises(NotFoundError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + workos.close() + + def test_update_attempts_rate_limited(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response( + status_code=429, + headers={"Retry-After": "0"}, + json={"message": "Slow down"}, + ) + with pytest.raises(RateLimitExceededError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + workos.close() + + def test_update_attempts_server_error(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=500, json={"message": "Server error"}) + with pytest.raises(ServerError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + workos.close() + + def test_update_attempts_bad_request(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + workos.close() + + def test_update_attempts_unprocessable(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + workos.close() + + +class TestAsyncAgents: + @pytest.mark.asyncio + async def test_update_attempts(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("claim_view_response.json")) + result = await async_workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + assert isinstance(result, ClaimViewResponse) + assert result.id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + assert result.status == "unverified" + request = httpx_mock.get_request() + assert request.method == "PATCH" + assert request.url.path.endswith("/agents/claims/attempts") + + @pytest.mark.asyncio + async def test_create_validate(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("agent_credential_validation.json")) + result = await async_workos.agents.create_validate( + type=AgentAdminValidateCredentialRequestType("api_key"), + credential="test_credential", + ) + assert isinstance(result, AgentCredentialValidation) + assert result.valid is True + assert result.registration_id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + request = httpx_mock.get_request() + assert request.method == "POST" + assert request.url.path.endswith("/agents/credentials/validate") + + @pytest.mark.asyncio + async def test_get_registration(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("agent_registration.json")) + result = await async_workos.agents.get_registration("test_id") + assert isinstance(result, AgentRegistration) + assert result.id == "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY" + assert result.organization_id == "org_01EHQMYV6MBK39QC5PZXHY59C3" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/agents/registrations/test_id") + + @pytest.mark.asyncio + async def test_update_attempts_with_request_options(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("claim_view_response.json")) + await async_workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + request_options={"extra_headers": {"X-Custom": "value"}}, + ) + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" + + @pytest.mark.asyncio + async def test_update_attempts_unauthorized(self, async_workos, httpx_mock): + httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"}) + with pytest.raises(AuthenticationError): + await async_workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + + @pytest.mark.asyncio + async def test_update_attempts_not_found(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=404, json={"message": "Not found"}) + with pytest.raises(NotFoundError): + await workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_update_attempts_rate_limited(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response( + status_code=429, + headers={"Retry-After": "0"}, + json={"message": "Slow down"}, + ) + with pytest.raises(RateLimitExceededError): + await workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_update_attempts_server_error(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=500, json={"message": "Server error"}) + with pytest.raises(ServerError): + await workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_update_attempts_bad_request(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + await workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_update_attempts_unprocessable(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + await workos.agents.update_attempts( + type="link_external_user", + claim_attempt_token="test_claim_attempt_token", + user=AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + ), + ) + finally: + await workos.close() diff --git a/tests/test_agents_models_round_trip.py b/tests/test_agents_models_round_trip.py new file mode 100644 index 00000000..7c353cad --- /dev/null +++ b/tests/test_agents_models_round_trip.py @@ -0,0 +1,294 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.agents.models import ( + AgentAdminLinkClaimAttemptToExternalUserRequestUser, + AgentCredentialValidation, + AgentRegistration, + AgentRegistrationAgentIdentity, + AgentRegistrationClaim, + AgentRegistrationClaimClaimCompletion, + ClaimViewResponse, + ClaimViewResponseOrganization, +) + + +class TestModelRoundTrip: + def test_agent_registration_round_trip(self): + data = load_fixture("agent_registration.json") + instance = AgentRegistration.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistration.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_minimal_payload(self): + data = { + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "status": "verified", + "kind": "service_auth", + "claim": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistration.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["agent_identity"] == data["agent_identity"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["kind"] == data["kind"] + assert serialized["claim"] == data["claim"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_preserves_nullable_fields(self): + data = { + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "status": "verified", + "kind": "service_auth", + "claim": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistration.from_dict(data) + serialized = instance.to_dict() + assert serialized["claim"] is None + + def test_agent_registration_round_trips_unknown_enum_values(self): + data = { + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "status": "unexpected_agent_registration_status", + "kind": "service_auth", + "claim": { + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claim_completion": { + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + "claimed_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistration.from_dict(data) + assert instance.to_dict() == data + + def test_agent_credential_validation_round_trip(self): + data = load_fixture("agent_credential_validation.json") + instance = AgentCredentialValidation.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentCredentialValidation.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_credential_validation_minimal_payload(self): + data = {"valid": True, "registration_id": None, "expires_at": None} + instance = AgentCredentialValidation.from_dict(data) + serialized = instance.to_dict() + assert serialized["valid"] == data["valid"] + assert serialized["registration_id"] == data["registration_id"] + assert serialized["expires_at"] == data["expires_at"] + + def test_agent_credential_validation_preserves_nullable_fields(self): + data = {"valid": True, "registration_id": None, "expires_at": None} + instance = AgentCredentialValidation.from_dict(data) + serialized = instance.to_dict() + assert serialized["registration_id"] is None + assert serialized["expires_at"] is None + + def test_claim_view_response_round_trip(self): + data = load_fixture("claim_view_response.json") + instance = ClaimViewResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ClaimViewResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_claim_view_response_minimal_payload(self): + data = { + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "user_code": "BCDF-GHJK", + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + } + instance = ClaimViewResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["status"] == data["status"] + assert serialized["user_code"] == data["user_code"] + assert serialized["organizations"] == data["organizations"] + + def test_claim_view_response_round_trips_unknown_enum_values(self): + data = { + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unexpected_claim_view_response_status", + "user_code": "BCDF-GHJK", + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + } + instance = ClaimViewResponse.from_dict(data) + assert instance.to_dict() == data + + def test_claim_view_response_organization_round_trip(self): + data = load_fixture("claim_view_response_organization.json") + instance = ClaimViewResponseOrganization.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ClaimViewResponseOrganization.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_claim_view_response_organization_minimal_payload(self): + data = {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + instance = ClaimViewResponseOrganization.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_agent_registration_agent_identity_round_trip(self): + data = load_fixture("agent_registration_agent_identity.json") + instance = AgentRegistrationAgentIdentity.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationAgentIdentity.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_agent_identity_minimal_payload(self): + data = { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationAgentIdentity.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["userland_user_id"] == data["userland_user_id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_agent_identity_preserves_nullable_fields(self): + data = { + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationAgentIdentity.from_dict(data) + serialized = instance.to_dict() + assert serialized["userland_user_id"] is None + + def test_agent_registration_claim_round_trip(self): + data = load_fixture("agent_registration_claim.json") + instance = AgentRegistrationClaim.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaim.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_minimal_payload(self): + data = { + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claim_completion": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaim.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["claim_completion"] == data["claim_completion"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["expires_at"] == data["expires_at"] + + def test_agent_registration_claim_preserves_nullable_fields(self): + data = { + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claim_completion": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaim.from_dict(data) + serialized = instance.to_dict() + assert serialized["claim_completion"] is None + + def test_agent_admin_link_claim_attempt_to_external_user_request_user_round_trip( + self, + ): + data = load_fixture( + "agent_admin_link_claim_attempt_to_external_user_request_user.json" + ) + instance = AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_agent_admin_link_claim_attempt_to_external_user_request_user_minimal_payload( + self, + ): + data = {"email": "alice@example.com", "external_id": "user_abc123"} + instance = AgentAdminLinkClaimAttemptToExternalUserRequestUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["external_id"] == data["external_id"] + + def test_agent_registration_claim_claim_completion_round_trip(self): + data = load_fixture("agent_registration_claim_claim_completion.json") + instance = AgentRegistrationClaimClaimCompletion.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimClaimCompletion.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_claim_completion_minimal_payload(self): + data = { + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "expires_at": "2026-01-15T12:00:00.000Z", + "claimed_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaimClaimCompletion.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["claimed_at"] == data["claimed_at"] diff --git a/tests/test_api_keys.py b/tests/test_api_keys.py index e50de032..578a6e5c 100644 --- a/tests/test_api_keys.py +++ b/tests/test_api_keys.py @@ -77,6 +77,7 @@ def test_create_validation(self, workos, httpx_mock): ) result = workos.api_keys.create_validation(value="test_value") assert isinstance(result, ApiKeyValidationResponse) + assert result.agent_registration_id == "agent_reg_01EHZNVPK3SFK441A1RGBFSHRT" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/api_keys/validations") @@ -240,6 +241,7 @@ async def test_create_validation(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("api_key_validation_response.json")) result = await async_workos.api_keys.create_validation(value="test_value") assert isinstance(result, ApiKeyValidationResponse) + assert result.agent_registration_id == "agent_reg_01EHZNVPK3SFK441A1RGBFSHRT" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/api_keys/validations") diff --git a/tests/test_api_keys_models_round_trip.py b/tests/test_api_keys_models_round_trip.py new file mode 100644 index 00000000..9cfc63c8 --- /dev/null +++ b/tests/test_api_keys_models_round_trip.py @@ -0,0 +1,268 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.api_keys.models import ( + ApiKey, + ApiKeyOwner, + ApiKeyValidationResponse, + OrganizationApiKey, + OrganizationApiKeyOwner, + OrganizationApiKeyWithValue, + OrganizationApiKeyWithValueOwner, +) + + +class TestModelRoundTrip: + def test_api_key_round_trip(self): + data = load_fixture("api_key.json") + instance = ApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKey.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_api_key_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_api_key_validation_response_round_trip(self): + data = load_fixture("api_key_validation_response.json") + instance = ApiKeyValidationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyValidationResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_validation_response_minimal_payload(self): + data = {"api_key": None} + instance = ApiKeyValidationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["api_key"] == data["api_key"] + + def test_api_key_validation_response_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "api_key": { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": { + "type": "organization", + "id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + }, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + } + instance = ApiKeyValidationResponse.from_dict(data) + serialized = instance.to_dict() + assert "agent_registration_id" not in serialized + + def test_api_key_validation_response_preserves_nullable_fields(self): + data = { + "api_key": None, + "agent_registration_id": "agent_reg_01EHZNVPK3SFK441A1RGBFSHRT", + } + instance = ApiKeyValidationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["api_key"] is None + + def test_organization_api_key_round_trip(self): + data = load_fixture("organization_api_key.json") + instance = OrganizationApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationApiKey.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_api_key_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_api_key_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationApiKey.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_organization_api_key_with_value_round_trip(self): + data = load_fixture("organization_api_key_with_value.json") + instance = OrganizationApiKeyWithValue.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationApiKeyWithValue.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_api_key_with_value_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "value": "sk_abcdefghijklmnop123456", + } + instance = OrganizationApiKeyWithValue.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["value"] == data["value"] + + def test_organization_api_key_with_value_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHZNVPK3SFK441A1RGBFSHRT", + "owner": {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"}, + "name": "Production API Key", + "obfuscated_value": "sk_...3456", + "last_used_at": None, + "expires_at": None, + "permissions": ["posts:read", "posts:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "value": "sk_abcdefghijklmnop123456", + } + instance = OrganizationApiKeyWithValue.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_organization_api_key_with_value_owner_round_trip(self): + data = load_fixture("organization_api_key_with_value_owner.json") + instance = OrganizationApiKeyWithValueOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationApiKeyWithValueOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_api_key_with_value_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"} + instance = OrganizationApiKeyWithValueOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + + def test_organization_api_key_owner_round_trip(self): + data = load_fixture("organization_api_key_owner.json") + instance = OrganizationApiKeyOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationApiKeyOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_api_key_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"} + instance = OrganizationApiKeyOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + + def test_api_key_owner_round_trip(self): + data = load_fixture("api_key_owner.json") + instance = ApiKeyOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHZNVPK3SFK441A1RGBFSHRT"} + instance = ApiKeyOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] diff --git a/tests/test_client_api_models_round_trip.py b/tests/test_client_api_models_round_trip.py new file mode 100644 index 00000000..60256e54 --- /dev/null +++ b/tests/test_client_api_models_round_trip.py @@ -0,0 +1,23 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.client_api.models import ClientApiTokenResponse + + +class TestModelRoundTrip: + def test_client_api_token_response_round_trip(self): + data = load_fixture("client_api_token_response.json") + instance = ClientApiTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ClientApiTokenResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_client_api_token_response_minimal_payload(self): + data = {"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNlc3Npb24..."} + instance = ClientApiTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["token"] == data["token"] diff --git a/tests/test_common_models_round_trip.py b/tests/test_common_models_round_trip.py index 0980407c..851378db 100644 --- a/tests/test_common_models_round_trip.py +++ b/tests/test_common_models_round_trip.py @@ -5,13 +5,300 @@ from tests.generated_helpers import load_fixture from workos.common.models import ( + AccessTokenAgentRegistrationCredentialIssuedDataDetail, + ActionAuthenticationDenied, + ActionAuthenticationDeniedData, + ActionUserRegistrationDenied, + ActionUserRegistrationDeniedData, + AgentRegistrationClaimAttemptCreated, + AgentRegistrationClaimAttemptCreatedData, + AgentRegistrationClaimCompleted, + AgentRegistrationClaimCompletedData, + AgentRegistrationClaimCompletedDataClaimedBy, + AgentRegistrationCreated, + AgentRegistrationCreatedData, + AgentRegistrationCreatedDataAgentIdentity, + AgentRegistrationCredentialIssued, + AgentRegistrationCredentialIssuedData, + AgentRegistrationCredentialIssuedDataDetail, + AgentRegistrationDeleted, + AgentRegistrationDeletedData, + AgentRegistrationExpired, + AgentRegistrationExpiredData, + AgentRegistrationOrganizationSwitched, + AgentRegistrationOrganizationSwitchedData, + AgentRegistrationRevoked, + AgentRegistrationRevokedData, + ApiKeyCreated, + ApiKeyCreatedData, + ApiKeyCreatedDataOwner, + ApiKeyRevoked, + ApiKeyRevokedData, + ApiKeyRevokedDataOwner, + ApiKeyUpdated, + ApiKeyUpdatedData, + ApiKeyUpdatedDataOwner, + ApiKeyUpdatedDataPreviousAttribute, + AuthMethodMismatchError, + AuthenticationEmailVerificationFailed, + AuthenticationEmailVerificationFailedData, + AuthenticationEmailVerificationFailedDataError, + AuthenticationEmailVerificationSucceeded, + AuthenticationEmailVerificationSucceededData, + AuthenticationMFAFailed, + AuthenticationMFAFailedData, + AuthenticationMFAFailedDataError, + AuthenticationMFASucceeded, + AuthenticationMFASucceededData, + AuthenticationMagicAuthFailed, + AuthenticationMagicAuthFailedData, + AuthenticationMagicAuthFailedDataError, + AuthenticationMagicAuthSucceeded, + AuthenticationMagicAuthSucceededData, + AuthenticationOAuthFailed, + AuthenticationOAuthFailedData, + AuthenticationOAuthFailedDataError, + AuthenticationOAuthSucceeded, + AuthenticationOAuthSucceededData, + AuthenticationPasskeyFailed, + AuthenticationPasskeyFailedData, + AuthenticationPasskeyFailedDataError, + AuthenticationPasskeySucceeded, + AuthenticationPasskeySucceededData, + AuthenticationPasswordFailed, + AuthenticationPasswordFailedData, + AuthenticationPasswordFailedDataError, + AuthenticationPasswordSucceeded, + AuthenticationPasswordSucceededData, + AuthenticationRadarRiskDetected, + AuthenticationRadarRiskDetectedData, + AuthenticationReauthenticationSucceeded, + AuthenticationReauthenticationSucceededData, + AuthenticationSSOFailed, + AuthenticationSSOFailedData, + AuthenticationSSOFailedDataError, + AuthenticationSSOFailedDataSSO, + AuthenticationSSOStarted, + AuthenticationSSOStartedData, + AuthenticationSSOStartedDataSSO, + AuthenticationSSOSucceeded, + AuthenticationSSOSucceededData, + AuthenticationSSOSucceededDataSSO, + AuthenticationSSOTimedOut, + AuthenticationSSOTimedOutData, + AuthenticationSSOTimedOutDataError, + AuthenticationSSOTimedOutDataSSO, ConnectApplicationM2M, ConnectApplicationOAuth, ConnectApplicationOAuthRedirectUris, + ConnectionActivated, + ConnectionActivatedData, + ConnectionActivatedDataDomain, + ConnectionDeactivated, + ConnectionDeactivatedData, + ConnectionDeactivatedDataDomain, + ConnectionDeleted, + ConnectionDeletedData, + ConnectionSAMLCertificateRenewalRequired, + ConnectionSAMLCertificateRenewalRequiredData, + ConnectionSAMLCertificateRenewalRequiredDataCertificate, + ConnectionSAMLCertificateRenewalRequiredDataConnection, + ConnectionSAMLCertificateRenewed, + ConnectionSAMLCertificateRenewedData, + ConnectionSAMLCertificateRenewedDataCertificate, + ConnectionSAMLCertificateRenewedDataConnection, + DirectoryUser, + DirectoryUserEmail, + DsyncActivated, + DsyncActivatedData, + DsyncActivatedDataDomain, + DsyncDeleted, + DsyncDeletedData, + DsyncGroupCreated, + DsyncGroupDeleted, + DsyncGroupUpdated, + DsyncGroupUpdatedData, + DsyncGroupUserAdded, + DsyncGroupUserAddedData, + DsyncGroupUserRemoved, + DsyncGroupUserRemovedData, + DsyncTokenCreated, + DsyncTokenCreatedData, + DsyncTokenRevoked, + DsyncTokenRevokedData, + DsyncUserCreated, + DsyncUserDeleted, + DsyncUserUpdated, + DsyncUserUpdatedData, + DsyncUserUpdatedDataEmail, + EmailVerificationCreated, + EmailVerificationCreatedData, + ErrorResponse, + EventContext, + EventContextActor, + EventContextGoogleAnalyticsSession, + FlagCreated, + FlagCreatedContext, + FlagCreatedContextActor, + FlagCreatedData, + FlagCreatedDataOwner, + FlagDeleted, + FlagDeletedContext, + FlagDeletedContextActor, + FlagDeletedData, + FlagDeletedDataOwner, + FlagRuleUpdated, + FlagRuleUpdatedContext, + FlagRuleUpdatedContextActor, + FlagRuleUpdatedContextConfiguredTarget, + FlagRuleUpdatedContextConfiguredTargetOrganization, + FlagRuleUpdatedContextConfiguredTargetUser, + FlagRuleUpdatedContextPreviousAttribute, + FlagRuleUpdatedContextPreviousAttributeContext, + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTarget, + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization, + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetUser, + FlagRuleUpdatedContextPreviousAttributeData, + FlagRuleUpdatedData, + FlagRuleUpdatedDataOwner, + FlagUpdated, + FlagUpdatedContext, + FlagUpdatedContextActor, + FlagUpdatedContextPreviousAttribute, + FlagUpdatedContextPreviousAttributeData, + FlagUpdatedData, + FlagUpdatedDataOwner, + GroupCreated, + GroupDeleted, + GroupMemberAdded, + GroupMemberAddedData, + GroupMemberRemoved, + GroupMemberRemovedData, + GroupUpdated, + InvitationAccepted, + InvitationAcceptedData, + InvitationCreated, + InvitationCreatedData, + InvitationResent, + InvitationResentData, + InvitationRevoked, + InvitationRevokedData, + MagicAuthCreated, + MagicAuthCreatedData, + OrganizationCreated, + OrganizationCreatedData, + OrganizationCreatedDataDomain, + OrganizationDeleted, + OrganizationDeletedData, + OrganizationDeletedDataDomain, + OrganizationDomainCreated, + OrganizationDomainCreatedData, + OrganizationDomainDeleted, + OrganizationDomainDeletedData, + OrganizationDomainUpdated, + OrganizationDomainUpdatedData, + OrganizationDomainVerificationFailed, + OrganizationDomainVerificationFailedData, + OrganizationDomainVerificationFailedDataOrganizationDomain, + OrganizationDomainVerified, + OrganizationDomainVerifiedData, + OrganizationMembershipCreated, + OrganizationMembershipCreatedData, + OrganizationMembershipDeleted, + OrganizationMembershipDeletedData, + OrganizationMembershipUpdated, + OrganizationMembershipUpdatedData, + OrganizationRoleCreated, + OrganizationRoleCreatedData, + OrganizationRoleDeleted, + OrganizationRoleDeletedData, + OrganizationRoleUpdated, + OrganizationRoleUpdatedData, + OrganizationUpdated, + OrganizationUpdatedData, + OrganizationUpdatedDataDomain, + PasswordResetCreated, + PasswordResetCreatedData, + PasswordResetSucceeded, + PasswordResetSucceededData, + PermissionCreated, + PermissionCreatedData, + PermissionDeleted, + PermissionDeletedData, + PermissionUpdated, + PermissionUpdatedData, + PipeConnectedAccount, + PipesConnectedAccountConnected, + PipesConnectedAccountConnectionFailed, + PipesConnectedAccountConnectionFailedData, + PipesConnectedAccountDisconnected, + PipesConnectedAccountReauthorizationNeeded, + RadarChallengeCreated, + RadarChallengeCreatedData, + RoleCreated, + RoleCreatedData, + RoleDeleted, + RoleDeletedData, + RoleUpdated, + RoleUpdatedData, + SessionCreated, + SessionCreatedData, + SessionCreatedDataImpersonator, + SessionRevoked, + SessionRevokedData, + SessionRevokedDataImpersonator, + UserApiKeyCreatedDataOwner, + UserApiKeyRevokedDataOwner, + UserApiKeyUpdatedDataOwner, + UserCreated, + UserDeleted, + UserUpdated, + VaultByokKeyDeleted, + VaultByokKeyDeletedData, + VaultByokKeyVerificationCompleted, + VaultByokKeyVerificationCompletedData, + VaultDataCreated, + VaultDataCreatedData, + VaultDataDeleted, + VaultDataDeletedData, + VaultDataRead, + VaultDataReadData, + VaultDataUpdated, + VaultDataUpdatedData, + VaultDekDecrypted, + VaultDekDecryptedData, + VaultDekRead, + VaultDekReadData, + VaultKekCreated, + VaultKekCreatedData, + VaultKekDeleted, + VaultKekDeletedData, + VaultMetadataRead, + VaultMetadataReadData, + VaultNamesListed, + VaultNamesListedData, + WaitlistUser, + WaitlistUserApproved, + WaitlistUserCreated, + WaitlistUserDenied, ) class TestModelRoundTrip: + def test_error_response_round_trip(self): + data = load_fixture("error_response.json") + instance = ErrorResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ErrorResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_error_response_minimal_payload(self): + data = {"error": "Invalid request parameters."} + instance = ErrorResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["error"] == data["error"] + def test_connect_application_oauth_round_trip(self): data = load_fixture("connect_application_oauth.json") instance = ConnectApplicationOAuth.from_dict(data) @@ -156,3 +443,13286 @@ def test_connect_application_m2m_preserves_nullable_fields(self): instance = ConnectApplicationM2M.from_dict(data) serialized = instance.to_dict() assert serialized["description"] is None + + def test_event_context_actor_round_trip(self): + data = load_fixture("event_context_actor.json") + instance = EventContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EventContextActor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_event_context_actor_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = EventContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["source"] == data["source"] + assert serialized["name"] == data["name"] + + def test_event_context_actor_preserves_nullable_fields(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = EventContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] is None + + def test_event_context_actor_round_trips_unknown_enum_values(self): + data = { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "unexpected_event_context_actor_source", + "name": "Jane Doe", + } + instance = EventContextActor.from_dict(data) + assert instance.to_dict() == data + + def test_event_context_round_trip(self): + data = load_fixture("event_context.json") + instance = EventContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EventContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_event_context_minimal_payload(self): + data = {} + instance = EventContext.from_dict(data) + assert instance.to_dict() is not None + + def test_event_context_omits_absent_optional_non_nullable_fields(self): + data = {} + instance = EventContext.from_dict(data) + serialized = instance.to_dict() + assert "google_analytics_client_id" not in serialized + assert "google_analytics_sessions" not in serialized + assert "ajs_anonymous_id" not in serialized + assert "client_id" not in serialized + assert "actor" not in serialized + assert "previous_attributes" not in serialized + + def test_directory_user_round_trip(self): + data = load_fixture("directory_user.json") + instance = DirectoryUser.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryUser.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_user_minimal_payload(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["raw_attributes"] == data["raw_attributes"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_directory_user_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryUser.from_dict(data) + serialized = instance.to_dict() + assert "emails" not in serialized + assert "role" not in serialized + assert "roles" not in serialized + + def test_directory_user_preserves_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "first_name": None, + "last_name": None, + "name": None, + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": None, + "username": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] is None + assert serialized["first_name"] is None + assert serialized["last_name"] is None + assert serialized["name"] is None + assert serialized["job_title"] is None + assert serialized["username"] is None + + def test_directory_user_round_trips_unknown_enum_values(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "unexpected_directory_user_state", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryUser.from_dict(data) + assert instance.to_dict() == data + + def test_pipe_connected_account_round_trip(self): + data = load_fixture("pipe_connected_account.json") + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipeConnectedAccount.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipe_connected_account_minimal_payload(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["data_integration_id"] == data["data_integration_id"] + assert serialized["provider_slug"] == data["provider_slug"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["scopes"] == data["scopes"] + assert serialized["state"] == data["state"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_pipe_connected_account_preserves_nullable_fields(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized["user_id"] is None + assert serialized["organization_id"] is None + + def test_pipe_connected_account_round_trips_unknown_enum_values(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "unexpected_pipe_connected_account_state", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + assert instance.to_dict() == data + + def test_waitlist_user_round_trip(self): + data = load_fixture("waitlist_user.json") + instance = WaitlistUser.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = WaitlistUser.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_waitlist_user_minimal_payload(self): + data = { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["approved_at"] == data["approved_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_waitlist_user_preserves_nullable_fields(self): + data = { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["approved_at"] is None + + def test_waitlist_user_round_trips_unknown_enum_values(self): + data = { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "unexpected_waitlist_user_state", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUser.from_dict(data) + assert instance.to_dict() == data + + def test_action_authentication_denied_round_trip(self): + data = load_fixture("action_authentication_denied.json") + instance = ActionAuthenticationDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ActionAuthenticationDenied.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_action_authentication_denied_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "action.authentication.denied", + "data": { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ActionAuthenticationDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_action_authentication_denied_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "action.authentication.denied", + "data": { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ActionAuthenticationDenied.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_action_authentication_denied_data_round_trip(self): + data = load_fixture("action_authentication_denied_data.json") + instance = ActionAuthenticationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ActionAuthenticationDeniedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_action_authentication_denied_data_minimal_payload(self): + data = { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": None, + "email": "user@example.com", + "ip_address": None, + "user_agent": None, + } + instance = ActionAuthenticationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["action_endpoint_id"] == data["action_endpoint_id"] + assert serialized["action_execution_id"] == data["action_execution_id"] + assert serialized["type"] == data["type"] + assert serialized["verdict"] == data["verdict"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["email"] == data["email"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + + def test_action_authentication_denied_data_preserves_nullable_fields(self): + data = { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": None, + "email": "user@example.com", + "ip_address": None, + "user_agent": None, + } + instance = ActionAuthenticationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_action_user_registration_denied_round_trip(self): + data = load_fixture("action_user_registration_denied.json") + instance = ActionUserRegistrationDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ActionUserRegistrationDenied.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_action_user_registration_denied_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "action.user_registration.denied", + "data": { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "user_registration", + "verdict": "Deny", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ActionUserRegistrationDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_action_user_registration_denied_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "action.user_registration.denied", + "data": { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "user_registration", + "verdict": "Deny", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ActionUserRegistrationDenied.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_action_user_registration_denied_data_round_trip(self): + data = load_fixture("action_user_registration_denied_data.json") + instance = ActionUserRegistrationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ActionUserRegistrationDeniedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_action_user_registration_denied_data_minimal_payload(self): + data = { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "user_registration", + "verdict": "Deny", + "organization_id": None, + "email": "user@example.com", + "ip_address": None, + "user_agent": None, + } + instance = ActionUserRegistrationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["action_endpoint_id"] == data["action_endpoint_id"] + assert serialized["action_execution_id"] == data["action_execution_id"] + assert serialized["type"] == data["type"] + assert serialized["verdict"] == data["verdict"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["email"] == data["email"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + + def test_action_user_registration_denied_data_preserves_nullable_fields(self): + data = { + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "user_registration", + "verdict": "Deny", + "organization_id": None, + "email": "user@example.com", + "ip_address": None, + "user_agent": None, + } + instance = ActionUserRegistrationDeniedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_agent_registration_claim_attempt_created_round_trip(self): + data = load_fixture("agent_registration_claim_attempt_created.json") + instance = AgentRegistrationClaimAttemptCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimAttemptCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_attempt_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.attempt.created", + "data": { + "object": "agent_registration_claim_attempt", + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_claim_id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "login_hint": "jane@example.com", + "expires_at": "2024-01-15T10:35:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaimAttemptCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_claim_attempt_created_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.attempt.created", + "data": { + "object": "agent_registration_claim_attempt", + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_claim_id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "login_hint": "jane@example.com", + "expires_at": "2024-01-15T10:35:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaimAttemptCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_claim_attempt_created_data_round_trip(self): + data = load_fixture("agent_registration_claim_attempt_created_data.json") + instance = AgentRegistrationClaimAttemptCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimAttemptCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_attempt_created_data_minimal_payload(self): + data = { + "object": "agent_registration_claim_attempt", + "id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_claim_id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "login_hint": "jane@example.com", + "expires_at": "2024-01-15T10:35:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + } + instance = AgentRegistrationClaimAttemptCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["agent_registration_id"] == data["agent_registration_id"] + assert ( + serialized["agent_registration_claim_id"] + == data["agent_registration_claim_id"] + ) + assert serialized["login_hint"] == data["login_hint"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_claim_completed_round_trip(self): + data = load_fixture("agent_registration_claim_completed.json") + instance = AgentRegistrationClaimCompleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimCompleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_completed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.completed", + "data": { + "object": "agent_registration_claim", + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "completed_by_attempt_id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claimed_by": { + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": None, + }, + "completed_at": "2024-01-15T10:32:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:32:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaimCompleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_claim_completed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.claim.completed", + "data": { + "object": "agent_registration_claim", + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "completed_by_attempt_id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claimed_by": { + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": None, + }, + "completed_at": "2024-01-15T10:32:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:32:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationClaimCompleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_claim_completed_data_round_trip(self): + data = load_fixture("agent_registration_claim_completed_data.json") + instance = AgentRegistrationClaimCompletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimCompletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_completed_data_minimal_payload(self): + data = { + "object": "agent_registration_claim", + "id": "agent_reg_claim_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "completed_by_attempt_id": "agent_reg_claim_attempt_01EHWNCE74X7JSDV0X3SZ3KJNY", + "claimed_by": { + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": None, + }, + "completed_at": "2024-01-15T10:32:00.000Z", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:32:00.000Z", + } + instance = AgentRegistrationClaimCompletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["agent_registration_id"] == data["agent_registration_id"] + assert serialized["completed_by_attempt_id"] == data["completed_by_attempt_id"] + assert serialized["claimed_by"] == data["claimed_by"] + assert serialized["completed_at"] == data["completed_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_claim_completed_data_claimed_by_round_trip(self): + data = load_fixture("agent_registration_claim_completed_data_claimed_by.json") + instance = AgentRegistrationClaimCompletedDataClaimedBy.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationClaimCompletedDataClaimedBy.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_claim_completed_data_claimed_by_minimal_payload(self): + data = {"user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "organization_id": None} + instance = AgentRegistrationClaimCompletedDataClaimedBy.from_dict(data) + serialized = instance.to_dict() + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + + def test_agent_registration_created_round_trip(self): + data = load_fixture("agent_registration_created.json") + instance = AgentRegistrationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.created", + "data": { + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.created", + "data": { + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_created_data_round_trip(self): + data = load_fixture("agent_registration_created_data.json") + instance = AgentRegistrationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_created_data_minimal_payload(self): + data = { + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unverified", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + } + instance = AgentRegistrationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["agent_identity"] == data["agent_identity"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["kind"] == data["kind"] + assert serialized["method"] == data["method"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_created_data_round_trips_unknown_enum_values(self): + data = { + "object": "agent_registration", + "id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_identity": { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + }, + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unexpected_agent_registration_created_data_status", + "kind": "anonymous", + "method": "anonymous", + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + } + instance = AgentRegistrationCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_agent_registration_created_data_agent_identity_round_trip(self): + data = load_fixture("agent_registration_created_data_agent_identity.json") + instance = AgentRegistrationCreatedDataAgentIdentity.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCreatedDataAgentIdentity.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_created_data_agent_identity_minimal_payload(self): + data = { + "object": "agent_identity", + "id": "agent_identity_01EHWNCE74X7JSDV0X3SZ3KJNY", + "userland_user_id": None, + } + instance = AgentRegistrationCreatedDataAgentIdentity.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["userland_user_id"] == data["userland_user_id"] + + def test_agent_registration_credential_issued_round_trip(self): + data = load_fixture("agent_registration_credential_issued.json") + instance = AgentRegistrationCredentialIssued.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCredentialIssued.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_credential_issued_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.credential.issued", + "data": { + "object": "agent_registration_credential", + "id": "agent_reg_credential_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "detail": { + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV", + }, + "created_at": "2024-01-15T10:33:00.000Z", + "updated_at": "2024-01-15T10:33:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationCredentialIssued.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_credential_issued_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.credential.issued", + "data": { + "object": "agent_registration_credential", + "id": "agent_reg_credential_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "detail": { + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV", + }, + "created_at": "2024-01-15T10:33:00.000Z", + "updated_at": "2024-01-15T10:33:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationCredentialIssued.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_credential_issued_data_round_trip(self): + data = load_fixture("agent_registration_credential_issued_data.json") + instance = AgentRegistrationCredentialIssuedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCredentialIssuedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_credential_issued_data_minimal_payload(self): + data = { + "object": "agent_registration_credential", + "id": "agent_reg_credential_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "detail": { + "kind": "api_key", + "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV", + }, + "created_at": "2024-01-15T10:33:00.000Z", + "updated_at": "2024-01-15T10:33:00.000Z", + } + instance = AgentRegistrationCredentialIssuedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["agent_registration_id"] == data["agent_registration_id"] + assert serialized["detail"] == data["detail"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_agent_registration_credential_issued_data_detail_round_trip(self): + data = load_fixture("agent_registration_credential_issued_data_detail.json") + instance = AgentRegistrationCredentialIssuedDataDetail.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationCredentialIssuedDataDetail.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_credential_issued_data_detail_minimal_payload(self): + data = {"kind": "api_key", "api_key_id": "api_key_01HWDP91J37GZW2FT9GCEX8YWV"} + instance = AgentRegistrationCredentialIssuedDataDetail.from_dict(data) + serialized = instance.to_dict() + assert serialized["kind"] == data["kind"] + assert serialized["api_key_id"] == data["api_key_id"] + + def test_access_token_agent_registration_credential_issued_data_detail_round_trip( + self, + ): + data = load_fixture( + "access_token_agent_registration_credential_issued_data_detail.json" + ) + instance = AccessTokenAgentRegistrationCredentialIssuedDataDetail.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = AccessTokenAgentRegistrationCredentialIssuedDataDetail.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_access_token_agent_registration_credential_issued_data_detail_minimal_payload( + self, + ): + data = { + "kind": "access_token", + "jti": "jti_01EHWNCE74X7JSDV0X3SZ3KJNY", + "expires_at": "2024-01-15T11:30:00.000Z", + } + instance = AccessTokenAgentRegistrationCredentialIssuedDataDetail.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["kind"] == data["kind"] + assert serialized["jti"] == data["jti"] + assert serialized["expires_at"] == data["expires_at"] + + def test_agent_registration_deleted_round_trip(self): + data = load_fixture("agent_registration_deleted.json") + instance = AgentRegistrationDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.deleted", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.deleted", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_deleted_data_round_trip(self): + data = load_fixture("agent_registration_deleted_data.json") + instance = AgentRegistrationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_deleted_data_minimal_payload(self): + data = {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = AgentRegistrationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["agent_registration_id"] == data["agent_registration_id"] + + def test_agent_registration_expired_round_trip(self): + data = load_fixture("agent_registration_expired.json") + instance = AgentRegistrationExpired.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationExpired.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_expired_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.expired", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationExpired.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_expired_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.expired", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationExpired.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_expired_data_round_trip(self): + data = load_fixture("agent_registration_expired_data.json") + instance = AgentRegistrationExpiredData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationExpiredData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_expired_data_minimal_payload(self): + data = {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = AgentRegistrationExpiredData.from_dict(data) + serialized = instance.to_dict() + assert serialized["agent_registration_id"] == data["agent_registration_id"] + + def test_agent_registration_organization_switched_round_trip(self): + data = load_fixture("agent_registration_organization_switched.json") + instance = AgentRegistrationOrganizationSwitched.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationOrganizationSwitched.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_organization_switched_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.organization.switched", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "from_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "to_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNZ", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationOrganizationSwitched.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_organization_switched_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.organization.switched", + "data": { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "from_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "to_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNZ", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationOrganizationSwitched.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_organization_switched_data_round_trip(self): + data = load_fixture("agent_registration_organization_switched_data.json") + instance = AgentRegistrationOrganizationSwitchedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationOrganizationSwitchedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_organization_switched_data_minimal_payload(self): + data = { + "agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY", + "from_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "to_organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNZ", + } + instance = AgentRegistrationOrganizationSwitchedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["agent_registration_id"] == data["agent_registration_id"] + assert serialized["from_organization_id"] == data["from_organization_id"] + assert serialized["to_organization_id"] == data["to_organization_id"] + + def test_agent_registration_revoked_round_trip(self): + data = load_fixture("agent_registration_revoked.json") + instance = AgentRegistrationRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationRevoked.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_revoked_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.revoked", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_agent_registration_revoked_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "agent.registration.revoked", + "data": {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AgentRegistrationRevoked.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_agent_registration_revoked_data_round_trip(self): + data = load_fixture("agent_registration_revoked_data.json") + instance = AgentRegistrationRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AgentRegistrationRevokedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_agent_registration_revoked_data_minimal_payload(self): + data = {"agent_registration_id": "agent_reg_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = AgentRegistrationRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["agent_registration_id"] == data["agent_registration_id"] + + def test_api_key_created_round_trip(self): + data = load_fixture("api_key_created.json") + instance = ApiKeyCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.created", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_api_key_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.created", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_api_key_created_data_round_trip(self): + data = load_fixture("api_key_created_data.json") + instance = ApiKeyCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_created_data_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_api_key_created_data_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_api_key_created_data_owner_round_trip(self): + data = load_fixture("api_key_created_data_owner.json") + instance = ApiKeyCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyCreatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_created_data_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ApiKeyCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + + def test_user_api_key_created_data_owner_round_trip(self): + data = load_fixture("user_api_key_created_data_owner.json") + instance = UserApiKeyCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserApiKeyCreatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_api_key_created_data_owner_minimal_payload(self): + data = { + "type": "user", + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = UserApiKeyCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + + def test_api_key_revoked_round_trip(self): + data = load_fixture("api_key_revoked.json") + instance = ApiKeyRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyRevoked.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_revoked_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.revoked", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_api_key_revoked_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.revoked", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyRevoked.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_api_key_revoked_data_round_trip(self): + data = load_fixture("api_key_revoked_data.json") + instance = ApiKeyRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyRevokedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_revoked_data_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_api_key_revoked_data_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_api_key_revoked_data_owner_round_trip(self): + data = load_fixture("api_key_revoked_data_owner.json") + instance = ApiKeyRevokedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyRevokedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_revoked_data_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ApiKeyRevokedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + + def test_user_api_key_revoked_data_owner_round_trip(self): + data = load_fixture("user_api_key_revoked_data_owner.json") + instance = UserApiKeyRevokedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserApiKeyRevokedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_api_key_revoked_data_owner_minimal_payload(self): + data = { + "type": "user", + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = UserApiKeyRevokedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + + def test_api_key_updated_round_trip(self): + data = load_fixture("api_key_updated.json") + instance = ApiKeyUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.updated", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"expires_at": None}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_api_key_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "api_key.updated", + "data": { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": { + "type": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"expires_at": None}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ApiKeyUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_api_key_updated_data_round_trip(self): + data = load_fixture("api_key_updated_data.json") + instance = ApiKeyUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_updated_data_minimal_payload(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"expires_at": None}, + } + instance = ApiKeyUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["owner"] == data["owner"] + assert serialized["name"] == data["name"] + assert serialized["obfuscated_value"] == data["obfuscated_value"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["previous_attributes"] == data["previous_attributes"] + + def test_api_key_updated_data_preserves_nullable_fields(self): + data = { + "object": "api_key", + "id": "api_key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "owner": {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"}, + "name": "My API Key", + "obfuscated_value": "sk_test_...1234", + "last_used_at": None, + "expires_at": None, + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"expires_at": None}, + } + instance = ApiKeyUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None + + def test_api_key_updated_data_owner_round_trip(self): + data = load_fixture("api_key_updated_data_owner.json") + instance = ApiKeyUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyUpdatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_updated_data_owner_minimal_payload(self): + data = {"type": "organization", "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ApiKeyUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + + def test_user_api_key_updated_data_owner_round_trip(self): + data = load_fixture("user_api_key_updated_data_owner.json") + instance = UserApiKeyUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserApiKeyUpdatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_api_key_updated_data_owner_minimal_payload(self): + data = { + "type": "user", + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = UserApiKeyUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + + def test_api_key_updated_data_previous_attribute_round_trip(self): + data = load_fixture("api_key_updated_data_previous_attribute.json") + instance = ApiKeyUpdatedDataPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyUpdatedDataPreviousAttribute.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_updated_data_previous_attribute_minimal_payload(self): + data = {"expires_at": None} + instance = ApiKeyUpdatedDataPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert serialized["expires_at"] == data["expires_at"] + + def test_api_key_updated_data_previous_attribute_preserves_nullable_fields(self): + data = {"expires_at": None} + instance = ApiKeyUpdatedDataPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert serialized["expires_at"] is None + + def test_authentication_email_verification_failed_round_trip(self): + data = load_fixture("authentication_email_verification_failed.json") + instance = AuthenticationEmailVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationEmailVerificationFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_email_verification_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.email_verification_failed", + "data": { + "type": "email_verification", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationEmailVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_email_verification_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.email_verification_failed", + "data": { + "type": "email_verification", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationEmailVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_email_verification_failed_data_round_trip(self): + data = load_fixture("authentication_email_verification_failed_data.json") + instance = AuthenticationEmailVerificationFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationEmailVerificationFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_email_verification_failed_data_minimal_payload(self): + data = { + "type": "email_verification", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationEmailVerificationFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_email_verification_failed_data_preserves_nullable_fields( + self, + ): + data = { + "type": "email_verification", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationEmailVerificationFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_email_verification_failed_data_error_round_trip(self): + data = load_fixture("authentication_email_verification_failed_data_error.json") + instance = AuthenticationEmailVerificationFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationEmailVerificationFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_email_verification_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationEmailVerificationFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_email_verification_succeeded_round_trip(self): + data = load_fixture("authentication_email_verification_succeeded.json") + instance = AuthenticationEmailVerificationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationEmailVerificationSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_email_verification_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.email_verification_succeeded", + "data": { + "type": "email_verification", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationEmailVerificationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_email_verification_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.email_verification_succeeded", + "data": { + "type": "email_verification", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationEmailVerificationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_email_verification_succeeded_data_round_trip(self): + data = load_fixture("authentication_email_verification_succeeded_data.json") + instance = AuthenticationEmailVerificationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationEmailVerificationSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_email_verification_succeeded_data_minimal_payload(self): + data = { + "type": "email_verification", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationEmailVerificationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_email_verification_succeeded_data_preserves_nullable_fields( + self, + ): + data = { + "type": "email_verification", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationEmailVerificationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_magic_auth_failed_round_trip(self): + data = load_fixture("authentication_magic_auth_failed.json") + instance = AuthenticationMagicAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMagicAuthFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_magic_auth_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.magic_auth_failed", + "data": { + "type": "magic_auth", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMagicAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_magic_auth_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.magic_auth_failed", + "data": { + "type": "magic_auth", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMagicAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_magic_auth_failed_data_round_trip(self): + data = load_fixture("authentication_magic_auth_failed_data.json") + instance = AuthenticationMagicAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMagicAuthFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_magic_auth_failed_data_minimal_payload(self): + data = { + "type": "magic_auth", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationMagicAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_magic_auth_failed_data_preserves_nullable_fields(self): + data = { + "type": "magic_auth", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationMagicAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_magic_auth_failed_data_error_round_trip(self): + data = load_fixture("authentication_magic_auth_failed_data_error.json") + instance = AuthenticationMagicAuthFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMagicAuthFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_magic_auth_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationMagicAuthFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_magic_auth_succeeded_round_trip(self): + data = load_fixture("authentication_magic_auth_succeeded.json") + instance = AuthenticationMagicAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMagicAuthSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_magic_auth_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.magic_auth_succeeded", + "data": { + "type": "magic_auth", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMagicAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_magic_auth_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.magic_auth_succeeded", + "data": { + "type": "magic_auth", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMagicAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_magic_auth_succeeded_data_round_trip(self): + data = load_fixture("authentication_magic_auth_succeeded_data.json") + instance = AuthenticationMagicAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMagicAuthSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_magic_auth_succeeded_data_minimal_payload(self): + data = { + "type": "magic_auth", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationMagicAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_magic_auth_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "magic_auth", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationMagicAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_mfa_failed_round_trip(self): + data = load_fixture("authentication_mfa_failed.json") + instance = AuthenticationMFAFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMFAFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_mfa_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.mfa_failed", + "data": { + "type": "mfa", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMFAFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_mfa_failed_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.mfa_failed", + "data": { + "type": "mfa", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMFAFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_mfa_failed_data_round_trip(self): + data = load_fixture("authentication_mfa_failed_data.json") + instance = AuthenticationMFAFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMFAFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_mfa_failed_data_minimal_payload(self): + data = { + "type": "mfa", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationMFAFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_mfa_failed_data_preserves_nullable_fields(self): + data = { + "type": "mfa", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationMFAFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_mfa_failed_data_error_round_trip(self): + data = load_fixture("authentication_mfa_failed_data_error.json") + instance = AuthenticationMFAFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMFAFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_mfa_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationMFAFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_mfa_succeeded_round_trip(self): + data = load_fixture("authentication_mfa_succeeded.json") + instance = AuthenticationMFASucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMFASucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_mfa_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.mfa_succeeded", + "data": { + "type": "mfa", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMFASucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_mfa_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.mfa_succeeded", + "data": { + "type": "mfa", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationMFASucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_mfa_succeeded_data_round_trip(self): + data = load_fixture("authentication_mfa_succeeded_data.json") + instance = AuthenticationMFASucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationMFASucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_mfa_succeeded_data_minimal_payload(self): + data = { + "type": "mfa", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationMFASucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_mfa_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "mfa", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationMFASucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_oauth_failed_round_trip(self): + data = load_fixture("authentication_oauth_failed.json") + instance = AuthenticationOAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationOAuthFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_oauth_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.oauth_failed", + "data": { + "type": "oauth", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationOAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_oauth_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.oauth_failed", + "data": { + "type": "oauth", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationOAuthFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_oauth_failed_data_round_trip(self): + data = load_fixture("authentication_oauth_failed_data.json") + instance = AuthenticationOAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationOAuthFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_oauth_failed_data_minimal_payload(self): + data = { + "type": "oauth", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationOAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_oauth_failed_data_preserves_nullable_fields(self): + data = { + "type": "oauth", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationOAuthFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_oauth_failed_data_error_round_trip(self): + data = load_fixture("authentication_oauth_failed_data_error.json") + instance = AuthenticationOAuthFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationOAuthFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_oauth_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationOAuthFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_oauth_succeeded_round_trip(self): + data = load_fixture("authentication_oauth_succeeded.json") + instance = AuthenticationOAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationOAuthSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_oauth_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.oauth_succeeded", + "data": { + "type": "oauth", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationOAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_oauth_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.oauth_succeeded", + "data": { + "type": "oauth", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationOAuthSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_oauth_succeeded_data_round_trip(self): + data = load_fixture("authentication_oauth_succeeded_data.json") + instance = AuthenticationOAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationOAuthSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_oauth_succeeded_data_minimal_payload(self): + data = { + "type": "oauth", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": "user@example.com", + } + instance = AuthenticationOAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_oauth_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "oauth", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": "user@example.com", + } + instance = AuthenticationOAuthSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + + def test_authentication_passkey_failed_round_trip(self): + data = load_fixture("authentication_passkey_failed.json") + instance = AuthenticationPasskeyFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasskeyFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_passkey_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.passkey_failed", + "data": { + "type": "passkey", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasskeyFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_passkey_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.passkey_failed", + "data": { + "type": "passkey", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasskeyFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_passkey_failed_data_round_trip(self): + data = load_fixture("authentication_passkey_failed_data.json") + instance = AuthenticationPasskeyFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasskeyFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_passkey_failed_data_minimal_payload(self): + data = { + "type": "passkey", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationPasskeyFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_passkey_failed_data_preserves_nullable_fields(self): + data = { + "type": "passkey", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationPasskeyFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_passkey_failed_data_error_round_trip(self): + data = load_fixture("authentication_passkey_failed_data_error.json") + instance = AuthenticationPasskeyFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasskeyFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_passkey_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationPasskeyFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_passkey_succeeded_round_trip(self): + data = load_fixture("authentication_passkey_succeeded.json") + instance = AuthenticationPasskeySucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasskeySucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_passkey_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.passkey_succeeded", + "data": { + "type": "passkey", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasskeySucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_passkey_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.passkey_succeeded", + "data": { + "type": "passkey", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasskeySucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_passkey_succeeded_data_round_trip(self): + data = load_fixture("authentication_passkey_succeeded_data.json") + instance = AuthenticationPasskeySucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasskeySucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_passkey_succeeded_data_minimal_payload(self): + data = { + "type": "passkey", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationPasskeySucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_passkey_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "passkey", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationPasskeySucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_password_failed_round_trip(self): + data = load_fixture("authentication_password_failed.json") + instance = AuthenticationPasswordFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasswordFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_password_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.password_failed", + "data": { + "type": "password", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasswordFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_password_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.password_failed", + "data": { + "type": "password", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasswordFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_password_failed_data_round_trip(self): + data = load_fixture("authentication_password_failed_data.json") + instance = AuthenticationPasswordFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasswordFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_password_failed_data_minimal_payload(self): + data = { + "type": "password", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationPasswordFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["error"] == data["error"] + + def test_authentication_password_failed_data_preserves_nullable_fields(self): + data = { + "type": "password", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationPasswordFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_password_failed_data_error_round_trip(self): + data = load_fixture("authentication_password_failed_data_error.json") + instance = AuthenticationPasswordFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasswordFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_password_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationPasswordFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_password_succeeded_round_trip(self): + data = load_fixture("authentication_password_succeeded.json") + instance = AuthenticationPasswordSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasswordSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_password_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.password_succeeded", + "data": { + "type": "password", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasswordSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_password_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.password_succeeded", + "data": { + "type": "password", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationPasswordSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_password_succeeded_data_round_trip(self): + data = load_fixture("authentication_password_succeeded_data.json") + instance = AuthenticationPasswordSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationPasswordSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_password_succeeded_data_minimal_payload(self): + data = { + "type": "password", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationPasswordSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_password_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "password", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationPasswordSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_radar_risk_detected_round_trip(self): + data = load_fixture("authentication_radar_risk_detected.json") + instance = AuthenticationRadarRiskDetected.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationRadarRiskDetected.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_radar_risk_detected_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.radar_risk_detected", + "data": { + "auth_method": "password", + "action": "signup", + "control": "block", + "blocklist_type": "ip", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationRadarRiskDetected.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_radar_risk_detected_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.radar_risk_detected", + "data": { + "auth_method": "password", + "action": "signup", + "control": "block", + "blocklist_type": "ip", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationRadarRiskDetected.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_radar_risk_detected_data_round_trip(self): + data = load_fixture("authentication_radar_risk_detected_data.json") + instance = AuthenticationRadarRiskDetectedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationRadarRiskDetectedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_radar_risk_detected_data_minimal_payload(self): + data = { + "auth_method": "password", + "action": "signup", + "control": None, + "blocklist_type": None, + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationRadarRiskDetectedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["auth_method"] == data["auth_method"] + assert serialized["action"] == data["action"] + assert serialized["control"] == data["control"] + assert serialized["blocklist_type"] == data["blocklist_type"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_radar_risk_detected_data_preserves_nullable_fields(self): + data = { + "auth_method": "password", + "action": "signup", + "control": None, + "blocklist_type": None, + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationRadarRiskDetectedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["control"] is None + assert serialized["blocklist_type"] is None + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_radar_risk_detected_data_round_trips_unknown_enum_values( + self, + ): + data = { + "auth_method": "password", + "action": "unexpected_authentication_radar_risk_detected_data_action", + "control": "block", + "blocklist_type": "ip", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationRadarRiskDetectedData.from_dict(data) + assert instance.to_dict() == data + + def test_authentication_reauthentication_succeeded_round_trip(self): + data = load_fixture("authentication_reauthentication_succeeded.json") + instance = AuthenticationReauthenticationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationReauthenticationSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_reauthentication_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.reauthentication_succeeded", + "data": { + "type": "reauthentication", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationReauthenticationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_reauthentication_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.reauthentication_succeeded", + "data": { + "type": "reauthentication", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationReauthenticationSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_reauthentication_succeeded_data_round_trip(self): + data = load_fixture("authentication_reauthentication_succeeded_data.json") + instance = AuthenticationReauthenticationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationReauthenticationSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_reauthentication_succeeded_data_minimal_payload(self): + data = { + "type": "reauthentication", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationReauthenticationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_authentication_reauthentication_succeeded_data_preserves_nullable_fields( + self, + ): + data = { + "type": "reauthentication", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = AuthenticationReauthenticationSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + + def test_authentication_sso_failed_round_trip(self): + data = load_fixture("authentication_sso_failed.json") + instance = AuthenticationSSOFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_failed", + "data": { + "type": "sso", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_sso_failed_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_failed", + "data": { + "type": "sso", + "status": "failed", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_sso_failed_data_round_trip(self): + data = load_fixture("authentication_sso_failed_data.json") + instance = AuthenticationSSOFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_failed_data_minimal_payload(self): + data = { + "type": "sso", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationSSOFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["sso"] == data["sso"] + assert serialized["error"] == data["error"] + + def test_authentication_sso_failed_data_preserves_nullable_fields(self): + data = { + "type": "sso", + "status": "failed", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationSSOFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_sso_failed_data_sso_round_trip(self): + data = load_fixture("authentication_sso_failed_data_sso.json") + instance = AuthenticationSSOFailedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOFailedDataSSO.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_failed_data_sso_minimal_payload(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOFailedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["connection_id"] == data["connection_id"] + assert serialized["session_id"] == data["session_id"] + + def test_authentication_sso_failed_data_sso_preserves_nullable_fields(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOFailedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["connection_id"] is None + assert serialized["session_id"] is None + + def test_authentication_sso_failed_data_error_round_trip(self): + data = load_fixture("authentication_sso_failed_data_error.json") + instance = AuthenticationSSOFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOFailedDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_failed_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationSSOFailedDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_authentication_sso_started_round_trip(self): + data = load_fixture("authentication_sso_started.json") + instance = AuthenticationSSOStarted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOStarted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_started_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_started", + "data": { + "type": "sso", + "status": "started", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOStarted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_sso_started_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_started", + "data": { + "type": "sso", + "status": "started", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOStarted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_sso_started_data_round_trip(self): + data = load_fixture("authentication_sso_started_data.json") + instance = AuthenticationSSOStartedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOStartedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_started_data_minimal_payload(self): + data = { + "type": "sso", + "status": "started", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + } + instance = AuthenticationSSOStartedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["sso"] == data["sso"] + + def test_authentication_sso_started_data_preserves_nullable_fields(self): + data = { + "type": "sso", + "status": "started", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + } + instance = AuthenticationSSOStartedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_sso_started_data_sso_round_trip(self): + data = load_fixture("authentication_sso_started_data_sso.json") + instance = AuthenticationSSOStartedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOStartedDataSSO.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_started_data_sso_minimal_payload(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOStartedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["connection_id"] == data["connection_id"] + assert serialized["session_id"] == data["session_id"] + + def test_authentication_sso_started_data_sso_preserves_nullable_fields(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOStartedDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["connection_id"] is None + assert serialized["session_id"] is None + + def test_authentication_sso_succeeded_round_trip(self): + data = load_fixture("authentication_sso_succeeded.json") + instance = AuthenticationSSOSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_succeeded", + "data": { + "type": "sso", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_sso_succeeded_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_succeeded", + "data": { + "type": "sso", + "status": "succeeded", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_sso_succeeded_data_round_trip(self): + data = load_fixture("authentication_sso_succeeded_data.json") + instance = AuthenticationSSOSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_succeeded_data_minimal_payload(self): + data = { + "type": "sso", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + } + instance = AuthenticationSSOSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["sso"] == data["sso"] + + def test_authentication_sso_succeeded_data_preserves_nullable_fields(self): + data = { + "type": "sso", + "status": "succeeded", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + } + instance = AuthenticationSSOSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + + def test_authentication_sso_succeeded_data_sso_round_trip(self): + data = load_fixture("authentication_sso_succeeded_data_sso.json") + instance = AuthenticationSSOSucceededDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOSucceededDataSSO.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_succeeded_data_sso_minimal_payload(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOSucceededDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["connection_id"] == data["connection_id"] + assert serialized["session_id"] == data["session_id"] + + def test_authentication_sso_succeeded_data_sso_preserves_nullable_fields(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOSucceededDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["connection_id"] is None + assert serialized["session_id"] is None + + def test_authentication_sso_timed_out_round_trip(self): + data = load_fixture("authentication_sso_timed_out.json") + instance = AuthenticationSSOTimedOut.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOTimedOut.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_timed_out_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_timed_out", + "data": { + "type": "sso", + "status": "timed_out", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOTimedOut.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_authentication_sso_timed_out_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "authentication.sso_timed_out", + "data": { + "type": "sso", + "status": "timed_out", + "ip_address": "203.0.113.42", + "user_agent": "Mozilla/5.0", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationSSOTimedOut.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_authentication_sso_timed_out_data_round_trip(self): + data = load_fixture("authentication_sso_timed_out_data.json") + instance = AuthenticationSSOTimedOutData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOTimedOutData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_timed_out_data_minimal_payload(self): + data = { + "type": "sso", + "status": "timed_out", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationSSOTimedOutData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["status"] == data["status"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["sso"] == data["sso"] + assert serialized["error"] == data["error"] + + def test_authentication_sso_timed_out_data_preserves_nullable_fields(self): + data = { + "type": "sso", + "status": "timed_out", + "ip_address": None, + "user_agent": None, + "user_id": None, + "email": None, + "sso": { + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "session_id": "sess_01E4ZCR3C56J083X43JQXF3JK5", + }, + "error": { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + }, + } + instance = AuthenticationSSOTimedOutData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["user_id"] is None + assert serialized["email"] is None + + def test_authentication_sso_timed_out_data_sso_round_trip(self): + data = load_fixture("authentication_sso_timed_out_data_sso.json") + instance = AuthenticationSSOTimedOutDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOTimedOutDataSSO.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_timed_out_data_sso_minimal_payload(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOTimedOutDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["connection_id"] == data["connection_id"] + assert serialized["session_id"] == data["session_id"] + + def test_authentication_sso_timed_out_data_sso_preserves_nullable_fields(self): + data = {"organization_id": None, "connection_id": None, "session_id": None} + instance = AuthenticationSSOTimedOutDataSSO.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["connection_id"] is None + assert serialized["session_id"] is None + + def test_authentication_sso_timed_out_data_error_round_trip(self): + data = load_fixture("authentication_sso_timed_out_data_error.json") + instance = AuthenticationSSOTimedOutDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationSSOTimedOutDataError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_sso_timed_out_data_error_minimal_payload(self): + data = { + "code": "mfa_challenge_failed", + "message": "The MFA challenge has failed.", + } + instance = AuthenticationSSOTimedOutDataError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_connection_activated_round_trip(self): + data = load_fixture("connection_activated.json") + instance = ConnectionActivated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionActivated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_activated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.activated", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionActivated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_connection_activated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.activated", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionActivated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_connection_activated_data_round_trip(self): + data = load_fixture("connection_activated_data.json") + instance = ConnectionActivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionActivatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_activated_data_minimal_payload(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionActivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["connection_type"] == data["connection_type"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["external_key"] == data["external_key"] + assert serialized["status"] == data["status"] + assert serialized["domains"] == data["domains"] + + def test_connection_activated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionActivatedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_connection_activated_data_round_trips_unknown_enum_values(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "unexpected_connection_activated_data_state", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionActivatedData.from_dict(data) + assert instance.to_dict() == data + + def test_connection_activated_data_domain_round_trip(self): + data = load_fixture("connection_activated_data_domain.json") + instance = ConnectionActivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionActivatedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_activated_data_domain_minimal_payload(self): + data = { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + instance = ConnectionActivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["domain"] == data["domain"] + + def test_connection_deactivated_round_trip(self): + data = load_fixture("connection_deactivated.json") + instance = ConnectionDeactivated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDeactivated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_deactivated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.deactivated", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeactivated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_connection_deactivated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.deactivated", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeactivated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_connection_deactivated_data_round_trip(self): + data = load_fixture("connection_deactivated_data.json") + instance = ConnectionDeactivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDeactivatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_deactivated_data_minimal_payload(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionDeactivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["connection_type"] == data["connection_type"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["external_key"] == data["external_key"] + assert serialized["status"] == data["status"] + assert serialized["domains"] == data["domains"] + + def test_connection_deactivated_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionDeactivatedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_connection_deactivated_data_round_trips_unknown_enum_values(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "unexpected_connection_deactivated_data_state", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "linked", + "domains": [ + { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = ConnectionDeactivatedData.from_dict(data) + assert instance.to_dict() == data + + def test_connection_deactivated_data_domain_round_trip(self): + data = load_fixture("connection_deactivated_data_domain.json") + instance = ConnectionDeactivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDeactivatedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_deactivated_data_domain_minimal_payload(self): + data = { + "object": "connection_domain", + "id": "conn_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + instance = ConnectionDeactivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["domain"] == data["domain"] + + def test_connection_deleted_round_trip(self): + data = load_fixture("connection_deleted.json") + instance = ConnectionDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.deleted", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_connection_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.deleted", + "data": { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_connection_deleted_data_round_trip(self): + data = load_fixture("connection_deleted_data.json") + instance = ConnectionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_deleted_data_minimal_payload(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["connection_type"] == data["connection_type"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_connection_deleted_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "active", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_connection_deleted_data_round_trips_unknown_enum_values(self): + data = { + "object": "connection", + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "state": "unexpected_connection_deleted_data_state", + "name": "Acme SSO", + "connection_type": "OktaSAML", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_connection_saml_certificate_renewal_required_round_trip(self): + data = load_fixture("connection_saml_certificate_renewal_required.json") + instance = ConnectionSAMLCertificateRenewalRequired.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewalRequired.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewal_required_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.saml_certificate_renewal_required", + "data": { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + "is_expired": False, + }, + "days_until_expiry": 30, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewalRequired.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_connection_saml_certificate_renewal_required_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.saml_certificate_renewal_required", + "data": { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + "is_expired": False, + }, + "days_until_expiry": 30, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewalRequired.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_connection_saml_certificate_renewal_required_data_round_trip(self): + data = load_fixture("connection_saml_certificate_renewal_required_data.json") + instance = ConnectionSAMLCertificateRenewalRequiredData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewalRequiredData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewal_required_data_minimal_payload(self): + data = { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + "is_expired": False, + }, + "days_until_expiry": 30, + } + instance = ConnectionSAMLCertificateRenewalRequiredData.from_dict(data) + serialized = instance.to_dict() + assert serialized["connection"] == data["connection"] + assert serialized["certificate"] == data["certificate"] + assert serialized["days_until_expiry"] == data["days_until_expiry"] + + def test_connection_saml_certificate_renewal_required_data_connection_round_trip( + self, + ): + data = load_fixture( + "connection_saml_certificate_renewal_required_data_connection.json" + ) + instance = ConnectionSAMLCertificateRenewalRequiredDataConnection.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewalRequiredDataConnection.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewal_required_data_connection_minimal_payload( + self, + ): + data = {"id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ConnectionSAMLCertificateRenewalRequiredDataConnection.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + + def test_connection_saml_certificate_renewal_required_data_connection_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ConnectionSAMLCertificateRenewalRequiredDataConnection.from_dict( + data + ) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_connection_saml_certificate_renewal_required_data_certificate_round_trip( + self, + ): + data = load_fixture( + "connection_saml_certificate_renewal_required_data_certificate.json" + ) + instance = ConnectionSAMLCertificateRenewalRequiredDataCertificate.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewalRequiredDataCertificate.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewal_required_data_certificate_minimal_payload( + self, + ): + data = { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + "is_expired": False, + } + instance = ConnectionSAMLCertificateRenewalRequiredDataCertificate.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["certificate_type"] == data["certificate_type"] + assert serialized["expiry_date"] == data["expiry_date"] + assert serialized["is_expired"] == data["is_expired"] + + def test_connection_saml_certificate_renewal_required_data_certificate_round_trips_unknown_enum_values( + self, + ): + data = { + "certificate_type": "unexpected_connection_saml_certificate_renewal_required_data_certificate_certificate_type", + "expiry_date": "2026-01-15T12:00:00.000Z", + "is_expired": False, + } + instance = ConnectionSAMLCertificateRenewalRequiredDataCertificate.from_dict( + data + ) + assert instance.to_dict() == data + + def test_connection_saml_certificate_renewed_round_trip(self): + data = load_fixture("connection_saml_certificate_renewed.json") + instance = ConnectionSAMLCertificateRenewed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.saml_certificate_renewed", + "data": { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + }, + "renewed_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_connection_saml_certificate_renewed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "connection.saml_certificate_renewed", + "data": { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + }, + "renewed_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_connection_saml_certificate_renewed_data_round_trip(self): + data = load_fixture("connection_saml_certificate_renewed_data.json") + instance = ConnectionSAMLCertificateRenewedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewed_data_minimal_payload(self): + data = { + "connection": { + "id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "certificate": { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + }, + "renewed_at": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["connection"] == data["connection"] + assert serialized["certificate"] == data["certificate"] + assert serialized["renewed_at"] == data["renewed_at"] + + def test_connection_saml_certificate_renewed_data_connection_round_trip(self): + data = load_fixture("connection_saml_certificate_renewed_data_connection.json") + instance = ConnectionSAMLCertificateRenewedDataConnection.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewedDataConnection.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewed_data_connection_minimal_payload(self): + data = {"id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ConnectionSAMLCertificateRenewedDataConnection.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + + def test_connection_saml_certificate_renewed_data_connection_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"id": "conn_01EHWNCE74X7JSDV0X3SZ3KJNY"} + instance = ConnectionSAMLCertificateRenewedDataConnection.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_connection_saml_certificate_renewed_data_certificate_round_trip(self): + data = load_fixture("connection_saml_certificate_renewed_data_certificate.json") + instance = ConnectionSAMLCertificateRenewedDataCertificate.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionSAMLCertificateRenewedDataCertificate.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_saml_certificate_renewed_data_certificate_minimal_payload(self): + data = { + "certificate_type": "ResponseSigning", + "expiry_date": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewedDataCertificate.from_dict(data) + serialized = instance.to_dict() + assert serialized["certificate_type"] == data["certificate_type"] + assert serialized["expiry_date"] == data["expiry_date"] + + def test_connection_saml_certificate_renewed_data_certificate_round_trips_unknown_enum_values( + self, + ): + data = { + "certificate_type": "unexpected_connection_saml_certificate_renewed_data_certificate_certificate_type", + "expiry_date": "2026-01-15T12:00:00.000Z", + } + instance = ConnectionSAMLCertificateRenewedDataCertificate.from_dict(data) + assert instance.to_dict() == data + + def test_dsync_activated_round_trip(self): + data = load_fixture("dsync_activated.json") + instance = DsyncActivated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncActivated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_activated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.activated", + "data": { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncActivated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_activated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.activated", + "data": { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncActivated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_activated_data_round_trip(self): + data = load_fixture("dsync_activated_data.json") + instance = DsyncActivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncActivatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_activated_data_minimal_payload(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = DsyncActivatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["external_key"] == data["external_key"] + assert serialized["domains"] == data["domains"] + + def test_dsync_activated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = DsyncActivatedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_dsync_activated_data_round_trips_unknown_enum_values(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "unexpected_dsync_activated_data_type", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "external_key": "ext_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + ], + } + instance = DsyncActivatedData.from_dict(data) + assert instance.to_dict() == data + + def test_dsync_activated_data_domain_round_trip(self): + data = load_fixture("dsync_activated_data_domain.json") + instance = DsyncActivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncActivatedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_activated_data_domain_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHWNCE74X7JSDV0X3SZ3KJNY", + "domain": "acme.com", + } + instance = DsyncActivatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["domain"] == data["domain"] + + def test_dsync_deleted_round_trip(self): + data = load_fixture("dsync_deleted.json") + instance = DsyncDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.deleted", + "data": { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.deleted", + "data": { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_deleted_data_round_trip(self): + data = load_fixture("dsync_deleted_data.json") + instance = DsyncDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_deleted_data_minimal_payload(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_dsync_deleted_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "okta scim v2.0", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_dsync_deleted_data_round_trips_unknown_enum_values(self): + data = { + "object": "directory", + "id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "unexpected_dsync_deleted_data_type", + "state": "active", + "name": "Acme Directory", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_dsync_group_created_round_trip(self): + data = load_fixture("dsync_group_created.json") + instance = DsyncGroupCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.created", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_group_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.created", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_deleted_round_trip(self): + data = load_fixture("dsync_group_deleted.json") + instance = DsyncGroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.deleted", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_group_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.deleted", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_updated_round_trip(self): + data = load_fixture("dsync_group_updated.json") + instance = DsyncGroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.updated", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_group_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.updated", + "data": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_updated_data_round_trip(self): + data = load_fixture("dsync_group_updated_data.json") + instance = DsyncGroupUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_updated_data_minimal_payload(self): + data = { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["name"] == data["name"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_dsync_group_updated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "raw_attributes" not in serialized + assert "previous_attributes" not in serialized + + def test_dsync_token_created_round_trip(self): + data = load_fixture("dsync_token_created.json") + instance = DsyncTokenCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncTokenCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_token_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.token.created", + "data": { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_token_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.token.created", + "data": { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_token_created_data_round_trip(self): + data = load_fixture("dsync_token_created_data.json") + instance = DsyncTokenCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncTokenCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_token_created_data_minimal_payload(self): + data = { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["token_suffix"] == data["token_suffix"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_token_created_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_dsync_token_revoked_round_trip(self): + data = load_fixture("dsync_token_revoked.json") + instance = DsyncTokenRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncTokenRevoked.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_token_revoked_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.token.revoked", + "data": { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_token_revoked_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.token.revoked", + "data": { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenRevoked.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_token_revoked_data_round_trip(self): + data = load_fixture("dsync_token_revoked_data.json") + instance = DsyncTokenRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncTokenRevokedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_token_revoked_data_minimal_payload(self): + data = { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["token_suffix"] == data["token_suffix"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_token_revoked_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_token", + "id": "directory_token_01EHWNCE74X7JSDV0X3SZ3KJNY", + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "token_suffix": "a1b2", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncTokenRevokedData.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + + def test_dsync_group_user_added_round_trip(self): + data = load_fixture("dsync_group_user_added.json") + instance = DsyncGroupUserAdded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUserAdded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_user_added_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.user_added", + "data": { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUserAdded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_group_user_added_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.user_added", + "data": { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUserAdded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_user_added_data_round_trip(self): + data = load_fixture("dsync_group_user_added_data.json") + instance = DsyncGroupUserAddedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUserAddedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_user_added_data_minimal_payload(self): + data = { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = DsyncGroupUserAddedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["directory_id"] == data["directory_id"] + assert serialized["user"] == data["user"] + assert serialized["group"] == data["group"] + + def test_dsync_user_created_round_trip(self): + data = load_fixture("dsync_user_created.json") + instance = DsyncUserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncUserCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_user_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.created", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_user_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.created", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_user_deleted_round_trip(self): + data = load_fixture("dsync_user_deleted.json") + instance = DsyncUserDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncUserDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_user_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.deleted", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_user_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.deleted", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_user_removed_round_trip(self): + data = load_fixture("dsync_group_user_removed.json") + instance = DsyncGroupUserRemoved.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUserRemoved.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_user_removed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.user_removed", + "data": { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUserRemoved.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_group_user_removed_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.group.user_removed", + "data": { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncGroupUserRemoved.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_group_user_removed_data_round_trip(self): + data = load_fixture("dsync_group_user_removed_data.json") + instance = DsyncGroupUserRemovedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncGroupUserRemovedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_group_user_removed_data_minimal_payload(self): + data = { + "directory_id": "directory_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "group": { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = DsyncGroupUserRemovedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["directory_id"] == data["directory_id"] + assert serialized["user"] == data["user"] + assert serialized["group"] == data["group"] + + def test_dsync_user_updated_round_trip(self): + data = load_fixture("dsync_user_updated.json") + instance = DsyncUserUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncUserUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_user_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.updated", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_dsync_user_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "dsync.user.updated", + "data": { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_dsync_user_updated_data_round_trip(self): + data = load_fixture("dsync_user_updated_data.json") + instance = DsyncUserUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncUserUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_user_updated_data_minimal_payload(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["raw_attributes"] == data["raw_attributes"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_dsync_user_updated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DsyncUserUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "emails" not in serialized + assert "role" not in serialized + assert "roles" not in serialized + assert "previous_attributes" not in serialized + + def test_dsync_user_updated_data_preserves_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "first_name": None, + "last_name": None, + "name": None, + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": None, + "username": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + } + instance = DsyncUserUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] is None + assert serialized["first_name"] is None + assert serialized["last_name"] is None + assert serialized["name"] is None + assert serialized["job_title"] is None + assert serialized["username"] is None + + def test_dsync_user_updated_data_round_trips_unknown_enum_values(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "unexpected_dsync_user_updated_data_state", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "previous_attributes": {"key": {}}, + } + instance = DsyncUserUpdatedData.from_dict(data) + assert instance.to_dict() == data + + def test_dsync_user_updated_data_email_round_trip(self): + data = load_fixture("dsync_user_updated_data_email.json") + instance = DsyncUserUpdatedDataEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DsyncUserUpdatedDataEmail.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_dsync_user_updated_data_email_minimal_payload(self): + data = {} + instance = DsyncUserUpdatedDataEmail.from_dict(data) + assert instance.to_dict() is not None + + def test_dsync_user_updated_data_email_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"value": "marcelina.davis@example.com"} + instance = DsyncUserUpdatedDataEmail.from_dict(data) + serialized = instance.to_dict() + assert "primary" not in serialized + assert "type" not in serialized + + def test_dsync_user_updated_data_email_preserves_nullable_fields(self): + data = {"primary": True, "type": "work", "value": None} + instance = DsyncUserUpdatedDataEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized["value"] is None + + def test_email_verification_created_round_trip(self): + data = load_fixture("email_verification_created.json") + instance = EmailVerificationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EmailVerificationCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_email_verification_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "email_verification.created", + "data": { + "object": "email_verification", + "id": "email_verification_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = EmailVerificationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_email_verification_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "email_verification.created", + "data": { + "object": "email_verification", + "id": "email_verification_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = EmailVerificationCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_email_verification_created_data_round_trip(self): + data = load_fixture("email_verification_created_data.json") + instance = EmailVerificationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EmailVerificationCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_email_verification_created_data_minimal_payload(self): + data = { + "object": "email_verification", + "id": "email_verification_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = EmailVerificationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_created_round_trip(self): + data = load_fixture("flag_created.json") + instance = FlagCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "flag.created", + "data": { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe", + }, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + }, + } + instance = FlagCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + assert serialized["context"] == data["context"] + + def test_flag_created_data_round_trip(self): + data = load_fixture("flag_created_data.json") + instance = FlagCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_created_data_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_created_data_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_flag_created_data_owner_round_trip(self): + data = load_fixture("flag_created_data_owner.json") + instance = FlagCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagCreatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_created_data_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_flag_created_data_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagCreatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None + + def test_flag_created_context_round_trip(self): + data = load_fixture("flag_created_context.json") + instance = FlagCreatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagCreatedContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_created_context_minimal_payload(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + } + instance = FlagCreatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized["client_id"] == data["client_id"] + assert serialized["actor"] == data["actor"] + + def test_flag_created_context_actor_round_trip(self): + data = load_fixture("flag_created_context_actor.json") + instance = FlagCreatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagCreatedContextActor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_created_context_actor_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagCreatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["source"] == data["source"] + assert serialized["name"] == data["name"] + + def test_flag_created_context_actor_preserves_nullable_fields(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagCreatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] is None + + def test_flag_created_context_actor_round_trips_unknown_enum_values(self): + data = { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "unexpected_flag_created_context_actor_source", + "name": "Jane Doe", + } + instance = FlagCreatedContextActor.from_dict(data) + assert instance.to_dict() == data + + def test_flag_deleted_round_trip(self): + data = load_fixture("flag_deleted.json") + instance = FlagDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "flag.deleted", + "data": { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe", + }, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + }, + } + instance = FlagDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + assert serialized["context"] == data["context"] + + def test_flag_deleted_data_round_trip(self): + data = load_fixture("flag_deleted_data.json") + instance = FlagDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_deleted_data_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_deleted_data_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_flag_deleted_data_owner_round_trip(self): + data = load_fixture("flag_deleted_data_owner.json") + instance = FlagDeletedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagDeletedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_deleted_data_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagDeletedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_flag_deleted_data_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagDeletedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None + + def test_flag_deleted_context_round_trip(self): + data = load_fixture("flag_deleted_context.json") + instance = FlagDeletedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagDeletedContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_deleted_context_minimal_payload(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + } + instance = FlagDeletedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized["client_id"] == data["client_id"] + assert serialized["actor"] == data["actor"] + + def test_flag_deleted_context_actor_round_trip(self): + data = load_fixture("flag_deleted_context_actor.json") + instance = FlagDeletedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagDeletedContextActor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_deleted_context_actor_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagDeletedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["source"] == data["source"] + assert serialized["name"] == data["name"] + + def test_flag_deleted_context_actor_preserves_nullable_fields(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagDeletedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] is None + + def test_flag_deleted_context_actor_round_trips_unknown_enum_values(self): + data = { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "unexpected_flag_deleted_context_actor_source", + "name": "Jane Doe", + } + instance = FlagDeletedContextActor.from_dict(data) + assert instance.to_dict() == data + + def test_flag_rule_updated_round_trip(self): + data = load_fixture("flag_rule_updated.json") + instance = FlagRuleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "flag.rule_updated", + "data": { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe", + }, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + "access_type": "none", + "configured_targets": { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + "previous_attributes": { + "data": {"enabled": True, "default_value": False}, + "context": { + "access_type": "none", + "configured_targets": { + "organizations": [ + { + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Corp", + } + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + }, + }, + }, + } + instance = FlagRuleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + assert serialized["context"] == data["context"] + + def test_flag_rule_updated_data_round_trip(self): + data = load_fixture("flag_rule_updated_data.json") + instance = FlagRuleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_data_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagRuleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_rule_updated_data_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagRuleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_flag_rule_updated_data_owner_round_trip(self): + data = load_fixture("flag_rule_updated_data_owner.json") + instance = FlagRuleUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_data_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagRuleUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_flag_rule_updated_data_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagRuleUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None + + def test_flag_rule_updated_context_round_trip(self): + data = load_fixture("flag_rule_updated_context.json") + instance = FlagRuleUpdatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_minimal_payload(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + "access_type": "none", + "configured_targets": { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + "previous_attributes": { + "data": {"enabled": True, "default_value": False}, + "context": { + "access_type": "none", + "configured_targets": { + "organizations": [ + { + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Corp", + } + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + }, + }, + } + instance = FlagRuleUpdatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized["client_id"] == data["client_id"] + assert serialized["actor"] == data["actor"] + assert serialized["access_type"] == data["access_type"] + assert serialized["configured_targets"] == data["configured_targets"] + assert serialized["previous_attributes"] == data["previous_attributes"] + + def test_flag_rule_updated_context_round_trips_unknown_enum_values(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + "access_type": "unexpected_flag_rule_updated_context_access_type", + "configured_targets": { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + "previous_attributes": { + "data": {"enabled": True, "default_value": False}, + "context": { + "access_type": "none", + "configured_targets": { + "organizations": [ + { + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Corp", + } + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + }, + }, + } + instance = FlagRuleUpdatedContext.from_dict(data) + assert instance.to_dict() == data + + def test_flag_rule_updated_context_actor_round_trip(self): + data = load_fixture("flag_rule_updated_context_actor.json") + instance = FlagRuleUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextActor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_actor_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagRuleUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["source"] == data["source"] + assert serialized["name"] == data["name"] + + def test_flag_rule_updated_context_actor_preserves_nullable_fields(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagRuleUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] is None + + def test_flag_rule_updated_context_actor_round_trips_unknown_enum_values(self): + data = { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "unexpected_flag_rule_updated_context_actor_source", + "name": "Jane Doe", + } + instance = FlagRuleUpdatedContextActor.from_dict(data) + assert instance.to_dict() == data + + def test_flag_rule_updated_context_configured_target_round_trip(self): + data = load_fixture("flag_rule_updated_context_configured_target.json") + instance = FlagRuleUpdatedContextConfiguredTarget.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextConfiguredTarget.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_configured_target_minimal_payload(self): + data = { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "email": "user@example.com"} + ], + } + instance = FlagRuleUpdatedContextConfiguredTarget.from_dict(data) + serialized = instance.to_dict() + assert serialized["organizations"] == data["organizations"] + assert serialized["users"] == data["users"] + + def test_flag_rule_updated_context_configured_target_organization_round_trip(self): + data = load_fixture( + "flag_rule_updated_context_configured_target_organization.json" + ) + instance = FlagRuleUpdatedContextConfiguredTargetOrganization.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextConfiguredTargetOrganization.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_configured_target_organization_minimal_payload( + self, + ): + data = {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + instance = FlagRuleUpdatedContextConfiguredTargetOrganization.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_flag_rule_updated_context_configured_target_user_round_trip(self): + data = load_fixture("flag_rule_updated_context_configured_target_user.json") + instance = FlagRuleUpdatedContextConfiguredTargetUser.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextConfiguredTargetUser.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_configured_target_user_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "email": "user@example.com"} + instance = FlagRuleUpdatedContextConfiguredTargetUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + + def test_flag_rule_updated_context_previous_attribute_round_trip(self): + data = load_fixture("flag_rule_updated_context_previous_attribute.json") + instance = FlagRuleUpdatedContextPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextPreviousAttribute.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_minimal_payload(self): + data = {} + instance = FlagRuleUpdatedContextPreviousAttribute.from_dict(data) + assert instance.to_dict() is not None + + def test_flag_rule_updated_context_previous_attribute_omits_absent_optional_non_nullable_fields( + self, + ): + data = {} + instance = FlagRuleUpdatedContextPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert "data" not in serialized + assert "context" not in serialized + + def test_flag_rule_updated_context_previous_attribute_data_round_trip(self): + data = load_fixture("flag_rule_updated_context_previous_attribute_data.json") + instance = FlagRuleUpdatedContextPreviousAttributeData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextPreviousAttributeData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_data_minimal_payload(self): + data = {} + instance = FlagRuleUpdatedContextPreviousAttributeData.from_dict(data) + assert instance.to_dict() is not None + + def test_flag_rule_updated_context_previous_attribute_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = {} + instance = FlagRuleUpdatedContextPreviousAttributeData.from_dict(data) + serialized = instance.to_dict() + assert "enabled" not in serialized + assert "default_value" not in serialized + + def test_flag_rule_updated_context_previous_attribute_context_round_trip(self): + data = load_fixture("flag_rule_updated_context_previous_attribute_context.json") + instance = FlagRuleUpdatedContextPreviousAttributeContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextPreviousAttributeContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_context_minimal_payload(self): + data = {} + instance = FlagRuleUpdatedContextPreviousAttributeContext.from_dict(data) + assert instance.to_dict() is not None + + def test_flag_rule_updated_context_previous_attribute_context_omits_absent_optional_non_nullable_fields( + self, + ): + data = {} + instance = FlagRuleUpdatedContextPreviousAttributeContext.from_dict(data) + serialized = instance.to_dict() + assert "access_type" not in serialized + assert "configured_targets" not in serialized + + def test_flag_rule_updated_context_previous_attribute_context_round_trips_unknown_enum_values( + self, + ): + data = { + "access_type": "unexpected_flag_rule_updated_context_previous_attribute_context_access_type", + "configured_targets": { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + } + ], + }, + } + instance = FlagRuleUpdatedContextPreviousAttributeContext.from_dict(data) + assert instance.to_dict() == data + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_round_trip( + self, + ): + data = load_fixture( + "flag_rule_updated_context_previous_attribute_context_configured_target.json" + ) + instance = ( + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTarget.from_dict( + data + ) + ) + serialized = instance.to_dict() + assert serialized == data + restored = ( + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTarget.from_dict( + serialized + ) + ) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_minimal_payload( + self, + ): + data = { + "organizations": [ + {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + ], + "users": [ + {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "email": "user@example.com"} + ], + } + instance = ( + FlagRuleUpdatedContextPreviousAttributeContextConfiguredTarget.from_dict( + data + ) + ) + serialized = instance.to_dict() + assert serialized["organizations"] == data["organizations"] + assert serialized["users"] == data["users"] + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_organization_round_trip( + self, + ): + data = load_fixture( + "flag_rule_updated_context_previous_attribute_context_configured_target_organization.json" + ) + instance = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_organization_minimal_payload( + self, + ): + data = {"id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "name": "Acme Corp"} + instance = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_user_round_trip( + self, + ): + data = load_fixture( + "flag_rule_updated_context_previous_attribute_context_configured_target_user.json" + ) + instance = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetUser.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetUser.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_flag_rule_updated_context_previous_attribute_context_configured_target_user_minimal_payload( + self, + ): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "email": "user@example.com"} + instance = FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetUser.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + + def test_flag_updated_round_trip(self): + data = load_fixture("flag_updated.json") + instance = FlagUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "flag.updated", + "data": { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe", + }, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + "previous_attributes": { + "data": { + "name": "My Feature Flag", + "description": "Enables the new feature.", + "tags": ["beta", "release"], + "enabled": True, + "default_value": False, + } + }, + }, + } + instance = FlagUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + assert serialized["context"] == data["context"] + + def test_flag_updated_data_round_trip(self): + data = load_fixture("flag_updated_data.json") + instance = FlagUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_data_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_updated_data_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "environment_id": "environment_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FlagUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_flag_updated_data_owner_round_trip(self): + data = load_fixture("flag_updated_data_owner.json") + instance = FlagUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedDataOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_data_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_flag_updated_data_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagUpdatedDataOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None + + def test_flag_updated_context_round_trip(self): + data = load_fixture("flag_updated_context.json") + instance = FlagUpdatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedContext.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_context_minimal_payload(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + } + instance = FlagUpdatedContext.from_dict(data) + serialized = instance.to_dict() + assert serialized["client_id"] == data["client_id"] + assert serialized["actor"] == data["actor"] + + def test_flag_updated_context_omits_absent_optional_non_nullable_fields(self): + data = { + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe", + }, + } + instance = FlagUpdatedContext.from_dict(data) + serialized = instance.to_dict() + assert "previous_attributes" not in serialized + + def test_flag_updated_context_actor_round_trip(self): + data = load_fixture("flag_updated_context_actor.json") + instance = FlagUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedContextActor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_context_actor_minimal_payload(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["source"] == data["source"] + assert serialized["name"] == data["name"] + + def test_flag_updated_context_actor_preserves_nullable_fields(self): + data = {"id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", "source": "api", "name": None} + instance = FlagUpdatedContextActor.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] is None + + def test_flag_updated_context_actor_round_trips_unknown_enum_values(self): + data = { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "unexpected_flag_updated_context_actor_source", + "name": "Jane Doe", + } + instance = FlagUpdatedContextActor.from_dict(data) + assert instance.to_dict() == data + + def test_flag_updated_context_previous_attribute_round_trip(self): + data = load_fixture("flag_updated_context_previous_attribute.json") + instance = FlagUpdatedContextPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedContextPreviousAttribute.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_context_previous_attribute_minimal_payload(self): + data = {} + instance = FlagUpdatedContextPreviousAttribute.from_dict(data) + assert instance.to_dict() is not None + + def test_flag_updated_context_previous_attribute_omits_absent_optional_non_nullable_fields( + self, + ): + data = {} + instance = FlagUpdatedContextPreviousAttribute.from_dict(data) + serialized = instance.to_dict() + assert "data" not in serialized + + def test_flag_updated_context_previous_attribute_data_round_trip(self): + data = load_fixture("flag_updated_context_previous_attribute_data.json") + instance = FlagUpdatedContextPreviousAttributeData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagUpdatedContextPreviousAttributeData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_updated_context_previous_attribute_data_minimal_payload(self): + data = {} + instance = FlagUpdatedContextPreviousAttributeData.from_dict(data) + assert instance.to_dict() is not None + + def test_flag_updated_context_previous_attribute_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"description": "Enables the new feature."} + instance = FlagUpdatedContextPreviousAttributeData.from_dict(data) + serialized = instance.to_dict() + assert "name" not in serialized + assert "tags" not in serialized + assert "enabled" not in serialized + assert "default_value" not in serialized + + def test_flag_updated_context_previous_attribute_data_preserves_nullable_fields( + self, + ): + data = { + "name": "My Feature Flag", + "description": None, + "tags": ["beta", "release"], + "enabled": True, + "default_value": False, + } + instance = FlagUpdatedContextPreviousAttributeData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_group_created_round_trip(self): + data = load_fixture("group_created.json") + instance = GroupCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.created", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_group_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.created", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_group_deleted_round_trip(self): + data = load_fixture("group_deleted.json") + instance = GroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.deleted", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_group_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.deleted", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_group_member_added_round_trip(self): + data = load_fixture("group_member_added.json") + instance = GroupMemberAdded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupMemberAdded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_member_added_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.member_added", + "data": { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupMemberAdded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_group_member_added_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.member_added", + "data": { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupMemberAdded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_group_member_added_data_round_trip(self): + data = load_fixture("group_member_added_data.json") + instance = GroupMemberAddedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupMemberAddedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_member_added_data_minimal_payload(self): + data = { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = GroupMemberAddedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["group_id"] == data["group_id"] + assert ( + serialized["organization_membership_id"] + == data["organization_membership_id"] + ) + + def test_group_member_removed_round_trip(self): + data = load_fixture("group_member_removed.json") + instance = GroupMemberRemoved.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupMemberRemoved.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_member_removed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.member_removed", + "data": { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupMemberRemoved.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_group_member_removed_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.member_removed", + "data": { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupMemberRemoved.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_group_member_removed_data_round_trip(self): + data = load_fixture("group_member_removed_data.json") + instance = GroupMemberRemovedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupMemberRemovedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_member_removed_data_minimal_payload(self): + data = { + "group_id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = GroupMemberRemovedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["group_id"] == data["group_id"] + assert ( + serialized["organization_membership_id"] + == data["organization_membership_id"] + ) + + def test_group_updated_round_trip(self): + data = load_fixture("group_updated.json") + instance = GroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = GroupUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.updated", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_group_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "group.updated", + "data": { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": "The engineering team", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = GroupUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_invitation_accepted_round_trip(self): + data = load_fixture("invitation_accepted.json") + instance = InvitationAccepted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationAccepted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_accepted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.accepted", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationAccepted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_invitation_accepted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.accepted", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationAccepted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_invitation_accepted_data_round_trip(self): + data = load_fixture("invitation_accepted_data.json") + instance = InvitationAcceptedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationAcceptedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_accepted_data_minimal_payload(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationAcceptedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["accepted_at"] == data["accepted_at"] + assert serialized["revoked_at"] == data["revoked_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["inviter_user_id"] == data["inviter_user_id"] + assert serialized["accepted_user_id"] == data["accepted_user_id"] + assert serialized["role_slug"] == data["role_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_invitation_accepted_data_preserves_nullable_fields(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationAcceptedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["accepted_at"] is None + assert serialized["revoked_at"] is None + assert serialized["organization_id"] is None + assert serialized["inviter_user_id"] is None + assert serialized["accepted_user_id"] is None + assert serialized["role_slug"] is None + + def test_invitation_accepted_data_round_trips_unknown_enum_values(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "unexpected_invitation_accepted_data_state", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationAcceptedData.from_dict(data) + assert instance.to_dict() == data + + def test_invitation_created_round_trip(self): + data = load_fixture("invitation_created.json") + instance = InvitationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.created", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_invitation_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.created", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_invitation_created_data_round_trip(self): + data = load_fixture("invitation_created_data.json") + instance = InvitationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_created_data_minimal_payload(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["accepted_at"] == data["accepted_at"] + assert serialized["revoked_at"] == data["revoked_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["inviter_user_id"] == data["inviter_user_id"] + assert serialized["accepted_user_id"] == data["accepted_user_id"] + assert serialized["role_slug"] == data["role_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_invitation_created_data_preserves_nullable_fields(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["accepted_at"] is None + assert serialized["revoked_at"] is None + assert serialized["organization_id"] is None + assert serialized["inviter_user_id"] is None + assert serialized["accepted_user_id"] is None + assert serialized["role_slug"] is None + + def test_invitation_created_data_round_trips_unknown_enum_values(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "unexpected_invitation_created_data_state", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_invitation_resent_round_trip(self): + data = load_fixture("invitation_resent.json") + instance = InvitationResent.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationResent.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_resent_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.resent", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationResent.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_invitation_resent_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.resent", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationResent.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_invitation_resent_data_round_trip(self): + data = load_fixture("invitation_resent_data.json") + instance = InvitationResentData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationResentData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_resent_data_minimal_payload(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationResentData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["accepted_at"] == data["accepted_at"] + assert serialized["revoked_at"] == data["revoked_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["inviter_user_id"] == data["inviter_user_id"] + assert serialized["accepted_user_id"] == data["accepted_user_id"] + assert serialized["role_slug"] == data["role_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_invitation_resent_data_preserves_nullable_fields(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationResentData.from_dict(data) + serialized = instance.to_dict() + assert serialized["accepted_at"] is None + assert serialized["revoked_at"] is None + assert serialized["organization_id"] is None + assert serialized["inviter_user_id"] is None + assert serialized["accepted_user_id"] is None + assert serialized["role_slug"] is None + + def test_invitation_resent_data_round_trips_unknown_enum_values(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "unexpected_invitation_resent_data_state", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationResentData.from_dict(data) + assert instance.to_dict() == data + + def test_invitation_revoked_round_trip(self): + data = load_fixture("invitation_revoked.json") + instance = InvitationRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationRevoked.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_revoked_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.revoked", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_invitation_revoked_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "invitation.revoked", + "data": { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationRevoked.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_invitation_revoked_data_round_trip(self): + data = load_fixture("invitation_revoked_data.json") + instance = InvitationRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = InvitationRevokedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_invitation_revoked_data_minimal_payload(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["accepted_at"] == data["accepted_at"] + assert serialized["revoked_at"] == data["revoked_at"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["inviter_user_id"] == data["inviter_user_id"] + assert serialized["accepted_user_id"] == data["accepted_user_id"] + assert serialized["role_slug"] == data["role_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_invitation_revoked_data_preserves_nullable_fields(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": None, + "inviter_user_id": None, + "accepted_user_id": None, + "role_slug": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["accepted_at"] is None + assert serialized["revoked_at"] is None + assert serialized["organization_id"] is None + assert serialized["inviter_user_id"] is None + assert serialized["accepted_user_id"] is None + assert serialized["role_slug"] is None + + def test_invitation_revoked_data_round_trips_unknown_enum_values(self): + data = { + "object": "invitation", + "id": "invitation_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "unexpected_invitation_revoked_data_state", + "accepted_at": None, + "revoked_at": None, + "expires_at": "2026-01-15T12:00:00.000Z", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3", + "accepted_user_id": None, + "role_slug": "admin", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = InvitationRevokedData.from_dict(data) + assert instance.to_dict() == data + + def test_magic_auth_created_round_trip(self): + data = load_fixture("magic_auth_created.json") + instance = MagicAuthCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = MagicAuthCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_magic_auth_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "magic_auth.created", + "data": { + "object": "magic_auth", + "id": "magic_auth_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = MagicAuthCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_magic_auth_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "magic_auth.created", + "data": { + "object": "magic_auth", + "id": "magic_auth_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = MagicAuthCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_magic_auth_created_data_round_trip(self): + data = load_fixture("magic_auth_created_data.json") + instance = MagicAuthCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = MagicAuthCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_magic_auth_created_data_minimal_payload(self): + data = { + "object": "magic_auth", + "id": "magic_auth_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = MagicAuthCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_created_round_trip(self): + data = load_fixture("organization_created.json") + instance = OrganizationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.created", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.created", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_created_data_round_trip(self): + data = load_fixture("organization_created_data.json") + instance = OrganizationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_created_data_minimal_payload(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + assert serialized["domains"] == data["domains"] + assert serialized["metadata"] == data["metadata"] + assert serialized["external_id"] == data["external_id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_created_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "stripe_customer_id" not in serialized + + def test_organization_created_data_preserves_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["external_id"] is None + + def test_organization_created_data_domain_round_trip(self): + data = load_fixture("organization_created_data_domain.json") + instance = OrganizationCreatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationCreatedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_created_data_domain_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_created_data_domain_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_created_data_domain_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_created_data_domain_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationCreatedDataDomain.from_dict(data) + assert instance.to_dict() == data + + def test_organization_deleted_round_trip(self): + data = load_fixture("organization_deleted.json") + instance = OrganizationDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.deleted", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.deleted", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_deleted_data_round_trip(self): + data = load_fixture("organization_deleted_data.json") + instance = OrganizationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_deleted_data_minimal_payload(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + assert serialized["domains"] == data["domains"] + assert serialized["metadata"] == data["metadata"] + assert serialized["external_id"] == data["external_id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_deleted_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "stripe_customer_id" not in serialized + + def test_organization_deleted_data_preserves_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["external_id"] is None + + def test_organization_deleted_data_domain_round_trip(self): + data = load_fixture("organization_deleted_data_domain.json") + instance = OrganizationDeletedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDeletedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_deleted_data_domain_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_deleted_data_domain_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_deleted_data_domain_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_deleted_data_domain_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDeletedDataDomain.from_dict(data) + assert instance.to_dict() == data + + def test_organization_domain_created_round_trip(self): + data = load_fixture("organization_domain_created.json") + instance = OrganizationDomainCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.created", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_domain_created_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.created", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_domain_created_data_round_trip(self): + data = load_fixture("organization_domain_created_data.json") + instance = OrganizationDomainCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_created_data_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_created_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_created_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_created_data_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_domain_deleted_round_trip(self): + data = load_fixture("organization_domain_deleted.json") + instance = OrganizationDomainDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.deleted", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_domain_deleted_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.deleted", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_domain_deleted_data_round_trip(self): + data = load_fixture("organization_domain_deleted_data.json") + instance = OrganizationDomainDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_deleted_data_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_deleted_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_deleted_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_deleted_data_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_domain_updated_round_trip(self): + data = load_fixture("organization_domain_updated.json") + instance = OrganizationDomainUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.updated", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_domain_updated_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.updated", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_domain_updated_data_round_trip(self): + data = load_fixture("organization_domain_updated_data.json") + instance = OrganizationDomainUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_updated_data_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_updated_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_updated_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_updated_data_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainUpdatedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_domain_verification_failed_round_trip(self): + data = load_fixture("organization_domain_verification_failed.json") + instance = OrganizationDomainVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainVerificationFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_verification_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.verification_failed", + "data": { + "reason": "domain_verification_period_expired", + "organization_domain": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_domain_verification_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.verification_failed", + "data": { + "reason": "domain_verification_period_expired", + "organization_domain": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerificationFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_domain_verification_failed_data_round_trip(self): + data = load_fixture("organization_domain_verification_failed_data.json") + instance = OrganizationDomainVerificationFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainVerificationFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_verification_failed_data_minimal_payload(self): + data = { + "reason": "domain_verification_period_expired", + "organization_domain": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = OrganizationDomainVerificationFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["reason"] == data["reason"] + assert serialized["organization_domain"] == data["organization_domain"] + + def test_organization_domain_verification_failed_data_round_trips_unknown_enum_values( + self, + ): + data = { + "reason": "unexpected_organization_domain_verification_failed_data_reason", + "organization_domain": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = OrganizationDomainVerificationFailedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_domain_verification_failed_data_organization_domain_round_trip( + self, + ): + data = load_fixture( + "organization_domain_verification_failed_data_organization_domain.json" + ) + instance = OrganizationDomainVerificationFailedDataOrganizationDomain.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainVerificationFailedDataOrganizationDomain.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_organization_domain_verification_failed_data_organization_domain_minimal_payload( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerificationFailedDataOrganizationDomain.from_dict( + data + ) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_verification_failed_data_organization_domain_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerificationFailedDataOrganizationDomain.from_dict( + data + ) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_verification_failed_data_organization_domain_round_trips_unknown_enum_values( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_verification_failed_data_organization_domain_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerificationFailedDataOrganizationDomain.from_dict( + data + ) + assert instance.to_dict() == data + + def test_organization_domain_verified_round_trip(self): + data = load_fixture("organization_domain_verified.json") + instance = OrganizationDomainVerified.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainVerified.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_verified_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.verified", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerified.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_domain_verified_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_domain.verified", + "data": { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerified.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_domain_verified_data_round_trip(self): + data = load_fixture("organization_domain_verified_data.json") + instance = OrganizationDomainVerifiedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainVerifiedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_verified_data_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerifiedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_verified_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerifiedData.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_verified_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_verified_data_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomainVerifiedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_membership_created_round_trip(self): + data = load_fixture("organization_membership_created.json") + instance = OrganizationMembershipCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.created", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_membership_created_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.created", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_membership_created_data_round_trip(self): + data = load_fixture("organization_membership_created_data.json") + instance = OrganizationMembershipCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_created_data_minimal_payload(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["role"] == data["role"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["directory_managed"] == data["directory_managed"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_membership_created_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "roles" not in serialized + + def test_organization_membership_created_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unexpected_organization_membership_created_data_status", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_membership_deleted_round_trip(self): + data = load_fixture("organization_membership_deleted.json") + instance = OrganizationMembershipDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.deleted", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_membership_deleted_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.deleted", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_membership_deleted_data_round_trip(self): + data = load_fixture("organization_membership_deleted_data.json") + instance = OrganizationMembershipDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_deleted_data_minimal_payload(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["role"] == data["role"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["directory_managed"] == data["directory_managed"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_membership_deleted_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "roles" not in serialized + + def test_organization_membership_deleted_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unexpected_organization_membership_deleted_data_status", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_membership_updated_round_trip(self): + data = load_fixture("organization_membership_updated.json") + instance = OrganizationMembershipUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.updated", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_membership_updated_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_membership.updated", + "data": { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_membership_updated_data_round_trip(self): + data = load_fixture("organization_membership_updated_data.json") + instance = OrganizationMembershipUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembershipUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_updated_data_minimal_payload(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["role"] == data["role"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["directory_managed"] == data["directory_managed"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_membership_updated_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "active", + "role": {"slug": "admin"}, + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "roles" not in serialized + + def test_organization_membership_updated_data_round_trips_unknown_enum_values(self): + data = { + "object": "organization_membership", + "id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "status": "unexpected_organization_membership_updated_data_status", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "custom_attributes": {"key": {}}, + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationMembershipUpdatedData.from_dict(data) + assert instance.to_dict() == data + + def test_organization_role_created_round_trip(self): + data = load_fixture("organization_role_created.json") + instance = OrganizationRoleCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.created", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_role_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.created", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_role_created_data_round_trip(self): + data = load_fixture("organization_role_created_data.json") + instance = OrganizationRoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_created_data_minimal_payload(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_role_created_data_preserves_nullable_fields(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_organization_role_deleted_round_trip(self): + data = load_fixture("organization_role_deleted.json") + instance = OrganizationRoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.deleted", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_role_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.deleted", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_role_deleted_data_round_trip(self): + data = load_fixture("organization_role_deleted_data.json") + instance = OrganizationRoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_deleted_data_minimal_payload(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_role_deleted_data_preserves_nullable_fields(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_organization_role_updated_round_trip(self): + data = load_fixture("organization_role_updated.json") + instance = OrganizationRoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.updated", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_role_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization_role.updated", + "data": { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": "Can manage billing settings.", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_role_updated_data_round_trip(self): + data = load_fixture("organization_role_updated_data.json") + instance = OrganizationRoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationRoleUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_role_updated_data_minimal_payload(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["permissions"] == data["permissions"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_role_updated_data_preserves_nullable_fields(self): + data = { + "object": "organization_role", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing-admin", + "name": "Billing Administrator", + "description": None, + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationRoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_organization_updated_round_trip(self): + data = load_fixture("organization_updated.json") + instance = OrganizationUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.updated", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_organization_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "organization.updated", + "data": { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_organization_updated_data_round_trip(self): + data = load_fixture("organization_updated_data.json") + instance = OrganizationUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_updated_data_minimal_payload(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + assert serialized["domains"] == data["domains"] + assert serialized["metadata"] == data["metadata"] + assert serialized["external_id"] == data["external_id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_updated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "stripe_customer_id" not in serialized + + def test_organization_updated_data_preserves_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["external_id"] is None + + def test_organization_updated_data_domain_round_trip(self): + data = load_fixture("organization_updated_data_domain.json") + instance = OrganizationUpdatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationUpdatedDataDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_updated_data_domain_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_updated_data_domain_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedDataDomain.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_updated_data_domain_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_updated_data_domain_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationUpdatedDataDomain.from_dict(data) + assert instance.to_dict() == data + + def test_password_reset_created_round_trip(self): + data = load_fixture("password_reset_created.json") + instance = PasswordResetCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PasswordResetCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_password_reset_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "password_reset.created", + "data": { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_password_reset_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "password_reset.created", + "data": { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_password_reset_created_data_round_trip(self): + data = load_fixture("password_reset_created_data.json") + instance = PasswordResetCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PasswordResetCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_password_reset_created_data_minimal_payload(self): + data = { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + + def test_password_reset_succeeded_round_trip(self): + data = load_fixture("password_reset_succeeded.json") + instance = PasswordResetSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PasswordResetSucceeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_password_reset_succeeded_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "password_reset.succeeded", + "data": { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetSucceeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_password_reset_succeeded_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "password_reset.succeeded", + "data": { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetSucceeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_password_reset_succeeded_data_round_trip(self): + data = load_fixture("password_reset_succeeded_data.json") + instance = PasswordResetSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PasswordResetSucceededData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_password_reset_succeeded_data_minimal_payload(self): + data = { + "object": "password_reset", + "id": "password_reset_01E4ZCR3C56J083X43JQXF3JK5", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PasswordResetSucceededData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + + def test_permission_created_round_trip(self): + data = load_fixture("permission_created.json") + instance = PermissionCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.created", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_permission_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.created", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_permission_created_data_round_trip(self): + data = load_fixture("permission_created_data.json") + instance = PermissionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_created_data_minimal_payload(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["system"] == data["system"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_permission_created_data_preserves_nullable_fields(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_permission_deleted_round_trip(self): + data = load_fixture("permission_deleted.json") + instance = PermissionDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.deleted", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_permission_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.deleted", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_permission_deleted_data_round_trip(self): + data = load_fixture("permission_deleted_data.json") + instance = PermissionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_deleted_data_minimal_payload(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["system"] == data["system"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_permission_deleted_data_preserves_nullable_fields(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_permission_updated_round_trip(self): + data = load_fixture("permission_updated.json") + instance = PermissionUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.updated", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_permission_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.updated", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_permission_updated_data_round_trip(self): + data = load_fixture("permission_updated_data.json") + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_updated_data_minimal_payload(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["system"] == data["system"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_permission_updated_data_preserves_nullable_fields(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_pipes_connected_account_connected_round_trip(self): + data = load_fixture("pipes_connected_account_connected.json") + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountConnected.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_connected_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_connected_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_pipes_connected_account_connection_failed_round_trip(self): + data = load_fixture("pipes_connected_account_connection_failed.json") + instance = PipesConnectedAccountConnectionFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountConnectionFailed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_connection_failed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connection_failed", + "data": { + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "error_code": "authorization_code_exchange_error", + "error_reason": "The authorization code has expired.", + "provider_error": "access_denied", + "provider_error_description": "The user denied the authorization request.", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnectionFailed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_connection_failed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connection_failed", + "data": { + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "error_code": "authorization_code_exchange_error", + "error_reason": "The authorization code has expired.", + "provider_error": "access_denied", + "provider_error_description": "The user denied the authorization request.", + "created_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnectionFailed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_pipes_connected_account_connection_failed_data_round_trip(self): + data = load_fixture("pipes_connected_account_connection_failed_data.json") + instance = PipesConnectedAccountConnectionFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountConnectionFailedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_connection_failed_data_minimal_payload(self): + data = { + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "error_code": "authorization_code_exchange_error", + "error_reason": None, + "provider_error": None, + "provider_error_description": None, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnectionFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["data_integration_id"] == data["data_integration_id"] + assert serialized["provider_slug"] == data["provider_slug"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["error_code"] == data["error_code"] + assert serialized["error_reason"] == data["error_reason"] + assert serialized["provider_error"] == data["provider_error"] + assert ( + serialized["provider_error_description"] + == data["provider_error_description"] + ) + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_connection_failed_data_preserves_nullable_fields( + self, + ): + data = { + "object": "connection_failed", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "error_code": "authorization_code_exchange_error", + "error_reason": None, + "provider_error": None, + "provider_error_description": None, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnectionFailedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["user_id"] is None + assert serialized["organization_id"] is None + assert serialized["error_reason"] is None + assert serialized["provider_error"] is None + assert serialized["provider_error_description"] is None + + def test_pipes_connected_account_disconnected_round_trip(self): + data = load_fixture("pipes_connected_account_disconnected.json") + instance = PipesConnectedAccountDisconnected.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountDisconnected.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_disconnected_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.disconnected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountDisconnected.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_disconnected_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.disconnected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountDisconnected.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_pipes_connected_account_reauthorization_needed_round_trip(self): + data = load_fixture("pipes_connected_account_reauthorization_needed.json") + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountReauthorizationNeeded.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_reauthorization_needed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.reauthorization_needed", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_reauthorization_needed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.reauthorization_needed", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_radar_challenge_created_round_trip(self): + data = load_fixture("radar_challenge_created.json") + instance = RadarChallengeCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RadarChallengeCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_radar_challenge_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "radar.challenge_created", + "data": { + "type": "email", + "radar_challenge_id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RadarChallengeCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_radar_challenge_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "radar.challenge_created", + "data": { + "type": "email", + "radar_challenge_id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RadarChallengeCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_radar_challenge_created_data_round_trip(self): + data = load_fixture("radar_challenge_created_data.json") + instance = RadarChallengeCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RadarChallengeCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_radar_challenge_created_data_minimal_payload(self): + data = { + "type": "email", + "radar_challenge_id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "user@example.com", + } + instance = RadarChallengeCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["type"] == data["type"] + assert serialized["radar_challenge_id"] == data["radar_challenge_id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + + def test_role_created_round_trip(self): + data = load_fixture("role_created.json") + instance = RoleCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.created", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_role_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.created", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_role_created_data_round_trip(self): + data = load_fixture("role_created_data.json") + instance = RoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_created_data_minimal_payload(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["slug"] == data["slug"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_role_created_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "permissions" not in serialized + + def test_role_deleted_round_trip(self): + data = load_fixture("role_deleted.json") + instance = RoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.deleted", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_role_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.deleted", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_role_deleted_data_round_trip(self): + data = load_fixture("role_deleted_data.json") + instance = RoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_deleted_data_minimal_payload(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["slug"] == data["slug"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_role_deleted_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleDeletedData.from_dict(data) + serialized = instance.to_dict() + assert "permissions" not in serialized + + def test_role_updated_round_trip(self): + data = load_fixture("role_updated.json") + instance = RoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.updated", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_role_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "role.updated", + "data": { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "permissions": ["users:read", "users:write"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_role_updated_data_round_trip(self): + data = load_fixture("role_updated_data.json") + instance = RoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RoleUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_role_updated_data_minimal_payload(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["slug"] == data["slug"] + assert serialized["resource_type_slug"] == data["resource_type_slug"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_role_updated_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "role", + "slug": "admin", + "resource_type_slug": "organization", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = RoleUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert "permissions" not in serialized + + def test_session_created_round_trip(self): + data = load_fixture("session_created.json") + instance = SessionCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "session.created", + "data": { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_session_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "session.created", + "data": { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_session_created_data_round_trip(self): + data = load_fixture("session_created_data.json") + instance = SessionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_created_data_minimal_payload(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["auth_method"] == data["auth_method"] + assert serialized["status"] == data["status"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["ended_at"] == data["ended_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_session_created_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "ip_address": "198.51.100.42", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert "impersonator" not in serialized + assert "organization_id" not in serialized + + def test_session_created_data_preserves_nullable_fields(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": None, + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["ended_at"] is None + + def test_session_created_data_round_trips_unknown_enum_values(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "unexpected_session_created_data_auth_method", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_session_created_data_impersonator_round_trip(self): + data = load_fixture("session_created_data_impersonator.json") + instance = SessionCreatedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionCreatedDataImpersonator.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_created_data_impersonator_minimal_payload(self): + data = {"email": "admin@foocorp.com", "reason": None} + instance = SessionCreatedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["reason"] == data["reason"] + + def test_session_created_data_impersonator_preserves_nullable_fields(self): + data = {"email": "admin@foocorp.com", "reason": None} + instance = SessionCreatedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized["reason"] is None + + def test_session_revoked_round_trip(self): + data = load_fixture("session_revoked.json") + instance = SessionRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionRevoked.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_revoked_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "session.revoked", + "data": { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevoked.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_session_revoked_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "session.revoked", + "data": { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevoked.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_session_revoked_data_round_trip(self): + data = load_fixture("session_revoked_data.json") + instance = SessionRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionRevokedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_revoked_data_minimal_payload(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "ip_address": None, + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["ip_address"] == data["ip_address"] + assert serialized["user_agent"] == data["user_agent"] + assert serialized["user_id"] == data["user_id"] + assert serialized["auth_method"] == data["auth_method"] + assert serialized["status"] == data["status"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["ended_at"] == data["ended_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_session_revoked_data_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "ip_address": "198.51.100.42", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevokedData.from_dict(data) + serialized = instance.to_dict() + assert "impersonator" not in serialized + assert "organization_id" not in serialized + + def test_session_revoked_data_preserves_nullable_fields(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": None, + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": None, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "sso", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevokedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["ip_address"] is None + assert serialized["user_agent"] is None + assert serialized["ended_at"] is None + + def test_session_revoked_data_round_trips_unknown_enum_values(self): + data = { + "object": "session", + "id": "session_01H93ZY4F80QPBEZ1R5B2SHQG8", + "impersonator": { + "email": "admin@foocorp.com", + "reason": "Investigating an issue with the customer's account.", + }, + "ip_address": "198.51.100.42", + "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "auth_method": "unexpected_session_revoked_data_auth_method", + "status": "active", + "expires_at": "2026-01-15T12:00:00.000Z", + "ended_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = SessionRevokedData.from_dict(data) + assert instance.to_dict() == data + + def test_session_revoked_data_impersonator_round_trip(self): + data = load_fixture("session_revoked_data_impersonator.json") + instance = SessionRevokedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SessionRevokedDataImpersonator.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_session_revoked_data_impersonator_minimal_payload(self): + data = {"email": "admin@foocorp.com", "reason": None} + instance = SessionRevokedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["reason"] == data["reason"] + + def test_session_revoked_data_impersonator_preserves_nullable_fields(self): + data = {"email": "admin@foocorp.com", "reason": None} + instance = SessionRevokedDataImpersonator.from_dict(data) + serialized = instance.to_dict() + assert serialized["reason"] is None + + def test_user_created_round_trip(self): + data = load_fixture("user_created.json") + instance = UserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.created", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_user_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.created", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_user_deleted_round_trip(self): + data = load_fixture("user_deleted.json") + instance = UserDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.deleted", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_user_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.deleted", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_user_updated_round_trip(self): + data = load_fixture("user_updated.json") + instance = UserUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.updated", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_user_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "user.updated", + "data": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = UserUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_byok_key_deleted_round_trip(self): + data = load_fixture("vault_byok_key_deleted.json") + instance = VaultByokKeyDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultByokKeyDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_byok_key_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.byok_key.deleted", + "data": { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultByokKeyDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_byok_key_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.byok_key.deleted", + "data": { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultByokKeyDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_byok_key_deleted_data_round_trip(self): + data = load_fixture("vault_byok_key_deleted_data.json") + instance = VaultByokKeyDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultByokKeyDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_byok_key_deleted_data_minimal_payload(self): + data = { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + } + instance = VaultByokKeyDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["key_provider"] == data["key_provider"] + + def test_vault_byok_key_deleted_data_round_trips_unknown_enum_values(self): + data = { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "unexpected_vault_byok_key_deleted_data_key_provider", + } + instance = VaultByokKeyDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_byok_key_verification_completed_round_trip(self): + data = load_fixture("vault_byok_key_verification_completed.json") + instance = VaultByokKeyVerificationCompleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultByokKeyVerificationCompleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_byok_key_verification_completed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.byok_key.verification_completed", + "data": { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + "verified": True, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultByokKeyVerificationCompleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_byok_key_verification_completed_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.byok_key.verification_completed", + "data": { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + "verified": True, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultByokKeyVerificationCompleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_byok_key_verification_completed_data_round_trip(self): + data = load_fixture("vault_byok_key_verification_completed_data.json") + instance = VaultByokKeyVerificationCompletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultByokKeyVerificationCompletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_byok_key_verification_completed_data_minimal_payload(self): + data = { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "AWS_KMS", + "verified": True, + } + instance = VaultByokKeyVerificationCompletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert serialized["key_provider"] == data["key_provider"] + assert serialized["verified"] == data["verified"] + + def test_vault_byok_key_verification_completed_data_round_trips_unknown_enum_values( + self, + ): + data = { + "organization_id": "org_01EHT88Z8J8795GZNQ4ZP1J81T", + "key_provider": "unexpected_vault_byok_key_verification_completed_data_key_provider", + "verified": True, + } + instance = VaultByokKeyVerificationCompletedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_data_created_round_trip(self): + data = load_fixture("vault_data_created.json") + instance = VaultDataCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.created", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_data_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.created", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_data_created_data_round_trip(self): + data = load_fixture("vault_data_created_data.json") + instance = VaultDataCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_created_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + } + instance = VaultDataCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["kv_name"] == data["kv_name"] + assert serialized["key_id"] == data["key_id"] + assert serialized["key_context"] == data["key_context"] + + def test_vault_data_created_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_data_created_data_actor_source", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + } + instance = VaultDataCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_data_deleted_round_trip(self): + data = load_fixture("vault_data_deleted.json") + instance = VaultDataDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.deleted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_data_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.deleted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_data_deleted_data_round_trip(self): + data = load_fixture("vault_data_deleted_data.json") + instance = VaultDataDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_deleted_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + } + instance = VaultDataDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["kv_name"] == data["kv_name"] + + def test_vault_data_deleted_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_data_deleted_data_actor_source", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + } + instance = VaultDataDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_data_read_round_trip(self): + data = load_fixture("vault_data_read.json") + instance = VaultDataRead.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataRead.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_read_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataRead.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_data_read_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataRead.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_data_read_data_round_trip(self): + data = load_fixture("vault_data_read_data.json") + instance = VaultDataReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataReadData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_read_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultDataReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["kv_name"] == data["kv_name"] + assert serialized["key_id"] == data["key_id"] + + def test_vault_data_read_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_data_read_data_actor_source", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultDataReadData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_data_updated_round_trip(self): + data = load_fixture("vault_data_updated.json") + instance = VaultDataUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataUpdated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_updated_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.updated", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_data_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.data.updated", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDataUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_data_updated_data_round_trip(self): + data = load_fixture("vault_data_updated_data.json") + instance = VaultDataUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDataUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_data_updated_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + } + instance = VaultDataUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["kv_name"] == data["kv_name"] + assert serialized["key_id"] == data["key_id"] + assert serialized["key_context"] == data["key_context"] + + def test_vault_data_updated_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_data_updated_data_actor_source", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + "key_context": {"key": "test_value"}, + } + instance = VaultDataUpdatedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_dek_decrypted_round_trip(self): + data = load_fixture("vault_dek_decrypted.json") + instance = VaultDekDecrypted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDekDecrypted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_dek_decrypted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.dek.decrypted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDekDecrypted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_dek_decrypted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.dek.decrypted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDekDecrypted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_dek_decrypted_data_round_trip(self): + data = load_fixture("vault_dek_decrypted_data.json") + instance = VaultDekDecryptedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDekDecryptedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_dek_decrypted_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultDekDecryptedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["key_id"] == data["key_id"] + + def test_vault_dek_decrypted_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_dek_decrypted_data_actor_source", + "actor_name": "Jane Doe", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultDekDecryptedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_dek_read_round_trip(self): + data = load_fixture("vault_dek_read.json") + instance = VaultDekRead.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDekRead.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_dek_read_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.dek.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_ids": ["dek_01EHWNCE74X7JSDV0X3SZ3KJNY"], + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDekRead.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_dek_read_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.dek.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_ids": ["dek_01EHWNCE74X7JSDV0X3SZ3KJNY"], + "key_context": {"key": "test_value"}, + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultDekRead.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_dek_read_data_round_trip(self): + data = load_fixture("vault_dek_read_data.json") + instance = VaultDekReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultDekReadData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_dek_read_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_ids": ["dek_01EHWNCE74X7JSDV0X3SZ3KJNY"], + "key_context": {"key": "test_value"}, + } + instance = VaultDekReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["key_ids"] == data["key_ids"] + assert serialized["key_context"] == data["key_context"] + + def test_vault_dek_read_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_dek_read_data_actor_source", + "actor_name": "Jane Doe", + "key_ids": ["dek_01EHWNCE74X7JSDV0X3SZ3KJNY"], + "key_context": {"key": "test_value"}, + } + instance = VaultDekReadData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_kek_created_round_trip(self): + data = load_fixture("vault_kek_created.json") + instance = VaultKekCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultKekCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_kek_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.kek.created", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultKekCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_kek_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.kek.created", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultKekCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_kek_created_data_round_trip(self): + data = load_fixture("vault_kek_created_data.json") + instance = VaultKekCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultKekCreatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_kek_created_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultKekCreatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["key_name"] == data["key_name"] + assert serialized["key_id"] == data["key_id"] + + def test_vault_kek_created_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_kek_created_data_actor_source", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultKekCreatedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_kek_deleted_round_trip(self): + data = load_fixture("vault_kek_deleted.json") + instance = VaultKekDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultKekDeleted.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_kek_deleted_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.kek.deleted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultKekDeleted.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_kek_deleted_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.kek.deleted", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultKekDeleted.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_kek_deleted_data_round_trip(self): + data = load_fixture("vault_kek_deleted_data.json") + instance = VaultKekDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultKekDeletedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_kek_deleted_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultKekDeletedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["key_name"] == data["key_name"] + assert serialized["key_id"] == data["key_id"] + + def test_vault_kek_deleted_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_kek_deleted_data_actor_source", + "actor_name": "Jane Doe", + "key_name": "production-kek", + "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", + } + instance = VaultKekDeletedData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_metadata_read_round_trip(self): + data = load_fixture("vault_metadata_read.json") + instance = VaultMetadataRead.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultMetadataRead.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_metadata_read_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.metadata.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultMetadataRead.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_metadata_read_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.metadata.read", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultMetadataRead.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_metadata_read_data_round_trip(self): + data = load_fixture("vault_metadata_read_data.json") + instance = VaultMetadataReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultMetadataReadData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_metadata_read_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + } + instance = VaultMetadataReadData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + assert serialized["kv_name"] == data["kv_name"] + + def test_vault_metadata_read_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_metadata_read_data_actor_source", + "actor_name": "Jane Doe", + "kv_name": "user-secrets", + } + instance = VaultMetadataReadData.from_dict(data) + assert instance.to_dict() == data + + def test_vault_names_listed_round_trip(self): + data = load_fixture("vault_names_listed.json") + instance = VaultNamesListed.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultNamesListed.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_names_listed_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.names.listed", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultNamesListed.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_vault_names_listed_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "vault.names.listed", + "data": { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = VaultNamesListed.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_vault_names_listed_data_round_trip(self): + data = load_fixture("vault_names_listed_data.json") + instance = VaultNamesListedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultNamesListedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_names_listed_data_minimal_payload(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "api", + "actor_name": "Jane Doe", + } + instance = VaultNamesListedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["actor_id"] == data["actor_id"] + assert serialized["actor_source"] == data["actor_source"] + assert serialized["actor_name"] == data["actor_name"] + + def test_vault_names_listed_data_round_trips_unknown_enum_values(self): + data = { + "actor_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor_source": "unexpected_vault_names_listed_data_actor_source", + "actor_name": "Jane Doe", + } + instance = VaultNamesListedData.from_dict(data) + assert instance.to_dict() == data + + def test_waitlist_user_approved_round_trip(self): + data = load_fixture("waitlist_user_approved.json") + instance = WaitlistUserApproved.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = WaitlistUserApproved.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_waitlist_user_approved_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.approved", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserApproved.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_waitlist_user_approved_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.approved", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserApproved.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_waitlist_user_created_round_trip(self): + data = load_fixture("waitlist_user_created.json") + instance = WaitlistUserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = WaitlistUserCreated.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_waitlist_user_created_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.created", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserCreated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_waitlist_user_created_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.created", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserCreated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_waitlist_user_denied_round_trip(self): + data = load_fixture("waitlist_user_denied.json") + instance = WaitlistUserDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = WaitlistUserDenied.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_waitlist_user_denied_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.denied", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserDenied.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_waitlist_user_denied_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "waitlist_user.denied", + "data": { + "object": "waitlist_user", + "id": "wl_user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "state": "pending", + "approved_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = WaitlistUserDenied.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_auth_method_mismatch_error_round_trip(self): + data = load_fixture("auth_method_mismatch_error.json") + instance = AuthMethodMismatchError.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthMethodMismatchError.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_auth_method_mismatch_error_minimal_payload(self): + data = { + "code": "auth_method_mismatch", + "message": "This installation uses oauth authentication. Use the POST /:slug/token endpoint instead.", + } + instance = AuthMethodMismatchError.from_dict(data) + serialized = instance.to_dict() + assert serialized["code"] == data["code"] + assert serialized["message"] == data["message"] + + def test_directory_user_email_round_trip(self): + data = load_fixture("directory_user_email.json") + instance = DirectoryUserEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryUserEmail.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_user_email_minimal_payload(self): + data = {} + instance = DirectoryUserEmail.from_dict(data) + assert instance.to_dict() is not None + + def test_directory_user_email_omits_absent_optional_non_nullable_fields(self): + data = {"value": "marcelina.davis@example.com"} + instance = DirectoryUserEmail.from_dict(data) + serialized = instance.to_dict() + assert "primary" not in serialized + assert "type" not in serialized + + def test_directory_user_email_preserves_nullable_fields(self): + data = {"primary": True, "type": "work", "value": None} + instance = DirectoryUserEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized["value"] is None + + def test_event_context_google_analytics_session_round_trip(self): + data = load_fixture("event_context_google_analytics_session.json") + instance = EventContextGoogleAnalyticsSession.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EventContextGoogleAnalyticsSession.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_event_context_google_analytics_session_minimal_payload(self): + data = {"containerId": "GTM-ABCDEF"} + instance = EventContextGoogleAnalyticsSession.from_dict(data) + serialized = instance.to_dict() + assert serialized["containerId"] == data["containerId"] + + def test_event_context_google_analytics_session_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"containerId": "GTM-ABCDEF"} + instance = EventContextGoogleAnalyticsSession.from_dict(data) + serialized = instance.to_dict() + assert "sessionId" not in serialized + assert "sessionNumber" not in serialized diff --git a/tests/test_connect.py b/tests/test_connect.py index 03499bd4..a8279e6a 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -67,6 +67,7 @@ def test_list_applications_encodes_query_params(self, workos, httpx_mock): before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + registration_types=["val1", "val2"], organization_id="value organization_id/test", ) request = httpx_mock.get_request() @@ -74,6 +75,7 @@ def test_list_applications_encodes_query_params(self, workos, httpx_mock): assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["registration_types"] == "val1,val2" assert request.url.params["organization_id"] == "value organization_id/test" def test_create_application(self, workos, httpx_mock): @@ -315,6 +317,7 @@ async def test_list_applications_encodes_query_params( before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + registration_types=["val1", "val2"], organization_id="value organization_id/test", ) request = httpx_mock.get_request() @@ -322,6 +325,7 @@ async def test_list_applications_encodes_query_params( assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["registration_types"] == "val1,val2" assert request.url.params["organization_id"] == "value organization_id/test" @pytest.mark.asyncio diff --git a/tests/test_connect_models_round_trip.py b/tests/test_connect_models_round_trip.py index 1243d7b5..c83aa773 100644 --- a/tests/test_connect_models_round_trip.py +++ b/tests/test_connect_models_round_trip.py @@ -7,7 +7,204 @@ from tests.generated_helpers import load_fixture from workos.common.models import ConnectApplicationM2M -from workos.connect.models import ConnectApplication, ConnectApplicationUnknown +from workos.connect.models import ( + ApplicationCredentialsListItem, + ConnectApplication, + ConnectApplicationUnknown, + ExternalAuthCompleteResponse, + NewConnectApplicationSecret, + RedirectUriInput, + UserConsentOption, + UserConsentOptionChoice, + UserObject, +) + + +class TestModelRoundTrip: + def test_user_object_round_trip(self): + data = load_fixture("user_object.json") + instance = UserObject.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserObject.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_object_minimal_payload(self): + data = {"id": "user_12345", "email": "marcelina.davis@example.com"} + instance = UserObject.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["email"] == data["email"] + + def test_user_object_omits_absent_optional_non_nullable_fields(self): + data = {"id": "user_12345", "email": "marcelina.davis@example.com"} + instance = UserObject.from_dict(data) + serialized = instance.to_dict() + assert "first_name" not in serialized + assert "last_name" not in serialized + assert "name" not in serialized + assert "metadata" not in serialized + + def test_user_consent_option_round_trip(self): + data = load_fixture("user_consent_option.json") + instance = UserConsentOption.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserConsentOption.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_consent_option_minimal_payload(self): + data = { + "claim": "tos_accepted", + "type": "enum", + "label": "Terms of Service", + "choices": [ + {"value": "accepted", "label": "I accept the Terms of Service"} + ], + } + instance = UserConsentOption.from_dict(data) + serialized = instance.to_dict() + assert serialized["claim"] == data["claim"] + assert serialized["type"] == data["type"] + assert serialized["label"] == data["label"] + assert serialized["choices"] == data["choices"] + + def test_redirect_uri_input_round_trip(self): + data = load_fixture("redirect_uri_input.json") + instance = RedirectUriInput.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RedirectUriInput.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_redirect_uri_input_minimal_payload(self): + data = {"uri": "https://example.com/callback"} + instance = RedirectUriInput.from_dict(data) + serialized = instance.to_dict() + assert serialized["uri"] == data["uri"] + + def test_redirect_uri_input_preserves_nullable_fields(self): + data = {"uri": "https://example.com/callback", "default": None} + instance = RedirectUriInput.from_dict(data) + serialized = instance.to_dict() + assert serialized["default"] is None + + def test_external_auth_complete_response_round_trip(self): + data = load_fixture("external_auth_complete_response.json") + instance = ExternalAuthCompleteResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ExternalAuthCompleteResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_external_auth_complete_response_minimal_payload(self): + data = { + "redirect_uri": "https://your-authkit-domain.workos.com/oauth/authorize/complete?state=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdGF0ZSI6InJhbmRvbV9zdGF0ZV9zdHJpbmciLCJpYXQiOjE3NDI2MDQ4NTN9.abc123def456ghi789" + } + instance = ExternalAuthCompleteResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["redirect_uri"] == data["redirect_uri"] + + def test_new_connect_application_secret_round_trip(self): + data = load_fixture("new_connect_application_secret.json") + instance = NewConnectApplicationSecret.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = NewConnectApplicationSecret.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_new_connect_application_secret_minimal_payload(self): + data = { + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "secret": "abc123def456ghi789jkl012mno345pqr678stu901vwx234yz", + } + instance = NewConnectApplicationSecret.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["secret_hint"] == data["secret_hint"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["secret"] == data["secret"] + + def test_new_connect_application_secret_preserves_nullable_fields(self): + data = { + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "secret": "abc123def456ghi789jkl012mno345pqr678stu901vwx234yz", + } + instance = NewConnectApplicationSecret.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None + + def test_user_consent_option_choice_round_trip(self): + data = load_fixture("user_consent_option_choice.json") + instance = UserConsentOptionChoice.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserConsentOptionChoice.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_consent_option_choice_minimal_payload(self): + data = {} + instance = UserConsentOptionChoice.from_dict(data) + assert instance.to_dict() is not None + + def test_user_consent_option_choice_omits_absent_optional_non_nullable_fields(self): + data = {} + instance = UserConsentOptionChoice.from_dict(data) + serialized = instance.to_dict() + assert "value" not in serialized + assert "label" not in serialized + + def test_application_credentials_list_item_round_trip(self): + data = load_fixture("application_credentials_list_item.json") + instance = ApplicationCredentialsListItem.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApplicationCredentialsListItem.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_application_credentials_list_item_minimal_payload(self): + data = { + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApplicationCredentialsListItem.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["secret_hint"] == data["secret_hint"] + assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_application_credentials_list_item_preserves_nullable_fields(self): + data = { + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = ApplicationCredentialsListItem.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_used_at"] is None class TestDiscriminatorDispatch: diff --git a/tests/test_directory_sync.py b/tests/test_directory_sync.py index 5cd3cc83..08fa2ee4 100644 --- a/tests/test_directory_sync.py +++ b/tests/test_directory_sync.py @@ -143,6 +143,8 @@ def test_list_users_encodes_query_params(self, workos, httpx_mock): order=PaginationOrder("value_order"), directory="value directory/test", group="value group/test", + idp_id="value idp_id/test", + email="value email/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" @@ -151,6 +153,8 @@ def test_list_users_encodes_query_params(self, workos, httpx_mock): assert request.url.params["order"] == "value_order" assert request.url.params["directory"] == "value directory/test" assert request.url.params["group"] == "value group/test" + assert request.url.params["idp_id"] == "value idp_id/test" + assert request.url.params["email"] == "value email/test" def test_get_user(self, workos, httpx_mock): httpx_mock.add_response( @@ -371,6 +375,8 @@ async def test_list_users_encodes_query_params(self, async_workos, httpx_mock): order=PaginationOrder("value_order"), directory="value directory/test", group="value group/test", + idp_id="value idp_id/test", + email="value email/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" @@ -379,6 +385,8 @@ async def test_list_users_encodes_query_params(self, async_workos, httpx_mock): assert request.url.params["order"] == "value_order" assert request.url.params["directory"] == "value directory/test" assert request.url.params["group"] == "value group/test" + assert request.url.params["idp_id"] == "value idp_id/test" + assert request.url.params["email"] == "value email/test" @pytest.mark.asyncio async def test_get_user(self, async_workos, httpx_mock): diff --git a/tests/test_directory_sync_models_round_trip.py b/tests/test_directory_sync_models_round_trip.py new file mode 100644 index 00000000..2412cf40 --- /dev/null +++ b/tests/test_directory_sync_models_round_trip.py @@ -0,0 +1,379 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.directory_sync.models import ( + Directory, + DirectoryGroup, + DirectoryMetadata, + DirectoryMetadataUser, + DirectoryUserWithGroups, + DirectoryUserWithGroupsEmail, +) + + +class TestModelRoundTrip: + def test_directory_round_trip(self): + data = load_fixture("directory.json") + instance = Directory.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Directory.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_minimal_payload(self): + data = { + "object": "directory", + "id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "external_key": "sPa12dwRQ", + "type": "gsuite directory", + "state": "linked", + "name": "Foo Corp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Directory.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["external_key"] == data["external_key"] + assert serialized["type"] == data["type"] + assert serialized["state"] == data["state"] + assert serialized["name"] == data["name"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_directory_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory", + "id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "external_key": "sPa12dwRQ", + "type": "gsuite directory", + "state": "linked", + "name": "Foo Corp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Directory.from_dict(data) + serialized = instance.to_dict() + assert "domain" not in serialized + assert "metadata" not in serialized + + def test_directory_round_trips_unknown_enum_values(self): + data = { + "object": "directory", + "id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "external_key": "sPa12dwRQ", + "type": "unexpected_directory_type", + "state": "linked", + "name": "Foo Corp", + "domain": "foo-corp.com", + "metadata": {"users": {"active": 42, "inactive": 3}, "groups": 5}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Directory.from_dict(data) + assert instance.to_dict() == data + + def test_directory_group_round_trip(self): + data = load_fixture("directory_group.json") + instance = DirectoryGroup.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryGroup.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_group_minimal_payload(self): + data = { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryGroup.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["name"] == data["name"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_directory_group_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = DirectoryGroup.from_dict(data) + serialized = instance.to_dict() + assert "raw_attributes" not in serialized + + def test_directory_user_with_groups_round_trip(self): + data = load_fixture("directory_user_with_groups.json") + instance = DirectoryUserWithGroups.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryUserWithGroups.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_user_with_groups_minimal_payload(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "groups": [ + { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + } + instance = DirectoryUserWithGroups.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["directory_id"] == data["directory_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["email"] == data["email"] + assert serialized["state"] == data["state"] + assert serialized["raw_attributes"] == data["raw_attributes"] + assert serialized["custom_attributes"] == data["custom_attributes"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["groups"] == data["groups"] + + def test_directory_user_with_groups_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "job_title": "Software Engineer", + "username": "mdavis", + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "groups": [ + { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + } + instance = DirectoryUserWithGroups.from_dict(data) + serialized = instance.to_dict() + assert "emails" not in serialized + assert "role" not in serialized + assert "roles" not in serialized + + def test_directory_user_with_groups_preserves_nullable_fields(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": None, + "first_name": None, + "last_name": None, + "name": None, + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": None, + "username": None, + "state": "active", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "groups": [ + { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + } + instance = DirectoryUserWithGroups.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] is None + assert serialized["first_name"] is None + assert serialized["last_name"] is None + assert serialized["name"] is None + assert serialized["job_title"] is None + assert serialized["username"] is None + + def test_directory_user_with_groups_round_trips_unknown_enum_values(self): + data = { + "object": "directory_user", + "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "idp_id": "2836", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "emails": [ + { + "primary": True, + "type": "work", + "value": "marcelina.davis@example.com", + } + ], + "job_title": "Software Engineer", + "username": "mdavis", + "state": "unexpected_directory_user_with_groups_state", + "raw_attributes": {"key": {}}, + "custom_attributes": { + "department": "Engineering", + "job_title": "Software Engineer", + }, + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "groups": [ + { + "object": "directory_group", + "id": "directory_group_01E1JJS84MFPPQ3G655FHTKX6Z", + "idp_id": "02grqrue4294w24", + "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", + "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", + "name": "Developers", + "raw_attributes": {"key": {}}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + } + instance = DirectoryUserWithGroups.from_dict(data) + assert instance.to_dict() == data + + def test_directory_user_with_groups_email_round_trip(self): + data = load_fixture("directory_user_with_groups_email.json") + instance = DirectoryUserWithGroupsEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryUserWithGroupsEmail.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_user_with_groups_email_minimal_payload(self): + data = {} + instance = DirectoryUserWithGroupsEmail.from_dict(data) + assert instance.to_dict() is not None + + def test_directory_user_with_groups_email_omits_absent_optional_non_nullable_fields( + self, + ): + data = {"value": "marcelina.davis@example.com"} + instance = DirectoryUserWithGroupsEmail.from_dict(data) + serialized = instance.to_dict() + assert "primary" not in serialized + assert "type" not in serialized + + def test_directory_user_with_groups_email_preserves_nullable_fields(self): + data = {"primary": True, "type": "work", "value": None} + instance = DirectoryUserWithGroupsEmail.from_dict(data) + serialized = instance.to_dict() + assert serialized["value"] is None + + def test_directory_metadata_round_trip(self): + data = load_fixture("directory_metadata.json") + instance = DirectoryMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryMetadata.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_metadata_minimal_payload(self): + data = {"users": {"active": 42, "inactive": 3}, "groups": 5} + instance = DirectoryMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["users"] == data["users"] + assert serialized["groups"] == data["groups"] + + def test_directory_metadata_user_round_trip(self): + data = load_fixture("directory_metadata_user.json") + instance = DirectoryMetadataUser.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DirectoryMetadataUser.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_directory_metadata_user_minimal_payload(self): + data = {"active": 42, "inactive": 3} + instance = DirectoryMetadataUser.from_dict(data) + serialized = instance.to_dict() + assert serialized["active"] == data["active"] + assert serialized["inactive"] == data["inactive"] diff --git a/tests/test_events_models_round_trip.py b/tests/test_events_models_round_trip.py new file mode 100644 index 00000000..87c69c62 --- /dev/null +++ b/tests/test_events_models_round_trip.py @@ -0,0 +1,58 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +import pytest + +from tests.generated_helpers import load_fixture + +from workos.common.models import ActionAuthenticationDenied +from workos.events.models import EventListListMetadata, EventSchema, EventSchemaUnknown + + +class TestModelRoundTrip: + def test_event_list_list_metadata_round_trip(self): + data = load_fixture("event_list_list_metadata.json") + instance = EventListListMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = EventListListMetadata.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_event_list_list_metadata_minimal_payload(self): + data = {"after": None} + instance = EventListListMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["after"] == data["after"] + + def test_event_list_list_metadata_preserves_nullable_fields(self): + data = {"after": None} + instance = EventListListMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["after"] is None + + +class TestDiscriminatorDispatch: + def test_event_schema_dispatches_known_variant(self): + data = load_fixture("action_authentication_denied.json") + result = EventSchema.from_dict(data) + assert isinstance(result, ActionAuthenticationDenied) + + def test_event_schema_returns_unknown_for_unrecognized_type(self): + data = load_fixture("action_authentication_denied.json") + data = {**data, "event": "future.unrecognized.type"} + result = EventSchema.from_dict(data) + assert isinstance(result, EventSchemaUnknown) + assert result.raw_data == data + + def test_event_schema_raises_on_missing_discriminator(self): + data = load_fixture("action_authentication_denied.json") + data = {k: v for k, v in data.items() if k != "event"} + with pytest.raises(Exception): + EventSchema.from_dict(data) + + def test_event_schema_raises_on_none_discriminator(self): + data = load_fixture("action_authentication_denied.json") + data = {**data, "event": None} + with pytest.raises(Exception): + EventSchema.from_dict(data) diff --git a/tests/test_feature_flags_models_round_trip.py b/tests/test_feature_flags_models_round_trip.py new file mode 100644 index 00000000..12eb6c13 --- /dev/null +++ b/tests/test_feature_flags_models_round_trip.py @@ -0,0 +1,165 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.feature_flags.models import FeatureFlag, FeatureFlagOwner, Flag, FlagOwner + + +class TestModelRoundTrip: + def test_flag_round_trip(self): + data = load_fixture("flag.json") + instance = Flag.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Flag.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Flag.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_flag_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": True, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Flag.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_flag_owner_round_trip(self): + data = load_fixture("flag_owner.json") + instance = FlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FlagOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_flag_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_flag_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None + + def test_feature_flag_round_trip(self): + data = load_fixture("feature_flag.json") + instance = FeatureFlag.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FeatureFlag.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_feature_flag_minimal_payload(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": False, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FeatureFlag.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["owner"] == data["owner"] + assert serialized["tags"] == data["tags"] + assert serialized["enabled"] == data["enabled"] + assert serialized["default_value"] == data["default_value"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_feature_flag_preserves_nullable_fields(self): + data = { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": None, + "owner": None, + "tags": ["reports"], + "enabled": False, + "default_value": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = FeatureFlag.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + assert serialized["owner"] is None + + def test_feature_flag_owner_round_trip(self): + data = load_fixture("feature_flag_owner.json") + instance = FeatureFlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = FeatureFlagOwner.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_feature_flag_owner_minimal_payload(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FeatureFlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + + def test_feature_flag_owner_preserves_nullable_fields(self): + data = {"email": "jane@example.com", "first_name": None, "last_name": None} + instance = FeatureFlagOwner.from_dict(data) + serialized = instance.to_dict() + assert serialized["first_name"] is None + assert serialized["last_name"] is None diff --git a/tests/test_groups_models_round_trip.py b/tests/test_groups_models_round_trip.py index 2709bfe0..79fc0d0c 100644 --- a/tests/test_groups_models_round_trip.py +++ b/tests/test_groups_models_round_trip.py @@ -4,10 +4,52 @@ from tests.generated_helpers import load_fixture -from workos.groups.models import UserOrganizationMembershipBaseListData +from workos.groups.models import Group, UserOrganizationMembershipBaseListData class TestModelRoundTrip: + def test_group_round_trip(self): + data = load_fixture("group.json") + instance = Group.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Group.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_group_minimal_payload(self): + data = { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Group.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_group_preserves_nullable_fields(self): + data = { + "object": "group", + "id": "group_01HXYZ123456789ABCDEFGHIJ", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Engineering", + "description": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Group.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + def test_user_organization_membership_base_list_data_round_trip(self): data = load_fixture("user_organization_membership_base_list_data.json") instance = UserOrganizationMembershipBaseListData.from_dict(data) diff --git a/tests/test_multi_factor_auth_models_round_trip.py b/tests/test_multi_factor_auth_models_round_trip.py new file mode 100644 index 00000000..19997a71 --- /dev/null +++ b/tests/test_multi_factor_auth_models_round_trip.py @@ -0,0 +1,306 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.multi_factor_auth.models import ( + AuthenticationChallenge, + AuthenticationChallengeVerifyResponse, + AuthenticationFactor, + AuthenticationFactorEnrolled, + AuthenticationFactorEnrolledSms, + AuthenticationFactorEnrolledTotp, + AuthenticationFactorSms, + AuthenticationFactorTotp, + UserAuthenticationFactorEnrollResponse, +) + + +class TestModelRoundTrip: + def test_authentication_challenge_round_trip(self): + data = load_fixture("authentication_challenge.json") + instance = AuthenticationChallenge.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationChallenge.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_challenge_minimal_payload(self): + data = { + "object": "authentication_challenge", + "id": "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationChallenge.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert ( + serialized["authentication_factor_id"] == data["authentication_factor_id"] + ) + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_authentication_challenge_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "authentication_challenge", + "id": "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationChallenge.from_dict(data) + serialized = instance.to_dict() + assert "expires_at" not in serialized + assert "code" not in serialized + + def test_authentication_challenge_verify_response_round_trip(self): + data = load_fixture("authentication_challenge_verify_response.json") + instance = AuthenticationChallengeVerifyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationChallengeVerifyResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_challenge_verify_response_minimal_payload(self): + data = { + "challenge": { + "object": "authentication_challenge", + "id": "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "expires_at": "2026-01-15T12:00:00.000Z", + "code": "123456", + "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "valid": True, + } + instance = AuthenticationChallengeVerifyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["challenge"] == data["challenge"] + assert serialized["valid"] == data["valid"] + + def test_authentication_factor_enrolled_round_trip(self): + data = load_fixture("authentication_factor_enrolled.json") + instance = AuthenticationFactorEnrolled.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactorEnrolled.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_enrolled_minimal_payload(self): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "totp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactorEnrolled.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_authentication_factor_enrolled_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "totp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactorEnrolled.from_dict(data) + serialized = instance.to_dict() + assert "user_id" not in serialized + assert "sms" not in serialized + assert "totp" not in serialized + + def test_authentication_factor_enrolled_round_trips_unknown_enum_values(self): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "unexpected_authentication_factor_enrolled_type", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "sms": {"phone_number": "+15005550006"}, + "totp": { + "issuer": "WorkOS", + "user": "user@example.com", + "secret": "JBSWY3DPEHPK3PXP", + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...", + "uri": "otpauth://totp/WorkOS:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=WorkOS", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactorEnrolled.from_dict(data) + assert instance.to_dict() == data + + def test_authentication_factor_round_trip(self): + data = load_fixture("authentication_factor.json") + instance = AuthenticationFactor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_minimal_payload(self): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "totp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactor.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_authentication_factor_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "totp", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactor.from_dict(data) + serialized = instance.to_dict() + assert "user_id" not in serialized + assert "sms" not in serialized + assert "totp" not in serialized + + def test_authentication_factor_round_trips_unknown_enum_values(self): + data = { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "unexpected_authentication_factor_type", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "sms": {"phone_number": "+15005550006"}, + "totp": {"issuer": "WorkOS", "user": "user@example.com"}, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = AuthenticationFactor.from_dict(data) + assert instance.to_dict() == data + + def test_user_authentication_factor_enroll_response_round_trip(self): + data = load_fixture("user_authentication_factor_enroll_response.json") + instance = UserAuthenticationFactorEnrollResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserAuthenticationFactorEnrollResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_authentication_factor_enroll_response_minimal_payload(self): + data = { + "authentication_factor": { + "object": "authentication_factor", + "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "type": "totp", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "sms": {"phone_number": "+15005550006"}, + "totp": { + "issuer": "WorkOS", + "user": "user@example.com", + "secret": "JBSWY3DPEHPK3PXP", + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...", + "uri": "otpauth://totp/WorkOS:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=WorkOS", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "authentication_challenge": { + "object": "authentication_challenge", + "id": "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "expires_at": "2026-01-15T12:00:00.000Z", + "code": "123456", + "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = UserAuthenticationFactorEnrollResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["authentication_factor"] == data["authentication_factor"] + assert ( + serialized["authentication_challenge"] == data["authentication_challenge"] + ) + + def test_authentication_factor_sms_round_trip(self): + data = load_fixture("authentication_factor_sms.json") + instance = AuthenticationFactorSms.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactorSms.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_sms_minimal_payload(self): + data = {"phone_number": "+15005550006"} + instance = AuthenticationFactorSms.from_dict(data) + serialized = instance.to_dict() + assert serialized["phone_number"] == data["phone_number"] + + def test_authentication_factor_totp_round_trip(self): + data = load_fixture("authentication_factor_totp.json") + instance = AuthenticationFactorTotp.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactorTotp.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_totp_minimal_payload(self): + data = {"issuer": "WorkOS", "user": "user@example.com"} + instance = AuthenticationFactorTotp.from_dict(data) + serialized = instance.to_dict() + assert serialized["issuer"] == data["issuer"] + assert serialized["user"] == data["user"] + + def test_authentication_factor_enrolled_sms_round_trip(self): + data = load_fixture("authentication_factor_enrolled_sms.json") + instance = AuthenticationFactorEnrolledSms.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactorEnrolledSms.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_enrolled_sms_minimal_payload(self): + data = {"phone_number": "+15005550006"} + instance = AuthenticationFactorEnrolledSms.from_dict(data) + serialized = instance.to_dict() + assert serialized["phone_number"] == data["phone_number"] + + def test_authentication_factor_enrolled_totp_round_trip(self): + data = load_fixture("authentication_factor_enrolled_totp.json") + instance = AuthenticationFactorEnrolledTotp.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuthenticationFactorEnrolledTotp.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_authentication_factor_enrolled_totp_minimal_payload(self): + data = { + "issuer": "WorkOS", + "user": "user@example.com", + "secret": "JBSWY3DPEHPK3PXP", + "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...", + "uri": "otpauth://totp/WorkOS:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=WorkOS", + } + instance = AuthenticationFactorEnrolledTotp.from_dict(data) + serialized = instance.to_dict() + assert serialized["issuer"] == data["issuer"] + assert serialized["user"] == data["user"] + assert serialized["secret"] == data["secret"] + assert serialized["qr_code"] == data["qr_code"] + assert serialized["uri"] == data["uri"] diff --git a/tests/test_organization_domains.py b/tests/test_organization_domains.py index 0b2c52a0..bf719959 100644 --- a/tests/test_organization_domains.py +++ b/tests/test_organization_domains.py @@ -7,7 +7,6 @@ from tests.generated_helpers import load_fixture from workos.common.models import OrganizationDomain -from workos.organization_domains.models import OrganizationDomainStandAlone from workos._errors import ( AuthenticationError, BadRequestError, @@ -38,10 +37,10 @@ def test_create_organization_domain(self, workos, httpx_mock): def test_get_organization_domain(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("organization_domain_stand_alone.json"), + json=load_fixture("organization_domain.json"), ) result = workos.organization_domains.get_organization_domain("test_id") - assert isinstance(result, OrganizationDomainStandAlone) + assert isinstance(result, OrganizationDomain) assert result.object == "organization_domain" assert result.id == "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A" request = httpx_mock.get_request() @@ -58,10 +57,10 @@ def test_delete_organization_domain(self, workos, httpx_mock): def test_verify_organization_domain(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("organization_domain_stand_alone.json"), + json=load_fixture("organization_domain.json"), ) result = workos.organization_domains.verify_organization_domain("test_id") - assert isinstance(result, OrganizationDomainStandAlone) + assert isinstance(result, OrganizationDomain) assert result.object == "organization_domain" assert result.id == "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A" request = httpx_mock.get_request() @@ -174,13 +173,11 @@ async def test_create_organization_domain(self, async_workos, httpx_mock): @pytest.mark.asyncio async def test_get_organization_domain(self, async_workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("organization_domain_stand_alone.json") - ) + httpx_mock.add_response(json=load_fixture("organization_domain.json")) result = await async_workos.organization_domains.get_organization_domain( "test_id" ) - assert isinstance(result, OrganizationDomainStandAlone) + assert isinstance(result, OrganizationDomain) assert result.object == "organization_domain" assert result.id == "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A" request = httpx_mock.get_request() @@ -200,13 +197,11 @@ async def test_delete_organization_domain(self, async_workos, httpx_mock): @pytest.mark.asyncio async def test_verify_organization_domain(self, async_workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("organization_domain_stand_alone.json") - ) + httpx_mock.add_response(json=load_fixture("organization_domain.json")) result = await async_workos.organization_domains.verify_organization_domain( "test_id" ) - assert isinstance(result, OrganizationDomainStandAlone) + assert isinstance(result, OrganizationDomain) assert result.object == "organization_domain" assert result.id == "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A" request = httpx_mock.get_request() diff --git a/tests/test_organization_domains_models_round_trip.py b/tests/test_organization_domains_models_round_trip.py new file mode 100644 index 00000000..050042c1 --- /dev/null +++ b/tests/test_organization_domains_models_round_trip.py @@ -0,0 +1,67 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.organization_domains.models import OrganizationDomain + + +class TestModelRoundTrip: + def test_organization_domain_round_trip(self): + data = load_fixture("organization_domain.json") + instance = OrganizationDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_minimal_payload(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["domain"] == data["domain"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_domain_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomain.from_dict(data) + serialized = instance.to_dict() + assert "state" not in serialized + assert "verification_prefix" not in serialized + assert "verification_token" not in serialized + assert "verification_strategy" not in serialized + + def test_organization_domain_round_trips_unknown_enum_values(self): + data = { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_state", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = OrganizationDomain.from_dict(data) + assert instance.to_dict() == data diff --git a/tests/test_organization_membership_models_round_trip.py b/tests/test_organization_membership_models_round_trip.py new file mode 100644 index 00000000..7881c2a8 --- /dev/null +++ b/tests/test_organization_membership_models_round_trip.py @@ -0,0 +1,260 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.organization_membership.models import ( + OrganizationMembership, + UserOrganizationMembership, +) + + +class TestModelRoundTrip: + def test_user_organization_membership_round_trip(self): + data = load_fixture("user_organization_membership.json") + instance = UserOrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = UserOrganizationMembership.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_user_organization_membership_minimal_payload(self): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "status": "active", + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = UserOrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["directory_managed"] == data["directory_managed"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["role"] == data["role"] + assert serialized["roles"] == data["roles"] + assert serialized["user"] == data["user"] + + def test_user_organization_membership_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "status": "active", + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = UserOrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert "organization_name" not in serialized + assert "custom_attributes" not in serialized + + def test_user_organization_membership_round_trips_unknown_enum_values(self): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "status": "unexpected_user_organization_membership_status", + "directory_managed": False, + "organization_name": "Acme Corp", + "custom_attributes": { + "department": "Engineering", + "title": "Developer Experience Engineer", + "location": "Brooklyn", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = UserOrganizationMembership.from_dict(data) + assert instance.to_dict() == data + + def test_organization_membership_round_trip(self): + data = load_fixture("organization_membership.json") + instance = OrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationMembership.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_membership_minimal_payload(self): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C5A4QZ2Z2JQXGKZJ9E", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "status": "active", + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = OrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["status"] == data["status"] + assert serialized["directory_managed"] == data["directory_managed"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["role"] == data["role"] + assert serialized["roles"] == data["roles"] + assert serialized["user"] == data["user"] + + def test_organization_membership_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C5A4QZ2Z2JQXGKZJ9E", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "status": "active", + "directory_managed": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = OrganizationMembership.from_dict(data) + serialized = instance.to_dict() + assert "organization_name" not in serialized + assert "custom_attributes" not in serialized + + def test_organization_membership_round_trips_unknown_enum_values(self): + data = { + "object": "organization_membership", + "id": "om_01HXYZ123456789ABCDEFGHIJ", + "user_id": "user_01E4ZCR3C5A4QZ2Z2JQXGKZJ9E", + "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5", + "status": "unexpected_organization_membership_status", + "directory_managed": False, + "organization_name": "Acme Corp", + "custom_attributes": { + "department": "Engineering", + "title": "Developer Experience Engineer", + "location": "Brooklyn", + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "user": { + "object": "user", + "id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "first_name": "Marcelina", + "last_name": "Davis", + "name": "Marcelina Davis", + "profile_picture_url": "https://workoscdn.com/images/v1/123abc", + "email": "marcelina.davis@example.com", + "email_verified": True, + "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", + "metadata": {"timezone": "America/New_York"}, + "last_sign_in_at": "2025-06-25T19:07:33.000Z", + "locale": "en-US", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = OrganizationMembership.from_dict(data) + assert instance.to_dict() == data diff --git a/tests/test_organizations.py b/tests/test_organizations.py index d480b254..361b7bda 100644 --- a/tests/test_organizations.py +++ b/tests/test_organizations.py @@ -7,7 +7,11 @@ from tests.generated_helpers import load_fixture from workos.common.models import PaginationOrder -from workos.organizations.models import AuditLogConfiguration, Organization +from workos.organizations.models import ( + AuditLogConfiguration, + Organization, + OrganizationAuthorizedConnectApplicationListData, +) from workos._pagination import AsyncPage, SyncPage from workos._errors import ( AuthenticationError, @@ -127,6 +131,42 @@ def test_get_audit_log_configuration(self, workos, httpx_mock): "/organizations/test_id/audit_log_configuration" ) + def test_list_authorized_applications(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture( + "list_organization_authorized_connect_application_list_data.json" + ), + ) + page = workos.organizations.list_authorized_applications("test_organization_id") + assert isinstance(page, SyncPage) + assert len(page.data) == 1 + assert isinstance( + page.data[0], OrganizationAuthorizedConnectApplicationListData + ) + + def test_list_authorized_applications_empty_page(self, workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = workos.organizations.list_authorized_applications("test_organization_id") + assert isinstance(page, SyncPage) + assert page.data == [] + + def test_list_authorized_applications_encodes_query_params( + self, workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + workos.organizations.list_authorized_applications( + "test_organization_id", + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + def test_list_organizations_with_request_options(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) workos.organizations.list_organizations( @@ -308,6 +348,51 @@ async def test_get_audit_log_configuration(self, async_workos, httpx_mock): "/organizations/test_id/audit_log_configuration" ) + @pytest.mark.asyncio + async def test_list_authorized_applications(self, async_workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture( + "list_organization_authorized_connect_application_list_data.json" + ) + ) + page = await async_workos.organizations.list_authorized_applications( + "test_organization_id" + ) + assert isinstance(page, AsyncPage) + assert len(page.data) == 1 + assert isinstance( + page.data[0], OrganizationAuthorizedConnectApplicationListData + ) + + @pytest.mark.asyncio + async def test_list_authorized_applications_empty_page( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = await async_workos.organizations.list_authorized_applications( + "test_organization_id" + ) + assert isinstance(page, AsyncPage) + assert page.data == [] + + @pytest.mark.asyncio + async def test_list_authorized_applications_encodes_query_params( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + await async_workos.organizations.list_authorized_applications( + "test_organization_id", + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + @pytest.mark.asyncio async def test_list_organizations_with_request_options( self, async_workos, httpx_mock diff --git a/tests/test_organizations_models_round_trip.py b/tests/test_organizations_models_round_trip.py index d17ea5db..834c520e 100644 --- a/tests/test_organizations_models_round_trip.py +++ b/tests/test_organizations_models_round_trip.py @@ -4,10 +4,40 @@ from tests.generated_helpers import load_fixture -from workos.organizations.models import AuditLogsRetention +from workos.organizations.models import ( + AuditLogConfiguration, + AuditLogConfigurationLogStream, + AuditLogsRetention, + Organization, + OrganizationAuthorizedConnectApplicationListData, + OrganizationDomainData, +) class TestModelRoundTrip: + def test_organization_domain_data_round_trip(self): + data = load_fixture("organization_domain_data.json") + instance = OrganizationDomainData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationDomainData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_domain_data_minimal_payload(self): + data = {"domain": "foo-corp.com", "state": "verified"} + instance = OrganizationDomainData.from_dict(data) + serialized = instance.to_dict() + assert serialized["domain"] == data["domain"] + assert serialized["state"] == data["state"] + + def test_organization_domain_data_round_trips_unknown_enum_values(self): + data = { + "domain": "foo-corp.com", + "state": "unexpected_organization_domain_data_state", + } + instance = OrganizationDomainData.from_dict(data) + assert instance.to_dict() == data + def test_audit_logs_retention_round_trip(self): data = load_fixture("audit_logs_retention.json") instance = AuditLogsRetention.from_dict(data) @@ -29,3 +59,278 @@ def test_audit_logs_retention_preserves_nullable_fields(self): instance = AuditLogsRetention.from_dict(data) serialized = instance.to_dict() assert serialized["retention_period_in_days"] is None + + def test_organization_round_trip(self): + data = load_fixture("organization.json") + instance = Organization.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Organization.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_organization_minimal_payload(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Organization.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + assert serialized["domains"] == data["domains"] + assert serialized["metadata"] == data["metadata"] + assert serialized["external_id"] == data["external_id"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_organization_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": "2fe01467-f7ea-4dd2-8b79-c2b4f56d0191", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Organization.from_dict(data) + serialized = instance.to_dict() + assert "stripe_customer_id" not in serialized + assert "allow_profiles_outside_organization" not in serialized + + def test_organization_preserves_nullable_fields(self): + data = { + "object": "organization", + "id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "name": "Acme Inc.", + "domains": [ + { + "object": "organization_domain", + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "organization_id": "org_01HE8GSH8FQPASKSY27THRKRBP", + "domain": "foo-corp.com", + "state": "pending", + "verification_prefix": "superapp-domain-verification-z3kjny", + "verification_token": "m5Oztg3jdK4NJLgs8uIlIprMw", + "verification_strategy": "dns", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + ], + "metadata": {"tier": "diamond"}, + "external_id": None, + "stripe_customer_id": "cus_R9qWAGMQ6nGE7V", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "allow_profiles_outside_organization": False, + } + instance = Organization.from_dict(data) + serialized = instance.to_dict() + assert serialized["external_id"] is None + + def test_audit_log_configuration_round_trip(self): + data = load_fixture("audit_log_configuration.json") + instance = AuditLogConfiguration.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuditLogConfiguration.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_audit_log_configuration_minimal_payload(self): + data = { + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "retention_period_in_days": 30, + "state": "active", + } + instance = AuditLogConfiguration.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] == data["organization_id"] + assert ( + serialized["retention_period_in_days"] == data["retention_period_in_days"] + ) + assert serialized["state"] == data["state"] + + def test_audit_log_configuration_omits_absent_optional_non_nullable_fields(self): + data = { + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "retention_period_in_days": 30, + "state": "active", + } + instance = AuditLogConfiguration.from_dict(data) + serialized = instance.to_dict() + assert "log_stream" not in serialized + + def test_audit_log_configuration_round_trips_unknown_enum_values(self): + data = { + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "retention_period_in_days": 30, + "state": "unexpected_audit_log_configuration_state", + "log_stream": { + "id": "als_01EHZNVPK3SFK441A1RGBFSHRT", + "type": "Datadog", + "state": "active", + "last_synced_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + }, + } + instance = AuditLogConfiguration.from_dict(data) + assert instance.to_dict() == data + + def test_audit_log_configuration_log_stream_round_trip(self): + data = load_fixture("audit_log_configuration_log_stream.json") + instance = AuditLogConfigurationLogStream.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = AuditLogConfigurationLogStream.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_audit_log_configuration_log_stream_minimal_payload(self): + data = { + "id": "als_01EHZNVPK3SFK441A1RGBFSHRT", + "type": "Datadog", + "state": "active", + "last_synced_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuditLogConfigurationLogStream.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["state"] == data["state"] + assert serialized["last_synced_at"] == data["last_synced_at"] + assert serialized["created_at"] == data["created_at"] + + def test_audit_log_configuration_log_stream_preserves_nullable_fields(self): + data = { + "id": "als_01EHZNVPK3SFK441A1RGBFSHRT", + "type": "Datadog", + "state": "active", + "last_synced_at": None, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuditLogConfigurationLogStream.from_dict(data) + serialized = instance.to_dict() + assert serialized["last_synced_at"] is None + + def test_audit_log_configuration_log_stream_round_trips_unknown_enum_values(self): + data = { + "id": "als_01EHZNVPK3SFK441A1RGBFSHRT", + "type": "unexpected_audit_log_configuration_log_stream_type", + "state": "active", + "last_synced_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = AuditLogConfigurationLogStream.from_dict(data) + assert instance.to_dict() == data + + def test_organization_authorized_connect_application_list_data_round_trip(self): + data = load_fixture( + "organization_authorized_connect_application_list_data.json" + ) + instance = OrganizationAuthorizedConnectApplicationListData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = OrganizationAuthorizedConnectApplicationListData.from_dict( + serialized + ) + assert restored.to_dict() == serialized + + def test_organization_authorized_connect_application_list_data_minimal_payload( + self, + ): + data = { + "object": "authorized_connect_application", + "id": "authorized_connect_app_01HXYZ123456789ABCDEFGHIJ", + "granted_scopes": ["openid", "profile", "email"], + "application": { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [ + {"uri": "https://example.com/callback", "default": True} + ], + "uses_pkce": True, + "is_first_party": True, + "was_dynamically_registered": True, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + }, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + } + instance = OrganizationAuthorizedConnectApplicationListData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["granted_scopes"] == data["granted_scopes"] + assert serialized["application"] == data["application"] + assert serialized["user_id"] == data["user_id"] + + def test_organization_authorized_connect_application_list_data_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "authorized_connect_application", + "id": "authorized_connect_app_01HXYZ123456789ABCDEFGHIJ", + "granted_scopes": ["openid", "profile", "email"], + "application": { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [ + {"uri": "https://example.com/callback", "default": True} + ], + "uses_pkce": True, + "is_first_party": True, + "was_dynamically_registered": True, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + }, + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + } + instance = OrganizationAuthorizedConnectApplicationListData.from_dict(data) + serialized = instance.to_dict() + assert "oauth_resource" not in serialized diff --git a/tests/test_pipes_models_round_trip.py b/tests/test_pipes_models_round_trip.py index 3477f8a8..6ca2ea12 100644 --- a/tests/test_pipes_models_round_trip.py +++ b/tests/test_pipes_models_round_trip.py @@ -5,6 +5,7 @@ from tests.generated_helpers import load_fixture from workos.pipes.models import ( + ApiKeyInstallation, ConnectedAccount, CustomProviderDefinition, DataIntegration, @@ -12,10 +13,11 @@ DataIntegrationAccessTokenResponseAccessToken, DataIntegrationAuthorizeUrlResponse, DataIntegrationCredential, - DataIntegrationCredentialsDto, + DataIntegrationCredentialsInput, DataIntegrationCredentialsResponse, DataIntegrationCredentialsResponseCredential, DataIntegrationCustomProvider, + DataIntegrationInstallation, DataIntegrationsListResponse, DataIntegrationsListResponseData, DataIntegrationsListResponseDataConnectedAccount, @@ -24,38 +26,65 @@ class TestModelRoundTrip: - def test_data_integration_credentials_dto_round_trip(self): - data = load_fixture("data_integration_credentials_dto.json") - instance = DataIntegrationCredentialsDto.from_dict(data) + def test_data_integration_credentials_input_round_trip(self): + data = load_fixture("data_integration_credentials_input.json") + instance = DataIntegrationCredentialsInput.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = DataIntegrationCredentialsDto.from_dict(serialized) + restored = DataIntegrationCredentialsInput.from_dict(serialized) assert restored.to_dict() == serialized - def test_data_integration_credentials_dto_minimal_payload(self): + def test_data_integration_credentials_input_minimal_payload(self): data = {"type": "custom"} - instance = DataIntegrationCredentialsDto.from_dict(data) + instance = DataIntegrationCredentialsInput.from_dict(data) serialized = instance.to_dict() assert serialized["type"] == data["type"] - def test_data_integration_credentials_dto_omits_absent_optional_non_nullable_fields( + def test_data_integration_credentials_input_omits_absent_optional_non_nullable_fields( self, ): data = {"type": "custom"} - instance = DataIntegrationCredentialsDto.from_dict(data) + instance = DataIntegrationCredentialsInput.from_dict(data) serialized = instance.to_dict() assert "client_id" not in serialized assert "client_secret" not in serialized - def test_data_integration_credentials_dto_round_trips_unknown_enum_values(self): + def test_data_integration_credentials_input_round_trips_unknown_enum_values(self): data = { - "type": "unexpected_data_integration_credentials_dto_type", + "type": "unexpected_data_integration_credentials_input_type", "client_id": "Iv1.abc123", "client_secret": "secret_…", } - instance = DataIntegrationCredentialsDto.from_dict(data) + instance = DataIntegrationCredentialsInput.from_dict(data) assert instance.to_dict() == data + def test_api_key_installation_round_trip(self): + data = load_fixture("api_key_installation.json") + instance = ApiKeyInstallation.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ApiKeyInstallation.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_api_key_installation_minimal_payload(self): + data = { + "secret": "sk-1234567890abcdef", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + } + instance = ApiKeyInstallation.from_dict(data) + serialized = instance.to_dict() + assert serialized["secret"] == data["secret"] + assert serialized["user_id"] == data["user_id"] + + def test_api_key_installation_omits_absent_optional_non_nullable_fields(self): + data = { + "secret": "sk-1234567890abcdef", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + } + instance = ApiKeyInstallation.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + def test_custom_provider_definition_round_trip(self): data = load_fixture("custom_provider_definition.json") instance = CustomProviderDefinition.from_dict(data) @@ -212,11 +241,13 @@ def test_data_integration_minimal_payload(self): "state": "valid", "scopes": None, "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + "auth_methods": ["oauth"], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "redacted_client_secret": "6789", }, + "installation": None, "custom_provider": None, "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -232,7 +263,9 @@ def test_data_integration_minimal_payload(self): assert serialized["state"] == data["state"] assert serialized["scopes"] == data["scopes"] assert serialized["redirect_uri"] == data["redirect_uri"] + assert serialized["auth_methods"] == data["auth_methods"] assert serialized["credentials"] == data["credentials"] + assert serialized["installation"] == data["installation"] assert serialized["custom_provider"] == data["custom_provider"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -248,11 +281,13 @@ def test_data_integration_preserves_nullable_fields(self): "state": "valid", "scopes": None, "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + "auth_methods": ["oauth"], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "redacted_client_secret": "6789", }, + "installation": None, "custom_provider": None, "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -261,6 +296,7 @@ def test_data_integration_preserves_nullable_fields(self): serialized = instance.to_dict() assert serialized["description"] is None assert serialized["scopes"] is None + assert serialized["installation"] is None assert serialized["custom_provider"] is None def test_data_integration_round_trips_unknown_enum_values(self): @@ -274,11 +310,13 @@ def test_data_integration_round_trips_unknown_enum_values(self): "state": "unexpected_data_integration_state", "scopes": ["repo", "read:org"], "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + "auth_methods": ["oauth"], "credentials": { "type": "custom", "client_id": "Iv1.abc123", "redacted_client_secret": "6789", }, + "installation": None, "custom_provider": { "name": "My OAuth App", "authorization_url": "https://provider.example.com/oauth/authorize", @@ -757,6 +795,40 @@ def test_data_integration_credential_round_trips_unknown_enum_values(self): instance = DataIntegrationCredential.from_dict(data) assert instance.to_dict() == data + def test_data_integration_installation_round_trip(self): + data = load_fixture("data_integration_installation.json") + instance = DataIntegrationInstallation.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DataIntegrationInstallation.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_data_integration_installation_minimal_payload(self): + data = { + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": None, + "api_key_last_4": None, + } + instance = DataIntegrationInstallation.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["api_key_last_4"] == data["api_key_last_4"] + + def test_data_integration_installation_preserves_nullable_fields(self): + data = { + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": None, + "api_key_last_4": None, + } + instance = DataIntegrationInstallation.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["api_key_last_4"] is None + def test_data_integration_custom_provider_round_trip(self): data = load_fixture("data_integration_custom_provider.json") instance = DataIntegrationCustomProvider.from_dict(data) diff --git a/tests/test_pipes_provider_models_round_trip.py b/tests/test_pipes_provider_models_round_trip.py new file mode 100644 index 00000000..485b13af --- /dev/null +++ b/tests/test_pipes_provider_models_round_trip.py @@ -0,0 +1,171 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.pipes_provider.models import ( + DataIntegrationConfigurationListResponse, + DataIntegrationConfigurationResponse, + DataIntegrationCredentials, +) + + +class TestModelRoundTrip: + def test_data_integration_credentials_round_trip(self): + data = load_fixture("data_integration_credentials.json") + instance = DataIntegrationCredentials.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DataIntegrationCredentials.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_data_integration_credentials_minimal_payload(self): + data = { + "credentials_type": "organization", + "has_credentials": True, + "client_id": None, + "client_secret_last_four": None, + "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + } + instance = DataIntegrationCredentials.from_dict(data) + serialized = instance.to_dict() + assert serialized["credentials_type"] == data["credentials_type"] + assert serialized["has_credentials"] == data["has_credentials"] + assert serialized["client_id"] == data["client_id"] + assert serialized["client_secret_last_four"] == data["client_secret_last_four"] + assert serialized["redirect_uri"] == data["redirect_uri"] + + def test_data_integration_credentials_preserves_nullable_fields(self): + data = { + "credentials_type": "organization", + "has_credentials": True, + "client_id": None, + "client_secret_last_four": None, + "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + } + instance = DataIntegrationCredentials.from_dict(data) + serialized = instance.to_dict() + assert serialized["client_id"] is None + assert serialized["client_secret_last_four"] is None + + def test_data_integration_credentials_round_trips_unknown_enum_values(self): + data = { + "credentials_type": "unexpected_data_integration_credentials_credentials_type", + "has_credentials": True, + "client_id": "client_01EHZNVPK3SFK441A1RGBFSHRT", + "client_secret_last_four": "1a2b", + "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + } + instance = DataIntegrationCredentials.from_dict(data) + assert instance.to_dict() == data + + def test_data_integration_configuration_response_round_trip(self): + data = load_fixture("data_integration_configuration_response.json") + instance = DataIntegrationConfigurationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DataIntegrationConfigurationResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_data_integration_configuration_response_minimal_payload(self): + data = { + "object": "data_integration_configuration", + "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "github", + "name": "GitHub", + "enabled": True, + "scopes": None, + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + } + instance = DataIntegrationConfigurationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["enabled"] == data["enabled"] + assert serialized["scopes"] == data["scopes"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_data_integration_configuration_response_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "data_integration_configuration", + "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "github", + "name": "GitHub", + "enabled": True, + "scopes": ["repo", "user:email"], + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + } + instance = DataIntegrationConfigurationResponse.from_dict(data) + serialized = instance.to_dict() + assert "credentials" not in serialized + + def test_data_integration_configuration_response_preserves_nullable_fields(self): + data = { + "object": "data_integration_configuration", + "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "github", + "name": "GitHub", + "enabled": True, + "scopes": None, + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + "credentials": { + "credentials_type": "organization", + "has_credentials": True, + "client_id": "client_01EHZNVPK3SFK441A1RGBFSHRT", + "client_secret_last_four": "1a2b", + "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + }, + } + instance = DataIntegrationConfigurationResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["scopes"] is None + + def test_data_integration_configuration_list_response_round_trip(self): + data = load_fixture("data_integration_configuration_list_response.json") + instance = DataIntegrationConfigurationListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DataIntegrationConfigurationListResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_data_integration_configuration_list_response_minimal_payload(self): + data = { + "object": "list", + "data": [ + { + "object": "data_integration_configuration", + "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "github", + "name": "GitHub", + "enabled": True, + "scopes": ["repo", "user:email"], + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:30:00.000Z", + "credentials": { + "credentials_type": "organization", + "has_credentials": True, + "client_id": "client_01EHZNVPK3SFK441A1RGBFSHRT", + "client_secret_last_four": "1a2b", + "redirect_uri": "https://api.workos.com/data-integrations/github/dik_01EHZNVPK3SFK441A1RGBFSHRT/callback", + }, + } + ], + } + instance = DataIntegrationConfigurationListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["data"] == data["data"] diff --git a/tests/test_sso_models_round_trip.py b/tests/test_sso_models_round_trip.py new file mode 100644 index 00000000..3b8dd9d6 --- /dev/null +++ b/tests/test_sso_models_round_trip.py @@ -0,0 +1,349 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.sso.models import ( + Connection, + ConnectionDomain, + Profile, + SSOAuthorizeUrlResponse, + SSOLogoutAuthorizeResponse, + SSOTokenResponse, + SSOTokenResponseOAuthToken, +) + + +class TestModelRoundTrip: + def test_connection_round_trip(self): + data = load_fixture("connection.json") + instance = Connection.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Connection.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_minimal_payload(self): + data = { + "object": "connection", + "id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "name": "Foo Corp", + "state": "active", + "status": "linked", + "domains": [ + { + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "object": "connection_domain", + "domain": "foo-corp.com", + } + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Connection.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["connection_type"] == data["connection_type"] + assert serialized["name"] == data["name"] + assert serialized["state"] == data["state"] + assert serialized["status"] == data["status"] + assert serialized["domains"] == data["domains"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_connection_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "connection", + "id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "name": "Foo Corp", + "state": "active", + "status": "linked", + "domains": [ + { + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "object": "connection_domain", + "domain": "foo-corp.com", + } + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Connection.from_dict(data) + serialized = instance.to_dict() + assert "organization_id" not in serialized + assert "callback_endpoint" not in serialized + + def test_connection_round_trips_unknown_enum_values(self): + data = { + "object": "connection", + "id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "connection_type": "unexpected_connection_connection_type", + "name": "Foo Corp", + "state": "active", + "status": "linked", + "domains": [ + { + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "object": "connection_domain", + "domain": "foo-corp.com", + } + ], + "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = Connection.from_dict(data) + assert instance.to_dict() == data + + def test_sso_authorize_url_response_round_trip(self): + data = load_fixture("sso_authorize_url_response.json") + instance = SSOAuthorizeUrlResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SSOAuthorizeUrlResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_sso_authorize_url_response_minimal_payload(self): + data = { + "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=example&redirect_uri=https%3A%2F%2Fapi.workos.com%2Fsso%2Fcallback&response_type=code&scope=openid%20profile%20email" + } + instance = SSOAuthorizeUrlResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["url"] == data["url"] + + def test_profile_round_trip(self): + data = load_fixture("profile.json") + instance = Profile.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Profile.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_profile_minimal_payload(self): + data = { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": None, + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": None, + "last_name": None, + "name": None, + "raw_attributes": {"key": {}}, + } + instance = Profile.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["connection_id"] == data["connection_id"] + assert serialized["connection_type"] == data["connection_type"] + assert serialized["idp_id"] == data["idp_id"] + assert serialized["email"] == data["email"] + assert serialized["first_name"] == data["first_name"] + assert serialized["last_name"] == data["last_name"] + assert serialized["name"] == data["name"] + assert serialized["raw_attributes"] == data["raw_attributes"] + + def test_profile_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": "Todd", + "last_name": "Rundgren", + "name": "Todd Rundgren", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "raw_attributes": {"key": {}}, + } + instance = Profile.from_dict(data) + serialized = instance.to_dict() + assert "groups" not in serialized + assert "custom_attributes" not in serialized + + def test_profile_preserves_nullable_fields(self): + data = { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": None, + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": None, + "last_name": None, + "name": None, + "role": None, + "roles": None, + "groups": ["Engineering", "Admins"], + "custom_attributes": {"key": {}}, + "raw_attributes": {"key": {}}, + } + instance = Profile.from_dict(data) + serialized = instance.to_dict() + assert serialized["organization_id"] is None + assert serialized["first_name"] is None + assert serialized["last_name"] is None + assert serialized["name"] is None + assert serialized["role"] is None + assert serialized["roles"] is None + + def test_profile_round_trips_unknown_enum_values(self): + data = { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "unexpected_profile_connection_type", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": "Todd", + "last_name": "Rundgren", + "name": "Todd Rundgren", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "groups": ["Engineering", "Admins"], + "custom_attributes": {"key": {}}, + "raw_attributes": {"key": {}}, + } + instance = Profile.from_dict(data) + assert instance.to_dict() == data + + def test_sso_token_response_round_trip(self): + data = load_fixture("sso_token_response.json") + instance = SSOTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SSOTokenResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_sso_token_response_minimal_payload(self): + data = { + "token_type": "Bearer", + "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNzby...", + "expires_in": 600, + "profile": { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": "Todd", + "last_name": "Rundgren", + "name": "Todd Rundgren", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "groups": ["Engineering", "Admins"], + "custom_attributes": {"key": {}}, + "raw_attributes": {"key": {}}, + }, + } + instance = SSOTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["token_type"] == data["token_type"] + assert serialized["access_token"] == data["access_token"] + assert serialized["expires_in"] == data["expires_in"] + assert serialized["profile"] == data["profile"] + + def test_sso_token_response_omits_absent_optional_non_nullable_fields(self): + data = { + "token_type": "Bearer", + "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNzby...", + "expires_in": 600, + "profile": { + "object": "profile", + "id": "prof_01DMC79VCBZ0NY2099737PSVF1", + "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", + "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", + "connection_type": "OktaSAML", + "idp_id": "103456789012345678901", + "email": "todd@example.com", + "first_name": "Todd", + "last_name": "Rundgren", + "name": "Todd Rundgren", + "role": {"slug": "admin"}, + "roles": [{"slug": "admin"}], + "groups": ["Engineering", "Admins"], + "custom_attributes": {"key": {}}, + "raw_attributes": {"key": {}}, + }, + } + instance = SSOTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert "oauth_tokens" not in serialized + + def test_sso_logout_authorize_response_round_trip(self): + data = load_fixture("sso_logout_authorize_response.json") + instance = SSOLogoutAuthorizeResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SSOLogoutAuthorizeResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_sso_logout_authorize_response_minimal_payload(self): + data = { + "logout_url": "https://auth.workos.com/sso/logout?token=eyJhbGciOiJSUzI1NiJ9", + "logout_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9maWxlX2lkIjoicHJvZl8wMUdXUTFHMEgyRk02QVNFRjBIUzEzSENXOS0zMDRrZzAzZyIsImV4cCI6IjE1MTYyMzkwMjIifQ.Wru9Qlnf5DpohtGCKhZU4cVOd3zpiu7QQ-XEX--5A_4", + } + instance = SSOLogoutAuthorizeResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["logout_url"] == data["logout_url"] + assert serialized["logout_token"] == data["logout_token"] + + def test_sso_token_response_oauth_token_round_trip(self): + data = load_fixture("sso_token_response_oauth_token.json") + instance = SSOTokenResponseOAuthToken.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = SSOTokenResponseOAuthToken.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_sso_token_response_oauth_token_minimal_payload(self): + data = { + "provider": "GoogleOAuth", + "refresh_token": "1//04g...", + "access_token": "ya29.a0ARrdaM...", + "expires_at": 1735141800, + "scopes": ["profile", "email", "openid"], + } + instance = SSOTokenResponseOAuthToken.from_dict(data) + serialized = instance.to_dict() + assert serialized["provider"] == data["provider"] + assert serialized["refresh_token"] == data["refresh_token"] + assert serialized["access_token"] == data["access_token"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["scopes"] == data["scopes"] + + def test_connection_domain_round_trip(self): + data = load_fixture("connection_domain.json") + instance = ConnectionDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectionDomain.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connection_domain_minimal_payload(self): + data = { + "id": "org_domain_01EHZNVPK2QXHMVWCEDQEKY69A", + "object": "connection_domain", + "domain": "foo-corp.com", + } + instance = ConnectionDomain.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["object"] == data["object"] + assert serialized["domain"] == data["domain"] diff --git a/tests/test_user_management.py b/tests/test_user_management.py index 77a19a1b..5c70a95c 100644 --- a/tests/test_user_management.py +++ b/tests/test_user_management.py @@ -21,6 +21,7 @@ MagicAuth, MagicAuthSendMagicAuthCodeAndReturnResponse, PasswordReset, + RadarChallenge, RedirectUri, ResetPasswordResponse, SendRadarSmsChallengeResponse, @@ -115,6 +116,18 @@ def test_create_radar_challenge(self, workos, httpx_mock): ) assert body["phone_number"] == "test_phone_number" + def test_get_radar_challenge(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("radar_challenge.json"), + ) + result = workos.user_management.get_radar_challenge("test_id") + assert isinstance(result, RadarChallenge) + assert result.object == "radar_challenge" + assert result.id == "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/user_management/radar_challenges/test_id") + def test_get_logout_url(self, workos): result = workos.user_management.get_logout_url(session_id="test_session_id") assert isinstance(result, str) @@ -619,13 +632,21 @@ def test_create_redirect_uri(self, workos, httpx_mock): result = workos.user_management.create_redirect_uri(uri="test_uri") assert isinstance(result, RedirectUri) assert result.object == "redirect_uri" - assert result.id == "ruri_01EHZNVPK3SFK441A1RGBFSHRT" + assert result.id == "redir_01EHZNVPK3SFK441A1RGBFSHRT" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/user_management/redirect_uris") body = json.loads(request.content) assert body["uri"] == "test_uri" + def test_delete_redirect_uris(self, workos, httpx_mock): + httpx_mock.add_response(status_code=204) + result = workos.user_management.delete_redirect_uris("test_id") + assert result is None + request = httpx_mock.get_request() + assert request.method == "DELETE" + assert request.url.path.endswith("/user_management/redirect_uris/test_id") + def test_list_user_authorized_applications(self, workos, httpx_mock): httpx_mock.add_response( json=load_fixture("list_authorized_connect_application_list_data.json"), @@ -753,7 +774,7 @@ def test_authenticate_with_refresh_token(self, workos, httpx_mock): def test_authenticate_with_magic_auth(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_magic_auth( - code="test_value", email="test_value" + code="test_code", email="test_email" ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -764,7 +785,8 @@ def test_authenticate_with_magic_auth(self, workos, httpx_mock): def test_authenticate_with_email_verification(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_email_verification( - code="test_value", pending_authentication_token="test_value" + code="test_code", + pending_authentication_token="test_pending_authentication_token", ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -790,7 +812,8 @@ def test_authenticate_with_totp(self, workos, httpx_mock): def test_authenticate_with_organization_selection(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_organization_selection( - pending_authentication_token="test_value", organization_id="test_value" + pending_authentication_token="test_pending_authentication_token", + organization_id="test_organization_id", ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -803,7 +826,7 @@ def test_authenticate_with_organization_selection(self, workos, httpx_mock): def test_authenticate_with_device_code(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_device_code( - device_code="test_value" + device_code="test_device_code" ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -814,9 +837,9 @@ def test_authenticate_with_device_code(self, workos, httpx_mock): def test_authenticate_with_radar_email_challenge(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_radar_email_challenge( - code="test_value", - radar_challenge_id="test_value", - pending_authentication_token="test_value", + code="test_code", + radar_challenge_id="test_radar_challenge_id", + pending_authentication_token="test_pending_authentication_token", ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -830,10 +853,10 @@ def test_authenticate_with_radar_email_challenge(self, workos, httpx_mock): def test_authenticate_with_radar_sms_challenge(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = workos.user_management.authenticate_with_radar_sms_challenge( - code="test_value", - verification_id="test_value", - phone_number="test_value", - pending_authentication_token="test_value", + code="test_code", + verification_id="test_verification_id", + phone_number="test_phone_number", + pending_authentication_token="test_pending_authentication_token", ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -982,6 +1005,17 @@ async def test_create_radar_challenge(self, async_workos, httpx_mock): assert request.method == "POST" assert request.url.path.endswith("/user_management/radar_challenges") + @pytest.mark.asyncio + async def test_get_radar_challenge(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("radar_challenge.json")) + result = await async_workos.user_management.get_radar_challenge("test_id") + assert isinstance(result, RadarChallenge) + assert result.object == "radar_challenge" + assert result.id == "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/user_management/radar_challenges/test_id") + def test_get_logout_url(self, async_workos): result = async_workos.user_management.get_logout_url( session_id="test_session_id" @@ -1473,11 +1507,20 @@ async def test_create_redirect_uri(self, async_workos, httpx_mock): result = await async_workos.user_management.create_redirect_uri(uri="test_uri") assert isinstance(result, RedirectUri) assert result.object == "redirect_uri" - assert result.id == "ruri_01EHZNVPK3SFK441A1RGBFSHRT" + assert result.id == "redir_01EHZNVPK3SFK441A1RGBFSHRT" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/user_management/redirect_uris") + @pytest.mark.asyncio + async def test_delete_redirect_uris(self, async_workos, httpx_mock): + httpx_mock.add_response(status_code=204) + result = await async_workos.user_management.delete_redirect_uris("test_id") + assert result is None + request = httpx_mock.get_request() + assert request.method == "DELETE" + assert request.url.path.endswith("/user_management/redirect_uris/test_id") + @pytest.mark.asyncio async def test_list_user_authorized_applications(self, async_workos, httpx_mock): httpx_mock.add_response( @@ -1620,7 +1663,7 @@ async def test_authenticate_with_refresh_token(self, async_workos, httpx_mock): async def test_authenticate_with_magic_auth(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = await async_workos.user_management.authenticate_with_magic_auth( - code="test_value", email="test_value" + code="test_code", email="test_email" ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -1633,7 +1676,8 @@ async def test_authenticate_with_email_verification(self, async_workos, httpx_mo httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = ( await async_workos.user_management.authenticate_with_email_verification( - code="test_value", pending_authentication_token="test_value" + code="test_code", + pending_authentication_token="test_pending_authentication_token", ) ) assert isinstance(result, AuthenticateResponse) @@ -1665,7 +1709,8 @@ async def test_authenticate_with_organization_selection( httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = ( await async_workos.user_management.authenticate_with_organization_selection( - pending_authentication_token="test_value", organization_id="test_value" + pending_authentication_token="test_pending_authentication_token", + organization_id="test_organization_id", ) ) assert isinstance(result, AuthenticateResponse) @@ -1680,7 +1725,7 @@ async def test_authenticate_with_organization_selection( async def test_authenticate_with_device_code(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = await async_workos.user_management.authenticate_with_device_code( - device_code="test_value" + device_code="test_device_code" ) assert isinstance(result, AuthenticateResponse) request = httpx_mock.get_request() @@ -1695,9 +1740,9 @@ async def test_authenticate_with_radar_email_challenge( httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = ( await async_workos.user_management.authenticate_with_radar_email_challenge( - code="test_value", - radar_challenge_id="test_value", - pending_authentication_token="test_value", + code="test_code", + radar_challenge_id="test_radar_challenge_id", + pending_authentication_token="test_pending_authentication_token", ) ) assert isinstance(result, AuthenticateResponse) @@ -1716,10 +1761,10 @@ async def test_authenticate_with_radar_sms_challenge( httpx_mock.add_response(json=load_fixture("authenticate_response.json")) result = ( await async_workos.user_management.authenticate_with_radar_sms_challenge( - code="test_value", - verification_id="test_value", - phone_number="test_value", - pending_authentication_token="test_value", + code="test_code", + verification_id="test_verification_id", + phone_number="test_phone_number", + pending_authentication_token="test_pending_authentication_token", ) ) assert isinstance(result, AuthenticateResponse) diff --git a/tests/test_user_management_models_round_trip.py b/tests/test_user_management_models_round_trip.py index 8025ea15..9fa36f6e 100644 --- a/tests/test_user_management_models_round_trip.py +++ b/tests/test_user_management_models_round_trip.py @@ -22,6 +22,7 @@ MagicAuth, MagicAuthSendMagicAuthCodeAndReturnResponse, PasswordReset, + RadarChallenge, RedirectUri, ResetPasswordResponse, SendRadarSmsChallengeResponse, @@ -148,6 +149,38 @@ def test_cors_origin_response_minimal_payload(self): assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] + def test_radar_challenge_round_trip(self): + data = load_fixture("radar_challenge.json") + instance = RadarChallenge.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = RadarChallenge.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_radar_challenge_minimal_payload(self): + data = { + "object": "radar_challenge", + "id": "radar_challenge_01HWZBQZY2M3AMQW166Q22K88F", + "type": "email", + "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5", + "email": "marcelina.davis@example.com", + "expires_at": "2026-01-15T12:00:00.000Z", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "code": "123456", + } + instance = RadarChallenge.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["type"] == data["type"] + assert serialized["user_id"] == data["user_id"] + assert serialized["email"] == data["email"] + assert serialized["expires_at"] == data["expires_at"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["code"] == data["code"] + def test_send_radar_sms_challenge_response_round_trip(self): data = load_fixture("send_radar_sms_challenge_response.json") instance = SendRadarSmsChallengeResponse.from_dict(data) @@ -177,7 +210,7 @@ def test_redirect_uri_round_trip(self): def test_redirect_uri_minimal_payload(self): data = { "object": "redirect_uri", - "id": "ruri_01EHZNVPK3SFK441A1RGBFSHRT", + "id": "redir_01EHZNVPK3SFK441A1RGBFSHRT", "uri": "https://example.com/callback", "default": True, "created_at": "2026-01-15T12:00:00.000Z", diff --git a/tests/test_vault_models_round_trip.py b/tests/test_vault_models_round_trip.py new file mode 100644 index 00000000..c1dae83e --- /dev/null +++ b/tests/test_vault_models_round_trip.py @@ -0,0 +1,278 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.vault.models import ( + Actor, + CreateDataKeyResponse, + DecryptResponse, + DeleteObjectResponse, + ObjectMetadata, + ObjectSummary, + ObjectVersion, + ObjectWithoutValue, + VaultObject, + VersionListResponse, +) + + +class TestModelRoundTrip: + def test_actor_round_trip(self): + data = load_fixture("actor.json") + instance = Actor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Actor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_actor_minimal_payload(self): + data = {"id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", "name": "My API Key"} + instance = Actor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_create_data_key_response_round_trip(self): + data = load_fixture("create_data_key_response.json") + instance = CreateDataKeyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = CreateDataKeyResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_create_data_key_response_minimal_payload(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "encrypted_keys": "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61", + } + instance = CreateDataKeyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["context"] == data["context"] + assert serialized["data_key"] == data["data_key"] + assert serialized["encrypted_keys"] == data["encrypted_keys"] + assert serialized["id"] == data["id"] + + def test_decrypt_response_round_trip(self): + data = load_fixture("decrypt_response.json") + instance = DecryptResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DecryptResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_decrypt_response_minimal_payload(self): + data = { + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61", + } + instance = DecryptResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["data_key"] == data["data_key"] + assert serialized["id"] == data["id"] + + def test_delete_object_response_round_trip(self): + data = load_fixture("delete_object_response.json") + instance = DeleteObjectResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DeleteObjectResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_delete_object_response_minimal_payload(self): + data = {"name": "my-secret", "success": True} + instance = DeleteObjectResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] == data["name"] + assert serialized["success"] == data["success"] + + def test_vault_object_round_trip(self): + data = load_fixture("vault_object.json") + instance = VaultObject.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultObject.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_object_minimal_payload(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + }, + "name": "my-secret", + "value": "s3cr3t-v4lu3", + } + instance = VaultObject.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["metadata"] == data["metadata"] + assert serialized["name"] == data["name"] + assert serialized["value"] == data["value"] + + def test_object_metadata_round_trip(self): + data = load_fixture("object_metadata.json") + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectMetadata.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_metadata_minimal_payload(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + } + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["context"] == data["context"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["id"] == data["id"] + assert serialized["key_id"] == data["key_id"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["updated_by"] == data["updated_by"] + + def test_object_metadata_preserves_nullable_fields(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": None, + } + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["version_id"] is None + + def test_object_summary_round_trip(self): + data = load_fixture("object_summary.json") + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectSummary.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_summary_minimal_payload(self): + data = {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "my-secret"} + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_object_summary_preserves_nullable_fields(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "my-secret", + "updated_at": None, + } + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized["updated_at"] is None + + def test_object_version_round_trip(self): + data = load_fixture("object_version.json") + instance = ObjectVersion.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectVersion.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_version_minimal_payload(self): + data = { + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": True, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256, + } + instance = ObjectVersion.from_dict(data) + serialized = instance.to_dict() + assert serialized["created_at"] == data["created_at"] + assert serialized["current_version"] == data["current_version"] + assert serialized["etag"] == data["etag"] + assert serialized["id"] == data["id"] + assert serialized["size"] == data["size"] + + def test_object_without_value_round_trip(self): + data = load_fixture("object_without_value.json") + instance = ObjectWithoutValue.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectWithoutValue.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_without_value_minimal_payload(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + }, + "name": "my-secret", + } + instance = ObjectWithoutValue.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["metadata"] == data["metadata"] + assert serialized["name"] == data["name"] + + def test_version_list_response_round_trip(self): + data = load_fixture("version_list_response.json") + instance = VersionListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VersionListResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_version_list_response_minimal_payload(self): + data = { + "data": [ + { + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": True, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256, + } + ], + "list_metadata": { + "after": "b21f3a8c-7e4d-4b1a-9c5e-2d8f6a7b3c4e", + "before": "a10e2b7d-6c3f-4a2b-8d1e-3f9a5b8c7d6e", + }, + } + instance = VersionListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["data"] == data["data"] + assert serialized["list_metadata"] == data["list_metadata"] diff --git a/tests/test_widgets.py b/tests/test_widgets.py index f4102093..c280de85 100644 --- a/tests/test_widgets.py +++ b/tests/test_widgets.py @@ -1,6 +1,5 @@ # This file is auto-generated by oagen. Do not edit. -import json import pytest from workos import WorkOSClient, AsyncWorkOSClient @@ -22,20 +21,17 @@ def test_create_token(self, workos, httpx_mock): httpx_mock.add_response( json=load_fixture("widget_session_token_response.json"), ) - result = workos.widgets.create_token(organization_id="test_organization_id") + result = workos.widgets.create_token() assert isinstance(result, WidgetSessionTokenResponse) assert result.token == "eyJhbGciOiJSUzI1NiIsImtpZCI6InNlc3Npb24..." request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/widgets/token") - body = json.loads(request.content) - assert body["organization_id"] == "test_organization_id" def test_create_token_with_request_options(self, workos, httpx_mock): httpx_mock.add_response(json=load_fixture("widget_session_token_response.json")) workos.widgets.create_token( - organization_id="test_organization_id", - request_options={"extra_headers": {"X-Custom": "value"}}, + request_options={"extra_headers": {"X-Custom": "value"}} ) request = httpx_mock.get_request() assert request.headers["X-Custom"] == "value" @@ -46,7 +42,7 @@ def test_create_token_unauthorized(self, workos, httpx_mock): json={"message": "Unauthorized"}, ) with pytest.raises(AuthenticationError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() def test_create_token_not_found(self, httpx_mock): workos = WorkOSClient( @@ -55,7 +51,7 @@ def test_create_token_not_found(self, httpx_mock): try: httpx_mock.add_response(status_code=404, json={"message": "Not found"}) with pytest.raises(NotFoundError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() finally: workos.close() @@ -70,7 +66,7 @@ def test_create_token_rate_limited(self, httpx_mock): json={"message": "Slow down"}, ) with pytest.raises(RateLimitExceededError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() finally: workos.close() @@ -81,7 +77,7 @@ def test_create_token_server_error(self, httpx_mock): try: httpx_mock.add_response(status_code=500, json={"message": "Server error"}) with pytest.raises(ServerError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() finally: workos.close() @@ -92,7 +88,7 @@ def test_create_token_bad_request(self, httpx_mock): try: httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) with pytest.raises(BadRequestError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() finally: workos.close() @@ -103,7 +99,7 @@ def test_create_token_unprocessable(self, httpx_mock): try: httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) with pytest.raises(UnprocessableEntityError): - workos.widgets.create_token(organization_id="test_organization_id") + workos.widgets.create_token() finally: workos.close() @@ -112,9 +108,7 @@ class TestAsyncWidgets: @pytest.mark.asyncio async def test_create_token(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("widget_session_token_response.json")) - result = await async_workos.widgets.create_token( - organization_id="test_organization_id" - ) + result = await async_workos.widgets.create_token() assert isinstance(result, WidgetSessionTokenResponse) assert result.token == "eyJhbGciOiJSUzI1NiIsImtpZCI6InNlc3Npb24..." request = httpx_mock.get_request() @@ -125,8 +119,7 @@ async def test_create_token(self, async_workos, httpx_mock): async def test_create_token_with_request_options(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("widget_session_token_response.json")) await async_workos.widgets.create_token( - organization_id="test_organization_id", - request_options={"extra_headers": {"X-Custom": "value"}}, + request_options={"extra_headers": {"X-Custom": "value"}} ) request = httpx_mock.get_request() assert request.headers["X-Custom"] == "value" @@ -135,9 +128,7 @@ async def test_create_token_with_request_options(self, async_workos, httpx_mock) async def test_create_token_unauthorized(self, async_workos, httpx_mock): httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"}) with pytest.raises(AuthenticationError): - await async_workos.widgets.create_token( - organization_id="test_organization_id" - ) + await async_workos.widgets.create_token() @pytest.mark.asyncio async def test_create_token_not_found(self, httpx_mock): @@ -147,9 +138,7 @@ async def test_create_token_not_found(self, httpx_mock): try: httpx_mock.add_response(status_code=404, json={"message": "Not found"}) with pytest.raises(NotFoundError): - await workos.widgets.create_token( - organization_id="test_organization_id" - ) + await workos.widgets.create_token() finally: await workos.close() @@ -165,9 +154,7 @@ async def test_create_token_rate_limited(self, httpx_mock): json={"message": "Slow down"}, ) with pytest.raises(RateLimitExceededError): - await workos.widgets.create_token( - organization_id="test_organization_id" - ) + await workos.widgets.create_token() finally: await workos.close() @@ -179,9 +166,7 @@ async def test_create_token_server_error(self, httpx_mock): try: httpx_mock.add_response(status_code=500, json={"message": "Server error"}) with pytest.raises(ServerError): - await workos.widgets.create_token( - organization_id="test_organization_id" - ) + await workos.widgets.create_token() finally: await workos.close() @@ -193,9 +178,7 @@ async def test_create_token_bad_request(self, httpx_mock): try: httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) with pytest.raises(BadRequestError): - await workos.widgets.create_token( - organization_id="test_organization_id" - ) + await workos.widgets.create_token() finally: await workos.close() @@ -207,8 +190,6 @@ async def test_create_token_unprocessable(self, httpx_mock): try: httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) with pytest.raises(UnprocessableEntityError): - await workos.widgets.create_token( - organization_id="test_organization_id" - ) + await workos.widgets.create_token() finally: await workos.close() diff --git a/tests/test_widgets_models_round_trip.py b/tests/test_widgets_models_round_trip.py new file mode 100644 index 00000000..b7897d3c --- /dev/null +++ b/tests/test_widgets_models_round_trip.py @@ -0,0 +1,23 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Model round-trip tests: from_dict(to_dict()) preserves data.""" + +from tests.generated_helpers import load_fixture + +from workos.widgets.models import WidgetSessionTokenResponse + + +class TestModelRoundTrip: + def test_widget_session_token_response_round_trip(self): + data = load_fixture("widget_session_token_response.json") + instance = WidgetSessionTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = WidgetSessionTokenResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_widget_session_token_response_minimal_payload(self): + data = {"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNlc3Npb24..."} + instance = WidgetSessionTokenResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["token"] == data["token"]