From 8f354423358753f10251a8f737c27301339df432 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 3 Jan 2026 13:18:04 -0500 Subject: [PATCH] resource provider and service improvements --- shared/lib/Files/Provider/IProviderBase.php | 84 +----- shared/lib/Mail/Provider/IProviderBase.php | 132 ---------- .../Mail/Provider/IProviderServiceMutate.php | 77 ------ .../Mail/Provider/ProviderBaseInterface.php | 41 +++ .../ProviderServiceDiscoverInterface.php | 67 +++++ .../ProviderServiceMutateInterface.php | 33 +++ .../Provider/ProviderServiceTestInterface.php | 79 ++++++ shared/lib/Mail/Service/IServiceIdentity.php | 36 --- .../Mail/Service/IServiceIdentityApiKey.php | 39 --- .../Mail/Service/IServiceIdentityBasic.php | 39 --- .../Mail/Service/IServiceIdentityOAuth.php | 68 ----- shared/lib/Mail/Service/IServiceLocation.php | 105 -------- ...rviceBase.php => ServiceBaseInterface.php} | 102 +------- ... => ServiceCollectionMutableInterface.php} | 2 +- .../Mail/Service/ServiceIdentityApiKey.php | 78 ------ .../lib/Mail/Service/ServiceIdentityBasic.php | 78 ------ shared/lib/Mail/Service/ServiceLocation.php | 211 --------------- ...php => ServiceMessageMutableInterface.php} | 2 +- ...nd.php => ServiceMessageSendInterface.php} | 2 +- .../Mail/Service/ServiceMutableInterface.php | 46 ++++ shared/lib/Mail/Service/ServiceScope.php | 37 --- .../ResourceProviderBaseInterface.php | 79 ++++++ ...ResourceProviderServiceMutateInterface.php | 49 ++++ .../Provider/ResourceServiceBaseInterface.php | 86 +++++++ .../ResourceServiceConfigureInterface.php | 44 ++++ .../Provider/ResourceServiceIdentityBasic.php | 61 +++++ .../ResourceServiceIdentityBearer.php | 41 +++ .../ResourceServiceIdentityInterface.php | 37 +++ .../Provider/ResourceServiceIdentityOAuth.php | 121 +++++++++ .../Provider/ResourceServiceLocationFile.php | 51 ++++ .../ResourceServiceLocationInterface.php | 37 +++ .../ResourceServiceLocationSocketSole.php | 131 ++++++++++ .../ResourceServiceLocationSocketSplit.php | 240 ++++++++++++++++++ .../Provider/ResourceServiceLocationUri.php | 150 +++++++++++ .../ResourceServiceMutateInterface.php | 46 ++++ shared/lib/Security/Crypto.php | 2 +- 36 files changed, 1447 insertions(+), 1086 deletions(-) delete mode 100644 shared/lib/Mail/Provider/IProviderBase.php delete mode 100644 shared/lib/Mail/Provider/IProviderServiceMutate.php create mode 100644 shared/lib/Mail/Provider/ProviderBaseInterface.php create mode 100644 shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php create mode 100644 shared/lib/Mail/Provider/ProviderServiceMutateInterface.php create mode 100644 shared/lib/Mail/Provider/ProviderServiceTestInterface.php delete mode 100644 shared/lib/Mail/Service/IServiceIdentity.php delete mode 100644 shared/lib/Mail/Service/IServiceIdentityApiKey.php delete mode 100644 shared/lib/Mail/Service/IServiceIdentityBasic.php delete mode 100644 shared/lib/Mail/Service/IServiceIdentityOAuth.php delete mode 100644 shared/lib/Mail/Service/IServiceLocation.php rename shared/lib/Mail/Service/{IServiceBase.php => ServiceBaseInterface.php} (72%) rename shared/lib/Mail/Service/{IServiceCollectionMutable.php => ServiceCollectionMutableInterface.php} (97%) delete mode 100644 shared/lib/Mail/Service/ServiceIdentityApiKey.php delete mode 100644 shared/lib/Mail/Service/ServiceIdentityBasic.php delete mode 100644 shared/lib/Mail/Service/ServiceLocation.php rename shared/lib/Mail/Service/{IServiceMessageMutable.php => ServiceMessageMutableInterface.php} (98%) rename shared/lib/Mail/Service/{IServiceSend.php => ServiceMessageSendInterface.php} (93%) create mode 100644 shared/lib/Mail/Service/ServiceMutableInterface.php delete mode 100644 shared/lib/Mail/Service/ServiceScope.php create mode 100644 shared/lib/Resource/Provider/ResourceProviderBaseInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceBaseInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceIdentityBasic.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceIdentityBearer.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceIdentityInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceIdentityOAuth.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceLocationFile.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceLocationInterface.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceLocationSocketSole.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceLocationSocketSplit.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceLocationUri.php create mode 100644 shared/lib/Resource/Provider/ResourceServiceMutateInterface.php diff --git a/shared/lib/Files/Provider/IProviderBase.php b/shared/lib/Files/Provider/IProviderBase.php index b1313fd..169d7f1 100644 --- a/shared/lib/Files/Provider/IProviderBase.php +++ b/shared/lib/Files/Provider/IProviderBase.php @@ -9,88 +9,8 @@ declare(strict_types=1); namespace KTXF\Files\Provider; -use JsonSerializable; -use KTXF\Files\Service\IServiceBase; +use KTXF\Resource\Provider\ResourceProviderInterface; -interface IProviderBase extends JsonSerializable { - - public const CAPABILITY_SERVICE_LIST = 'ServiceList'; - public const CAPABILITY_SERVICE_FETCH = 'ServiceFetch'; - public const CAPABILITY_SERVICE_EXTANT = 'ServiceExtant'; - - public const JSON_TYPE = 'files.provider'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; - - /** - * Confirms if specific capability is supported (e.g. 'ServiceList') - * - * @since 2025.11.01 - */ - public function capable(string $value): bool; - - /** - * Lists all supported capabilities - * - * @since 2025.11.01 - * - * @return array - */ - public function capabilities(): array; - - /** - * An arbitrary unique text string identifying this provider (e.g. UUID or 'system' or anything else) - * - * @since 2025.11.01 - */ - public function id(): string; - - /** - * The localized human friendly name of this provider (e.g. System File Provider) - * - * @since 2025.11.01 - */ - public function label(): string; - - /** - * Retrieve collection of services for a specific user - * - * @since 2025.11.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param array $filter filter criteria - * - * @return array collection of service objects - */ - public function serviceList(string $tenantId, string $userId, array $filter): array; - - /** - * Determine if any services are configured for a specific user - * - * @since 2025.11.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param int|string ...$identifiers variadic collection of service identifiers - * - * @return array collection of service identifiers with boolean values indicating if the service is available - */ - public function serviceExtant(string $tenantId, string $userId, int|string ...$identifiers): array; - - /** - * Retrieve a service with a specific identifier - * - * @since 2025.11.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param string|int $identifier service identifier - * - * @return IServiceBase|null returns service object or null if non found - */ - public function serviceFetch(string $tenantId, string $userId, string|int $identifier): ?IServiceBase; +interface IProviderBase extends ResourceProviderInterface { } diff --git a/shared/lib/Mail/Provider/IProviderBase.php b/shared/lib/Mail/Provider/IProviderBase.php deleted file mode 100644 index 8b83b65..0000000 --- a/shared/lib/Mail/Provider/IProviderBase.php +++ /dev/null @@ -1,132 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Provider; - -use JsonSerializable; -use KTXF\Mail\Selector\ServiceSelector; -use KTXF\Mail\Service\IServiceBase; - -/** - * Mail Provider Base Interface - * - * Core interface for mail providers with context-aware service discovery. - * - * @since 2025.05.01 - */ -interface IProviderBase extends JsonSerializable { - - public const CAPABILITY_SERVICE_LIST = 'ServiceList'; - public const CAPABILITY_SERVICE_FETCH = 'ServiceFetch'; - public const CAPABILITY_SERVICE_EXTANT = 'ServiceExtant'; - public const CAPABILITY_SERVICE_FIND_BY_ADDRESS = 'ServiceFindByAddress'; - - public const JSON_TYPE = 'mail.provider'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; - - /** - * Confirms if a specific capability is supported - * - * @since 2025.05.01 - * - * @param string $value Required capability e.g. 'ServiceList' - * - * @return bool - */ - public function capable(string $value): bool; - - /** - * Lists all supported capabilities - * - * @since 2025.05.01 - * - * @return array - */ - public function capabilities(): array; - - /** - * Gets the unique identifier for this provider - * - * @since 2025.05.01 - * - * @return string Provider ID (e.g., 'smtp', 'imap', 'jmap') - */ - public function id(): string; - - /** - * Gets the localized human-friendly name of this provider - * - * @since 2025.05.01 - * - * @return string Provider label (e.g., 'SMTP Mail Provider') - */ - public function label(): string; - - /** - * Lists services for a tenant, optionally filtered by user context - * - * When userId is null, returns only System-scoped services. - * When userId is provided, returns System-scoped services plus - * User-scoped services owned by that user. - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for context (null = system only) - * @param ServiceSelector|null $selector Optional filter criteria - * - * @return array - */ - public function serviceList(string $tenantId, ?string $userId = null, ?ServiceSelector $selector = null): array; - - /** - * Checks if specific services exist - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for context - * @param string|int ...$identifiers Service identifiers to check - * - * @return array Identifier => exists - */ - public function serviceExtant(string $tenantId, ?string $userId, string|int ...$identifiers): array; - - /** - * Fetches a specific service by identifier - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for context - * @param string|int $identifier Service identifier - * - * @return IServiceBase|null - */ - public function serviceFetch(string $tenantId, ?string $userId, string|int $identifier): ?IServiceBase; - - /** - * Finds a service that handles a specific email address - * - * Searches within the appropriate scope based on userId context. - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for context - * @param string $address Email address to find service for - * - * @return IServiceBase|null Service handling the address, or null - */ - public function serviceFindByAddress(string $tenantId, ?string $userId, string $address): ?IServiceBase; - -} diff --git a/shared/lib/Mail/Provider/IProviderServiceMutate.php b/shared/lib/Mail/Provider/IProviderServiceMutate.php deleted file mode 100644 index aeff98a..0000000 --- a/shared/lib/Mail/Provider/IProviderServiceMutate.php +++ /dev/null @@ -1,77 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Provider; - -use KTXF\Json\JsonDeserializable; -use KTXF\Mail\Service\IServiceBase; - -/** - * Mail Provider Service Mutate Interface - * - * Optional interface for providers that support service CRUD operations. - * - * @since 2025.05.01 - */ -interface IProviderServiceMutate extends JsonDeserializable { - - public const CAPABILITY_SERVICE_FRESH = 'ServiceFresh'; - public const CAPABILITY_SERVICE_CREATE = 'ServiceCreate'; - public const CAPABILITY_SERVICE_MODIFY = 'ServiceModify'; - public const CAPABILITY_SERVICE_DESTROY = 'ServiceDestroy'; - - /** - * Creates a new blank service instance for configuration - * - * @since 2025.05.01 - * - * @return IServiceBase Fresh service object - */ - public function serviceFresh(): IServiceBase; - - /** - * Creates a new service configuration - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId Owner user ID (null for system services) - * @param IServiceBase $service Service configuration to create - * - * @return string|int Created service identifier - */ - public function serviceCreate(string $tenantId, ?string $userId, IServiceBase $service): string|int; - - /** - * Modifies an existing service configuration - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for authorization context - * @param IServiceBase $service Service configuration to update - * - * @return string|int Updated service identifier - */ - public function serviceModify(string $tenantId, ?string $userId, IServiceBase $service): string|int; - - /** - * Destroys a service configuration - * - * @since 2025.05.01 - * - * @param string $tenantId Tenant identifier - * @param string|null $userId User identifier for authorization context - * @param IServiceBase $service Service to destroy - * - * @return bool True if destroyed, false if not found - */ - public function serviceDestroy(string $tenantId, ?string $userId, IServiceBase $service): bool; - -} diff --git a/shared/lib/Mail/Provider/ProviderBaseInterface.php b/shared/lib/Mail/Provider/ProviderBaseInterface.php new file mode 100644 index 0000000..10a3690 --- /dev/null +++ b/shared/lib/Mail/Provider/ProviderBaseInterface.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Provider; + +use KTXF\Mail\Service\ServiceBaseInterface; +use KTXF\Resource\Provider\ResourceProviderBaseInterface; + +/** + * Mail Provider Base Interface + * + * Core interface for mail providers with context-aware service discovery. + * + * @since 2025.05.01 + */ +interface ProviderBaseInterface extends ResourceProviderBaseInterface{ + + public const JSON_TYPE = 'mail.provider'; + + /** + * Finds a service that handles a specific email address + * + * Searches within the appropriate scope based on userId context. + * + * @since 2025.05.01 + * + * @param string $tenantId Tenant identifier + * @param string|null $userId User identifier for context + * @param string $address Email address to find service for + * + * @return IServiceBase|null Service handling the address, or null + */ + public function serviceFindByAddress(string $tenantId, ?string $userId, string $address): ?ServiceBaseInterface; + +} diff --git a/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php b/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php new file mode 100644 index 0000000..e5fbd2d --- /dev/null +++ b/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php @@ -0,0 +1,67 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Provider; + +/** + * Mail Provider Autodiscovery Interface + * + * Optional interface for mail providers that support automatic service discovery + * from email addresses or domains. Providers implementing this interface can + * discover mail service configurations using various methods specific to their + * protocol or provider type. + * + * Examples: + * - IMAP/SMTP providers: Mozilla Autoconfig, DNS SRV, well-known URIs + * - JMAP providers: Well-known JMAP endpoint discovery + * - Provider-specific: Gmail, Outlook, etc. with known configurations + * + * @since 2025.05.01 + */ +interface ProviderServiceDiscoverInterface extends ProviderBaseInterface { + + public const CAPABILITY_SERVICE_DISCOVER = 'ServiceDiscover'; + + /** + * Discover service configuration + * + * Attempts to discover service configuration using provider-specific methods. + * Each provider may use different discovery mechanisms: + * - IMAP/SMTP: config database, DNS SRV, well-known URIs, common patterns + * - JMAP: Well-known JMAP session discovery + * - Provider-specific: Known configurations for popular providers + * + * @since 2025.05.01 + * + * @param string $identity Identity to discover configuration for + * @param array $options Provider-specific options (e.g., preferred protocols, timeout) + * + * @return array Discovery results in the format: + * [ + * 'domain' => 'example.com', + * 'provider' => 'gmail|outlook|generic|etc', // Optional detected provider + * 'results' => [ + * [ + * 'protocol' => 'imap|smtp|jmap|etc', + * 'host' => 'imap.example.com', + * 'port' => 993, + * 'security' => 'ssl|tls|starttls|none', + * 'authentication' => ['plain', 'login', 'oauth2'], // Supported auth methods + * 'confidence' => 'high|medium|low', + * 'source' => 'mozilla|srv|wellknown|common|verified', // Discovery method used + * ], + * // ... more protocol results + * ] + * ] + * + * Returns empty results array if no configuration could be discovered. + */ + public function serviceDiscover(string $identity, array $options = []): array; + +} diff --git a/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php b/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php new file mode 100644 index 0000000..550f7f6 --- /dev/null +++ b/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Provider; + +use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface; + +/** + * Mail Provider Service Mutate Interface + * + * Optional interface for providers that support service CRUD operations. + * + * Implementations return ServiceMutableInterface instances (which extend ResourceServiceMutateInterface). + * + * @since 2025.05.01 + * + * @method ServiceMutableInterface serviceFresh() Construct a new blank mail service instance + * @method string serviceCreate(string $tenantId, ?string $userId, ServiceMutableInterface $service) Create a mail service configuration + * @method string serviceModify(string $tenantId, ?string $userId, ServiceMutableInterface $service) Modify a mail service configuration + * @method bool serviceDestroy(string $tenantId, ?string $userId, ServiceMutableInterface $service) Delete a mail service configuration + */ +interface ProviderServiceMutateInterface extends ProviderBaseInterface, ResourceProviderServiceMutateInterface { + + // Methods inherited from ResourceProviderServiceMutateInterface + // Implementations should return/accept ServiceMutableInterface instances + +} diff --git a/shared/lib/Mail/Provider/ProviderServiceTestInterface.php b/shared/lib/Mail/Provider/ProviderServiceTestInterface.php new file mode 100644 index 0000000..b6d186c --- /dev/null +++ b/shared/lib/Mail/Provider/ProviderServiceTestInterface.php @@ -0,0 +1,79 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Provider; + +use KTXF\Mail\Service\ServiceBaseInterface; + +/** + * Mail Provider Service Test Interface + * + * Optional interface for mail providers that support testing service connections. + * Providers implementing this interface can validate connection parameters, + * test authentication, and verify service availability before creating a + * persistent service configuration. + * + * Supports two testing modes: + * 1. Testing an existing service (validate current configuration) + * 2. Testing a fresh configuration (validate before saving) + * + * @since 2025.05.01 + */ +interface ProviderServiceTestInterface extends ProviderBaseInterface { + + public const CAPABILITY_SERVICE_TEST = 'ServiceTest'; + + /** + * Test a service connection + * + * Tests connectivity, authentication, and capabilities of a service. + * + * For new services: use serviceFresh() to create a service, configure it with + * setters, then pass it to this method for testing before persisting. + * + * For existing services: fetch the service and pass it directly. + * + * @since 2025.05.01 + * + * @param ServiceBaseInterface $service Service to test (can be fresh/unsaved or existing) + * @param array $options Provider-specific test options: + * - 'timeout' => int (seconds, default: 10) + * - 'verify_ssl' => bool (default: true) + * - 'test_send' => bool (attempt test send if capable, default: false) + * - 'test_receive' => bool (attempt mailbox access if capable, default: true) + * + * @return array Test results in the format: + * [ + * 'success' => bool, + * 'message' => 'Connection successful' | 'Error message', + * 'details' => [ + * 'connected' => bool, // Socket/HTTP connection succeeded + * 'authenticated' => bool, // Authentication succeeded + * 'capabilities' => ['IMAP4rev1', ...], // Server capabilities (if applicable) + * 'serverInfo' => 'Server version/banner', + * 'latency' => 123, // Connection time in milliseconds + * 'protocols' => [ + * 'inbound' => [ + * 'connected' => bool, + * 'authenticated' => bool, + * 'error' => 'error message if failed' + * ], + * 'outbound' => [ // For split-socket (IMAP+SMTP) + * 'connected' => bool, + * 'authenticated' => bool, + * 'error' => 'error message if failed' + * ] + * ], + * 'errors' => ['Error 1', 'Error 2'], // List of errors encountered + * ] + * ] + */ + public function serviceTest(ServiceBaseInterface $service, array $options = []): array; + +} diff --git a/shared/lib/Mail/Service/IServiceIdentity.php b/shared/lib/Mail/Service/IServiceIdentity.php deleted file mode 100644 index 1fd951b..0000000 --- a/shared/lib/Mail/Service/IServiceIdentity.php +++ /dev/null @@ -1,36 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -use JsonSerializable; - -/** - * Mail Service Identity Interface - * - * Base interface for authentication credentials used by mail services. - * - * @since 2025.05.01 - */ -interface IServiceIdentity extends JsonSerializable { - - public const TYPE_BASIC = 'basic'; - public const TYPE_OAUTH = 'oauth'; - public const TYPE_APIKEY = 'apikey'; - - /** - * Gets the identity/authentication type - * - * @since 2025.05.01 - * - * @return string One of: 'basic', 'oauth', 'apikey' - */ - public function getType(): string; - -} diff --git a/shared/lib/Mail/Service/IServiceIdentityApiKey.php b/shared/lib/Mail/Service/IServiceIdentityApiKey.php deleted file mode 100644 index 9d098f6..0000000 --- a/shared/lib/Mail/Service/IServiceIdentityApiKey.php +++ /dev/null @@ -1,39 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -/** - * Mail Service API Key Identity Interface - * - * API key authentication for transactional mail services (SendGrid, Mailgun, etc.) - * - * @since 2025.05.01 - */ -interface IServiceIdentityApiKey extends IServiceIdentity { - - /** - * Gets the API key - * - * @since 2025.05.01 - * - * @return string - */ - public function getApiKey(): string; - - /** - * Gets the optional API key identifier/name - * - * @since 2025.05.01 - * - * @return string|null - */ - public function getApiKeyId(): ?string; - -} diff --git a/shared/lib/Mail/Service/IServiceIdentityBasic.php b/shared/lib/Mail/Service/IServiceIdentityBasic.php deleted file mode 100644 index bd55412..0000000 --- a/shared/lib/Mail/Service/IServiceIdentityBasic.php +++ /dev/null @@ -1,39 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -/** - * Mail Service Basic Authentication Identity Interface - * - * Username/password authentication for traditional mail services. - * - * @since 2025.05.01 - */ -interface IServiceIdentityBasic extends IServiceIdentity { - - /** - * Gets the username/login identifier - * - * @since 2025.05.01 - * - * @return string - */ - public function getUsername(): string; - - /** - * Gets the password/secret - * - * @since 2025.05.01 - * - * @return string - */ - public function getPassword(): string; - -} diff --git a/shared/lib/Mail/Service/IServiceIdentityOAuth.php b/shared/lib/Mail/Service/IServiceIdentityOAuth.php deleted file mode 100644 index cf090c6..0000000 --- a/shared/lib/Mail/Service/IServiceIdentityOAuth.php +++ /dev/null @@ -1,68 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -use DateTimeImmutable; - -/** - * Mail Service OAuth Identity Interface - * - * OAuth2 token-based authentication for modern mail APIs. - * - * @since 2025.05.01 - */ -interface IServiceIdentityOAuth extends IServiceIdentity { - - /** - * Gets the OAuth access token - * - * @since 2025.05.01 - * - * @return string - */ - public function getAccessToken(): string; - - /** - * Gets the OAuth refresh token - * - * @since 2025.05.01 - * - * @return string|null - */ - public function getRefreshToken(): ?string; - - /** - * Gets the token expiration time - * - * @since 2025.05.01 - * - * @return DateTimeImmutable|null - */ - public function getExpiresAt(): ?DateTimeImmutable; - - /** - * Gets the granted OAuth scopes - * - * @since 2025.05.01 - * - * @return array - */ - public function getScopes(): array; - - /** - * Checks if the access token has expired - * - * @since 2025.05.01 - * - * @return bool - */ - public function isExpired(): bool; - -} diff --git a/shared/lib/Mail/Service/IServiceLocation.php b/shared/lib/Mail/Service/IServiceLocation.php deleted file mode 100644 index d3b04fb..0000000 --- a/shared/lib/Mail/Service/IServiceLocation.php +++ /dev/null @@ -1,105 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -use JsonSerializable; - -/** - * Mail Service Location Interface - * - * Unified interface supporting both URI-based (API services) and socket-based - * (traditional IMAP/SMTP) connection configurations. - * - * @since 2025.05.01 - */ -interface IServiceLocation extends JsonSerializable { - - public const TYPE_URI = 'uri'; - public const TYPE_SOCKET_SINGLE = 'socket-single'; - public const TYPE_SOCKET_SPLIT = 'socket-split'; - - public const SECURITY_NONE = 'none'; - public const SECURITY_SSL = 'ssl'; - public const SECURITY_TLS = 'tls'; - public const SECURITY_STARTTLS = 'starttls'; - - /** - * Gets the location type - * - * @since 2025.05.01 - * - * @return string One of: 'uri', 'socket-single', 'socket-split' - */ - public function getType(): string; - - /** - * Gets the URI for API-based services (JMAP, EWS, Graph API, HTTP relay) - * - * @since 2025.05.01 - * - * @return string|null URI or null if not URI-based - */ - public function getUri(): ?string; - - /** - * Gets the inbound/primary host for socket-based services - * - * @since 2025.05.01 - * - * @return string|null Hostname or null if URI-based - */ - public function getInboundHost(): ?string; - - /** - * Gets the inbound/primary port for socket-based services - * - * @since 2025.05.01 - * - * @return int|null Port number or null if URI-based - */ - public function getInboundPort(): ?int; - - /** - * Gets the inbound/primary security mode - * - * @since 2025.05.01 - * - * @return string|null One of: 'none', 'ssl', 'tls', 'starttls' - */ - public function getInboundSecurity(): ?string; - - /** - * Gets the outbound host for split-socket services (e.g., SMTP separate from IMAP) - * - * @since 2025.05.01 - * - * @return string|null Hostname or null if not split-socket - */ - public function getOutboundHost(): ?string; - - /** - * Gets the outbound port for split-socket services - * - * @since 2025.05.01 - * - * @return int|null Port number or null if not split-socket - */ - public function getOutboundPort(): ?int; - - /** - * Gets the outbound security mode for split-socket services - * - * @since 2025.05.01 - * - * @return string|null One of: 'none', 'ssl', 'tls', 'starttls' - */ - public function getOutboundSecurity(): ?string; - -} diff --git a/shared/lib/Mail/Service/IServiceBase.php b/shared/lib/Mail/Service/ServiceBaseInterface.php similarity index 72% rename from shared/lib/Mail/Service/IServiceBase.php rename to shared/lib/Mail/Service/ServiceBaseInterface.php index bfc427b..e833daa 100644 --- a/shared/lib/Mail/Service/IServiceBase.php +++ b/shared/lib/Mail/Service/ServiceBaseInterface.php @@ -9,11 +9,11 @@ declare(strict_types=1); namespace KTXF\Mail\Service; -use JsonSerializable; use KTXF\Mail\Collection\ICollectionBase; use KTXF\Mail\Entity\IAddress; use KTXF\Mail\Entity\IMessageBase; use KTXF\Resource\Filter\IFilter; +use KTXF\Resource\Provider\ResourceServiceBaseInterface; use KTXF\Resource\Range\IRange; use KTXF\Resource\Range\RangeType; use KTXF\Resource\Sort\ISort; @@ -26,7 +26,7 @@ use KTXF\Resource\Sort\ISort; * * @since 2025.05.01 */ -interface IServiceBase extends JsonSerializable { +interface ServiceBaseInterface extends ResourceServiceBaseInterface { // Collection capabilities public const CAPABILITY_COLLECTION_LIST = 'CollectionList'; @@ -43,7 +43,6 @@ interface IServiceBase extends JsonSerializable { public const CAPABILITY_MESSAGE_DELTA = 'MessageDelta'; public const CAPABILITY_MESSAGE_EXTANT = 'MessageExtant'; public const CAPABILITY_MESSAGE_FETCH = 'MessageFetch'; - public const CAPABILITY_MESSAGE_SEARCH = 'MessageSearch'; // Filter capabilities public const CAPABILITY_FILTER_ID = 'FilterId'; @@ -62,91 +61,9 @@ interface IServiceBase extends JsonSerializable { public const CAPABILITY_SORT_SIZE = 'SortSize'; public const JSON_TYPE = 'mail.service'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_PROVIDER = 'provider'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_SCOPE = 'scope'; - public const JSON_PROPERTY_OWNER = 'owner'; - public const JSON_PROPERTY_ENABLED = 'enabled'; - public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; public const JSON_PROPERTY_PRIMARY_ADDRESS = 'primaryAddress'; public const JSON_PROPERTY_SECONDARY_ADDRESSES = 'secondaryAddresses'; - /** - * Confirms if a specific capability is supported - * - * @since 2025.05.01 - * - * @param string $value Required capability e.g. 'Send' - * - * @return bool - */ - public function capable(string $value): bool; - - /** - * Lists all supported capabilities - * - * @since 2025.05.01 - * - * @return array - */ - public function capabilities(): array; - - /** - * Gets the unique identifier of the provider this service belongs to - * - * @since 2025.05.01 - * - * @return string - */ - public function in(): string; - - /** - * Gets the unique identifier for this service - * - * @since 2025.05.01 - * - * @return string|int - */ - public function id(): string|int; - - /** - * Gets the localized human-friendly name of this service - * - * @since 2025.05.01 - * - * @return string - */ - public function getLabel(): string; - - /** - * Gets the scope of this service (System or User) - * - * @since 2025.05.01 - * - * @return ServiceScope - */ - public function getScope(): ServiceScope; - - /** - * Gets the owner user ID for User-scoped services - * - * @since 2025.05.01 - * - * @return string|null User ID or null for System scope - */ - public function getOwner(): ?string; - - /** - * Gets whether this service is enabled - * - * @since 2025.05.01 - * - * @return bool - */ - public function getEnabled(): bool; - /** * Gets the primary mailing address for this service * @@ -309,19 +226,4 @@ interface IServiceBase extends JsonSerializable { */ public function messageFetch(string|int $collection, string|int ...$identifiers): array; - /** - * Searches messages across collections - * - * @since 2025.05.01 - * - * @param string $query Search query (syntax depends on protocol) - * @param array|null $collections Collection IDs to search (null = all) - * @param IFilter|null $filter Additional filter criteria - * @param ISort|null $sort Optional sort order - * @param IRange|null $range Optional pagination - * - * @return array Matching messages - */ - public function messageSearch(string $query, ?array $collections = null, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null): array; - } diff --git a/shared/lib/Mail/Service/IServiceCollectionMutable.php b/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php similarity index 97% rename from shared/lib/Mail/Service/IServiceCollectionMutable.php rename to shared/lib/Mail/Service/ServiceCollectionMutableInterface.php index 81cba39..7736af6 100644 --- a/shared/lib/Mail/Service/IServiceCollectionMutable.php +++ b/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php @@ -20,7 +20,7 @@ use KTXF\Mail\Collection\ICollectionMutable; * * @since 2025.05.01 */ -interface IServiceCollectionMutable extends IServiceBase { +interface ServiceCollectionMutableInterface extends ServiceBaseInterface { public const CAPABILITY_COLLECTION_CREATE = 'CollectionCreate'; public const CAPABILITY_COLLECTION_MODIFY = 'CollectionModify'; diff --git a/shared/lib/Mail/Service/ServiceIdentityApiKey.php b/shared/lib/Mail/Service/ServiceIdentityApiKey.php deleted file mode 100644 index 970ba23..0000000 --- a/shared/lib/Mail/Service/ServiceIdentityApiKey.php +++ /dev/null @@ -1,78 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -/** - * Mail Service API Key Identity Implementation - * - * API key authentication for transactional mail services. - * - * @since 2025.05.01 - */ -class ServiceIdentityApiKey implements IServiceIdentityApiKey { - - /** - * @param string $apiKey API key - * @param string|null $apiKeyId Optional API key identifier - */ - public function __construct( - private string $apiKey, - private ?string $apiKeyId = null, - ) {} - - /** - * Creates from array data - * - * @since 2025.05.01 - * - * @param array $data - * - * @return self - */ - public static function fromArray(array $data): self { - return new self( - $data['apiKey'] ?? '', - $data['apiKeyId'] ?? null, - ); - } - - /** - * @inheritDoc - */ - public function getType(): string { - return self::TYPE_APIKEY; - } - - /** - * @inheritDoc - */ - public function getApiKey(): string { - return $this->apiKey; - } - - /** - * @inheritDoc - */ - public function getApiKeyId(): ?string { - return $this->apiKeyId; - } - - /** - * @inheritDoc - */ - public function jsonSerialize(): array { - return array_filter([ - 'type' => self::TYPE_APIKEY, - 'apiKeyId' => $this->apiKeyId, - // API key intentionally omitted from serialization for security - ], fn($v) => $v !== null); - } - -} diff --git a/shared/lib/Mail/Service/ServiceIdentityBasic.php b/shared/lib/Mail/Service/ServiceIdentityBasic.php deleted file mode 100644 index a301955..0000000 --- a/shared/lib/Mail/Service/ServiceIdentityBasic.php +++ /dev/null @@ -1,78 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -/** - * Mail Service Basic Identity Implementation - * - * Username/password authentication credentials. - * - * @since 2025.05.01 - */ -class ServiceIdentityBasic implements IServiceIdentityBasic { - - /** - * @param string $username Login username - * @param string $password Login password - */ - public function __construct( - private string $username, - private string $password, - ) {} - - /** - * Creates from array data - * - * @since 2025.05.01 - * - * @param array $data - * - * @return self - */ - public static function fromArray(array $data): self { - return new self( - $data['username'] ?? '', - $data['password'] ?? '', - ); - } - - /** - * @inheritDoc - */ - public function getType(): string { - return self::TYPE_BASIC; - } - - /** - * @inheritDoc - */ - public function getUsername(): string { - return $this->username; - } - - /** - * @inheritDoc - */ - public function getPassword(): string { - return $this->password; - } - - /** - * @inheritDoc - */ - public function jsonSerialize(): array { - return [ - 'type' => self::TYPE_BASIC, - 'username' => $this->username, - // Password intentionally omitted from serialization for security - ]; - } - -} diff --git a/shared/lib/Mail/Service/ServiceLocation.php b/shared/lib/Mail/Service/ServiceLocation.php deleted file mode 100644 index 8d40791..0000000 --- a/shared/lib/Mail/Service/ServiceLocation.php +++ /dev/null @@ -1,211 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -/** - * Mail Service Location Implementation - * - * Unified implementation supporting URI-based and socket-based connections. - * - * @since 2025.05.01 - */ -class ServiceLocation implements IServiceLocation { - - /** - * @param string $type Location type (uri, socket-single, socket-split) - * @param string|null $uri URI for API-based services - * @param string|null $inboundHost Inbound/primary host - * @param int|null $inboundPort Inbound/primary port - * @param string|null $inboundSecurity Inbound security (none, ssl, tls, starttls) - * @param string|null $outboundHost Outbound host (for split-socket) - * @param int|null $outboundPort Outbound port (for split-socket) - * @param string|null $outboundSecurity Outbound security (for split-socket) - */ - public function __construct( - private string $type, - private ?string $uri = null, - private ?string $inboundHost = null, - private ?int $inboundPort = null, - private ?string $inboundSecurity = null, - private ?string $outboundHost = null, - private ?int $outboundPort = null, - private ?string $outboundSecurity = null, - ) {} - - /** - * Creates a URI-based location (for API services) - * - * @since 2025.05.01 - * - * @param string $uri - * - * @return self - */ - public static function uri(string $uri): self { - return new self(self::TYPE_URI, $uri); - } - - /** - * Creates a single-socket location (e.g., SMTP only) - * - * @since 2025.05.01 - * - * @param string $host - * @param int $port - * @param string $security - * - * @return self - */ - public static function socket(string $host, int $port, string $security = self::SECURITY_TLS): self { - return new self( - self::TYPE_SOCKET_SINGLE, - null, - $host, - $port, - $security - ); - } - - /** - * Creates a split-socket location (IMAP + SMTP) - * - * @since 2025.05.01 - * - * @param string $inboundHost IMAP host - * @param int $inboundPort IMAP port - * @param string $inboundSecurity IMAP security - * @param string $outboundHost SMTP host - * @param int $outboundPort SMTP port - * @param string $outboundSecurity SMTP security - * - * @return self - */ - public static function splitSocket( - string $inboundHost, - int $inboundPort, - string $inboundSecurity, - string $outboundHost, - int $outboundPort, - string $outboundSecurity - ): self { - return new self( - self::TYPE_SOCKET_SPLIT, - null, - $inboundHost, - $inboundPort, - $inboundSecurity, - $outboundHost, - $outboundPort, - $outboundSecurity - ); - } - - /** - * Creates from array data - * - * @since 2025.05.01 - * - * @param array $data - * - * @return self - */ - public static function fromArray(array $data): self { - return new self( - $data['type'] ?? self::TYPE_SOCKET_SINGLE, - $data['uri'] ?? null, - $data['inboundHost'] ?? $data['host'] ?? null, - $data['inboundPort'] ?? $data['port'] ?? null, - $data['inboundSecurity'] ?? $data['security'] ?? null, - $data['outboundHost'] ?? null, - $data['outboundPort'] ?? null, - $data['outboundSecurity'] ?? null, - ); - } - - /** - * @inheritDoc - */ - public function getType(): string { - return $this->type; - } - - /** - * @inheritDoc - */ - public function getUri(): ?string { - return $this->uri; - } - - /** - * @inheritDoc - */ - public function getInboundHost(): ?string { - return $this->inboundHost; - } - - /** - * @inheritDoc - */ - public function getInboundPort(): ?int { - return $this->inboundPort; - } - - /** - * @inheritDoc - */ - public function getInboundSecurity(): ?string { - return $this->inboundSecurity; - } - - /** - * @inheritDoc - */ - public function getOutboundHost(): ?string { - return $this->outboundHost ?? $this->inboundHost; - } - - /** - * @inheritDoc - */ - public function getOutboundPort(): ?int { - return $this->outboundPort ?? $this->inboundPort; - } - - /** - * @inheritDoc - */ - public function getOutboundSecurity(): ?string { - return $this->outboundSecurity ?? $this->inboundSecurity; - } - - /** - * @inheritDoc - */ - public function jsonSerialize(): array { - $data = ['type' => $this->type]; - - if ($this->type === self::TYPE_URI) { - $data['uri'] = $this->uri; - } else { - $data['inboundHost'] = $this->inboundHost; - $data['inboundPort'] = $this->inboundPort; - $data['inboundSecurity'] = $this->inboundSecurity; - - if ($this->type === self::TYPE_SOCKET_SPLIT) { - $data['outboundHost'] = $this->outboundHost; - $data['outboundPort'] = $this->outboundPort; - $data['outboundSecurity'] = $this->outboundSecurity; - } - } - - return array_filter($data, fn($v) => $v !== null); - } - -} diff --git a/shared/lib/Mail/Service/IServiceMessageMutable.php b/shared/lib/Mail/Service/ServiceMessageMutableInterface.php similarity index 98% rename from shared/lib/Mail/Service/IServiceMessageMutable.php rename to shared/lib/Mail/Service/ServiceMessageMutableInterface.php index 87f6bee..59775a7 100644 --- a/shared/lib/Mail/Service/IServiceMessageMutable.php +++ b/shared/lib/Mail/Service/ServiceMessageMutableInterface.php @@ -20,7 +20,7 @@ use KTXF\Mail\Entity\IMessageMutable; * * @since 2025.05.01 */ -interface IServiceMessageMutable extends IServiceBase { +interface ServiceMessageMutableInterface extends ServiceBaseInterface { public const CAPABILITY_MESSAGE_CREATE = 'MessageCreate'; public const CAPABILITY_MESSAGE_MODIFY = 'MessageModify'; diff --git a/shared/lib/Mail/Service/IServiceSend.php b/shared/lib/Mail/Service/ServiceMessageSendInterface.php similarity index 93% rename from shared/lib/Mail/Service/IServiceSend.php rename to shared/lib/Mail/Service/ServiceMessageSendInterface.php index 940c0bc..4e8f3f4 100644 --- a/shared/lib/Mail/Service/IServiceSend.php +++ b/shared/lib/Mail/Service/ServiceMessageSendInterface.php @@ -20,7 +20,7 @@ use KTXF\Mail\Exception\SendException; * * @since 2025.05.01 */ -interface IServiceSend extends IServiceBase { +interface ServiceMessageSendInterface extends ServiceBaseInterface { public const CAPABILITY_SEND = 'Send'; diff --git a/shared/lib/Mail/Service/ServiceMutableInterface.php b/shared/lib/Mail/Service/ServiceMutableInterface.php new file mode 100644 index 0000000..8245d3e --- /dev/null +++ b/shared/lib/Mail/Service/ServiceMutableInterface.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Service; + +use KTXF\Mail\Entity\IAddress; + +/** + * Mail Service Mutable Interface + * + * Extends base service interface with setter methods for mutable properties. + * Used for service configuration and updates. + * + * @since 2025.05.01 + */ +interface ServiceMutableInterface extends ServiceBaseInterface { + + /** + * Sets the primary mailing address for this service + * + * @since 2025.05.01 + * + * @param IAddress $value Primary email address + * + * @return self + */ + public function setPrimaryAddress(IAddress $value): self; + + /** + * Sets the secondary mailing addresses (aliases) for this service + * + * @since 2025.05.01 + * + * @param array $value Array of secondary addresses + * + * @return self + */ + public function setSecondaryAddresses(array $value): self; + +} diff --git a/shared/lib/Mail/Service/ServiceScope.php b/shared/lib/Mail/Service/ServiceScope.php deleted file mode 100644 index bfdbff3..0000000 --- a/shared/lib/Mail/Service/ServiceScope.php +++ /dev/null @@ -1,37 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\Mail\Service; - -use JsonSerializable; - -/** - * Defines the scope/context of a mail service - * - * @since 2025.05.01 - */ -enum ServiceScope: string implements JsonSerializable { - - /** - * System-level service for tenant-wide communications - * (e.g., notifications@, reports@, noreply@) - */ - case System = 'system'; - - /** - * User-level service for personal mail accounts - * (e.g., user's own IMAP/SMTP accounts) - */ - case User = 'user'; - - public function jsonSerialize(): string { - return $this->value; - } - -} diff --git a/shared/lib/Resource/Provider/ResourceProviderBaseInterface.php b/shared/lib/Resource/Provider/ResourceProviderBaseInterface.php new file mode 100644 index 0000000..25950f0 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceProviderBaseInterface.php @@ -0,0 +1,79 @@ + + */ + public function capabilities(): array; + + /** + * Retrieve collection of services for a specific user + * + * @since 2025.11.01 + * + * @param string $tenantId tenant identifier + * @param string $userId user identifier + * @param array $filter filter criteria + * + * @return array collection of service objects + */ + public function serviceList(string $tenantId, string $userId, array $filter): array; + + /** + * Determine if any services are configured for a specific user + * + * @since 2025.11.01 + * + * @param string $tenantId tenant identifier + * @param string $userId user identifier + * @param int|string ...$identifiers variadic collection of service identifiers + * + * @return array collection of service identifiers with boolean values indicating if the service is available + */ + public function serviceExtant(string $tenantId, string $userId, int|string ...$identifiers): array; + + /** + * Retrieve a service with a specific identifier + * + * @since 2025.11.01 + * + * @param string $tenantId tenant identifier + * @param string $userId user identifier + * @param string|int $identifier service identifier + * + * @return ResourceServiceBaseInterface|null returns service object or null if non found + */ + public function serviceFetch(string $tenantId, string $userId, string|int $identifier): ?ResourceServiceBaseInterface; + +} diff --git a/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php b/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php new file mode 100644 index 0000000..45d1c3e --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php @@ -0,0 +1,49 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +use KTXF\Json\JsonDeserializable; + +interface ResourceProviderServiceMutateInterface extends ResourceProviderBaseInterface, JsonDeserializable { + + public const CAPABILITY_SERVICE_FRESH = 'ServiceFresh'; + public const CAPABILITY_SERVICE_CREATE = 'ServiceCreate'; + public const CAPABILITY_SERVICE_UPDATE = 'ServiceUpdate'; + public const CAPABILITY_SERVICE_DESTROY = 'ServiceDestroy'; + + /** + * construct and new blank service instance + * + * @since 2025.05.01 + */ + public function serviceFresh(string $tenantId, ?string $userId): ResourceServiceMutateInterface; + + /** + * create a service configuration for a specific user + * + * @since 2025.05.01 + */ + public function serviceCreate(string $tenantId, ?string $userId, ResourceServiceMutateInterface $service): string; + + /** + * modify a service configuration for a specific user + * + * @since 2025.05.01 + */ + public function serviceModify(string $tenantId, ?string $userId, ResourceServiceMutateInterface $service): string; + + /** + * delete a service configuration for a specific user + * + * @since 2025.05.01 + */ + public function serviceDestroy(string $tenantId, ?string $userId, ResourceServiceMutateInterface $service): bool; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceBaseInterface.php b/shared/lib/Resource/Provider/ResourceServiceBaseInterface.php new file mode 100644 index 0000000..e097819 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceBaseInterface.php @@ -0,0 +1,86 @@ + + */ + public function capabilities(): array; + + /** + * Unique identifier of the provider this service belongs to + * + * @since 2025.11.01 + */ + public function in(): string; + + /** + * Unique arbitrary text string identifying this service (e.g. 1 or service1 or anything else) + * + * @since 2025.11.01 + */ + public function id(): string|int; + + /** + * Gets the localized human friendly name of this service (e.g. ACME Company File Service) + * + * @since 2025.11.01 + */ + public function getLabel(): string; + + /** + * Gets the active status of this service + * + * @since 2025.11.01 + */ + public function getEnabled(): bool; + + /** + * Gets the location information of this service + * + * @since 2025.05.01 + * + * @return ResourceServiceLocationInterface + */ + public function getLocation(): ResourceServiceLocationInterface; + + /** + * Gets the identity information of this service + * + * @since 2025.05.01 + * + * @return ResourceServiceIdentityInterface + */ + public function getIdentity(): ResourceServiceIdentityInterface; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php b/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php new file mode 100644 index 0000000..c8a29ae --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php @@ -0,0 +1,44 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Configurable Interface + * + * Extends base service interface with setter methods for mutable properties. + * Used for service configuration and updates. + * + * @since 2025.05.01 + */ +interface ResourceServiceConfigureInterface extends ResourceServiceMutateInterface { + + /** + * Sets the location/configuration of this service + * + * @since 2025.05.01 + * + * @param ResourceServiceLocationInterface $value Service location/configuration + * + * @return self + */ + public function setLocation(ResourceServiceLocationInterface $value): self; + + /** + * Sets the identity used for this service + * + * @since 2025.05.01 + * + * @param ResourceServiceIdentityInterface $value Service identity + * + * @return self + */ + public function setIdentity(ResourceServiceIdentityInterface $value): self; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceIdentityBasic.php b/shared/lib/Resource/Provider/ResourceServiceIdentityBasic.php new file mode 100644 index 0000000..671a137 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceIdentityBasic.php @@ -0,0 +1,61 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Identity Basic + * + * Basic authentication (username/password) credentials for resource services. + * + * @since 2025.05.01 + */ +interface ResourceServiceIdentityBasic extends ResourceServiceIdentityInterface { + + /** + * Gets the identity/username + * + * @since 2025.05.01 + * + * @return string + */ + public function getIdentity(): string; + + /** + * Sets the identity/username + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setIdentity(string $value): void; + + /** + * Gets the secret/password + * + * @since 2025.05.01 + * + * @return string + */ + public function getSecret(): string; + + /** + * Sets the secret/password + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setSecret(string $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceIdentityBearer.php b/shared/lib/Resource/Provider/ResourceServiceIdentityBearer.php new file mode 100644 index 0000000..55dad81 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceIdentityBearer.php @@ -0,0 +1,41 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Identity Bearer + * + * Bearer token authentication credentials for resource services. + * + * @since 2025.05.01 + */ +interface ResourceServiceIdentityBearer extends ResourceServiceIdentityInterface { + + /** + * Gets the bearer token + * + * @since 2025.05.01 + * + * @return string + */ + public function getToken(): string; + + /** + * Sets the bearer token + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setToken(string $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceIdentityInterface.php b/shared/lib/Resource/Provider/ResourceServiceIdentityInterface.php new file mode 100644 index 0000000..63c20ad --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceIdentityInterface.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +use KTXF\Json\JsonSerializable; + +/** + * Resource Service Identity Interface + * + * Base interface for authentication credentials used by resource services. + * + * @since 2025.05.01 + */ +interface ResourceServiceIdentityInterface extends JsonSerializable { + + public const TYPE_NONE = 'NA'; + public const TYPE_BASIC = 'BA'; + public const TYPE_BEARER = 'BR'; + public const TYPE_OAUTH = 'OA'; + + /** + * Gets the identity/authentication type + * + * @since 2025.05.01 + * + * @return string One of: TYPE_NONE, TYPE_BASIC, TYPE_BEARER, TYPE_OAUTH + */ + public function type(): string; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceIdentityOAuth.php b/shared/lib/Resource/Provider/ResourceServiceIdentityOAuth.php new file mode 100644 index 0000000..84f13ae --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceIdentityOAuth.php @@ -0,0 +1,121 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Identity OAuth + * + * OAuth authentication credentials for resource services, including token management. + * + * @since 2025.05.01 + */ +interface ResourceServiceIdentityOAuth extends ResourceServiceIdentityInterface { + + /** + * Gets the access token + * + * @since 2025.05.01 + * + * @return string + */ + public function getAccessToken(): string; + + /** + * Sets the access token + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setAccessToken(string $value): void; + + /** + * Gets the access token scope + * + * @since 2025.05.01 + * + * @return array + */ + public function getAccessScope(): array; + + /** + * Sets the access token scope + * + * @since 2025.05.01 + * + * @param array $value + * + * @return void + */ + public function setAccessScope(array $value): void; + + /** + * Gets the access token expiry timestamp + * + * @since 2025.05.01 + * + * @return int Unix timestamp + */ + public function getAccessExpiry(): int; + + /** + * Sets the access token expiry timestamp + * + * @since 2025.05.01 + * + * @param int $value Unix timestamp + * + * @return void + */ + public function setAccessExpiry(int $value): void; + + /** + * Gets the refresh token + * + * @since 2025.05.01 + * + * @return string + */ + public function getRefreshToken(): string; + + /** + * Sets the refresh token + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setRefreshToken(string $value): void; + + /** + * Gets the token refresh location/endpoint + * + * @since 2025.05.01 + * + * @return string + */ + public function getRefreshLocation(): string; + + /** + * Sets the token refresh location/endpoint + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setRefreshLocation(string $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceLocationFile.php b/shared/lib/Resource/Provider/ResourceServiceLocationFile.php new file mode 100644 index 0000000..9f2fd9e --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceLocationFile.php @@ -0,0 +1,51 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Location File + * + * File-based service location for services using local or network file paths + * (e.g., maildir, mbox, local storage). + * + * @since 2025.05.01 + */ +interface ResourceServiceLocationFile extends ResourceServiceLocationInterface { + + /** + * Gets the complete file location path + * + * @since 2025.05.01 + * + * @return string File path (e.g., "/var/mail/user" or "\\server\share\mail") + */ + public function location(): string; + + /** + * Gets the file location path + * + * @since 2025.05.01 + * + * @return string File path + */ + public function getLocation(): string; + + /** + * Sets the file location path + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setLocation(string $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceLocationInterface.php b/shared/lib/Resource/Provider/ResourceServiceLocationInterface.php new file mode 100644 index 0000000..c3565d8 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceLocationInterface.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +use JsonSerializable; + +/** + * Resource Service Location Interface + * + * Unified interface supporting both URI-based (API services) and socket-based + * (traditional IMAP/SMTP) connection configurations. + * + * @since 2025.05.01 + */ +interface ResourceServiceLocationInterface extends JsonSerializable { + + public const TYPE_URI = 'URI'; + public const TYPE_SOCKET_SOLE = 'SOCKET_SOLE'; + public const TYPE_SOCKET_SPLIT = 'SOCKET_SPLIT'; + public const TYPE_FILE = 'FILE'; + + /** + * Gets the service location type + * + * @since 2025.05.01 + * + * @return string One of: TYPE_URI, TYPE_SOCKET_SOLE, TYPE_SOCKET_SPLIT, TYPE_FILE + */ + public function type(): string; +} diff --git a/shared/lib/Resource/Provider/ResourceServiceLocationSocketSole.php b/shared/lib/Resource/Provider/ResourceServiceLocationSocketSole.php new file mode 100644 index 0000000..08861a8 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceLocationSocketSole.php @@ -0,0 +1,131 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Location Socket Sole + * + * Single socket-based service location for services using a single host/port combination + * (e.g., JMAP, unified mail servers). + * + * @since 2025.05.01 + */ +interface ResourceServiceLocationSocketSole extends ResourceServiceLocationInterface { + + /** + * Gets the complete location string + * + * @since 2025.05.01 + * + * @return string Location (e.g., "mail.example.com:993") + */ + public function location(): string; + + /** + * Gets the host + * + * @since 2025.05.01 + * + * @return string Host (e.g., "mail.example.com") + */ + public function getHost(): string; + + /** + * Sets the host + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setHost(string $value): void; + + /** + * Gets the port + * + * @since 2025.05.01 + * + * @return int Port number + */ + public function getPort(): int; + + /** + * Sets the port + * + * @since 2025.05.01 + * + * @param int $value + * + * @return void + */ + public function setPort(int $value): void; + + /** + * Gets the encryption/security mode + * + * @since 2025.12.01 + * + * @return string One of: 'none', 'ssl', 'tls', 'starttls' + */ + public function getEncryption(): string; + + /** + * Sets the encryption/security mode + * + * @since 2025.12.01 + * + * @param string $value One of: 'none', 'ssl', 'tls', 'starttls' + * + * @return void + */ + public function setEncryption(string $value): void; + + /** + * Gets whether to verify SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @return bool + */ + public function getVerifyPeer(): bool; + + /** + * Sets whether to verify SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setVerifyPeer(bool $value): void; + + /** + * Gets whether to verify SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @return bool + */ + public function getVerifyHost(): bool; + + /** + * Sets whether to verify SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setVerifyHost(bool $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceLocationSocketSplit.php b/shared/lib/Resource/Provider/ResourceServiceLocationSocketSplit.php new file mode 100644 index 0000000..1b94cc8 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceLocationSocketSplit.php @@ -0,0 +1,240 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Location Socket Split + * + * Split socket-based service location for services using separate inbound/outbound servers + * (e.g., traditional IMAP/SMTP configurations). + * + * @since 2025.05.01 + */ +interface ResourceServiceLocationSocketSplit extends ResourceServiceLocationInterface { + + /** + * Gets the complete inbound location string + * + * @since 2025.05.01 + * + * @return string Inbound location (e.g., "imap.example.com:993") + */ + public function locationInbound(): string; + + /** + * Gets the complete outbound location string + * + * @since 2025.05.01 + * + * @return string Outbound location (e.g., "smtp.example.com:465") + */ + public function locationOutbound(): string; + + /** + * Gets the inbound host + * + * @since 2025.05.01 + * + * @return string Inbound host (e.g., "imap.example.com") + */ + public function getInboundHost(): string; + + /** + * Sets the inbound host + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setInboundHost(string $value): void; + + /** + * Gets the outbound host + * + * @since 2025.05.01 + * + * @return string Outbound host (e.g., "smtp.example.com") + */ + public function getOutboundHost(): string; + + /** + * Sets the outbound host + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setOutboundHost(string $value): void; + + /** + * Gets the inbound port + * + * @since 2025.05.01 + * + * @return int Inbound port number + */ + public function getInboundPort(): int; + + /** + * Sets the inbound port + * + * @since 2025.05.01 + * + * @param int $value + * + * @return void + */ + public function setInboundPort(int $value): void; + + /** + * Gets the outbound port + * + * @since 2025.05.01 + * + * @return int Outbound port number + */ + public function getOutboundPort(): int; + + /** + * Sets the outbound port + * + * @since 2025.05.01 + * + * @param int $value + * + * @return void + */ + public function setOutboundPort(int $value): void; + + /** + * Gets the inbound encryption/security mode + * + * @since 2025.12.01 + * + * @return string One of: 'none', 'ssl', 'tls', 'starttls' + */ + public function getInboundEncryption(): string; + + /** + * Sets the inbound encryption/security mode + * + * @since 2025.12.01 + * + * @param string $value One of: 'none', 'ssl', 'tls', 'starttls' + * + * @return void + */ + public function setInboundEncryption(string $value): void; + + /** + * Gets the outbound encryption/security mode + * + * @since 2025.12.01 + * + * @return string One of: 'none', 'ssl', 'tls', 'starttls' + */ + public function getOutboundEncryption(): string; + + /** + * Sets the outbound encryption/security mode + * + * @since 2025.12.01 + * + * @param string $value One of: 'none', 'ssl', 'tls', 'starttls' + * + * @return void + */ + public function setOutboundEncryption(string $value): void; + + /** + * Gets whether to verify inbound SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @return bool + */ + public function getInboundVerifyPeer(): bool; + + /** + * Sets whether to verify inbound SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setInboundVerifyPeer(bool $value): void; + + /** + * Gets whether to verify inbound SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @return bool + */ + public function getInboundVerifyHost(): bool; + + /** + * Sets whether to verify inbound SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setInboundVerifyHost(bool $value): void; + + /** + * Gets whether to verify outbound SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @return bool + */ + public function getOutboundVerifyPeer(): bool; + + /** + * Sets whether to verify outbound SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setOutboundVerifyPeer(bool $value): void; + + /** + * Gets whether to verify outbound SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @return bool + */ + public function getOutboundVerifyHost(): bool; + + /** + * Sets whether to verify outbound SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setOutboundVerifyHost(bool $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceLocationUri.php b/shared/lib/Resource/Provider/ResourceServiceLocationUri.php new file mode 100644 index 0000000..e502ea3 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceLocationUri.php @@ -0,0 +1,150 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +/** + * Resource Service Location Uri + * + * URI-based service location for API and web services (e.g., https://api.example.com:443/v1/endpoint). + * + * @since 2025.05.01 + */ +interface ResourceServiceLocationUri extends ResourceServiceLocationInterface { + + /** + * Gets the complete location URI + * + * @since 2025.05.01 + * + * @return string Complete URI (e.g., "https://api.example.com:443/v1") + */ + public function location(): string; + + /** + * Gets the URI scheme + * + * @since 2025.05.01 + * + * @return string Scheme (e.g., "https", "http") + */ + public function getScheme(): string; + + /** + * Sets the URI scheme + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setScheme(string $value): void; + + /** + * Gets the host + * + * @since 2025.05.01 + * + * @return string Host (e.g., "api.example.com") + */ + public function getHost(): string; + + /** + * Sets the host + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setHost(string $value): void; + + /** + * Gets the port + * + * @since 2025.05.01 + * + * @return int Port number + */ + public function getPort(): int; + + /** + * Sets the port + * + * @since 2025.05.01 + * + * @param int $value + * + * @return void + */ + public function setPort(int $value): void; + + /** + * Gets the path + * + * @since 2025.05.01 + * + * @return string Path (e.g., "/v1/api") + */ + public function getPath(): string; + + /** + * Sets the path + * + * @since 2025.05.01 + * + * @param string $value + * + * @return void + */ + public function setPath(string $value): void; + + /** + * Gets whether to verify SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @return bool + */ + public function getVerifyPeer(): bool; + + /** + * Sets whether to verify SSL/TLS peer certificate + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setVerifyPeer(bool $value): void; + + /** + * Gets whether to verify SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @return bool + */ + public function getVerifyHost(): bool; + + /** + * Sets whether to verify SSL/TLS certificate host + * + * @since 2025.12.01 + * + * @param bool $value + * + * @return void + */ + public function setVerifyHost(bool $value): void; + +} diff --git a/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php b/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php new file mode 100644 index 0000000..8d585b1 --- /dev/null +++ b/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php @@ -0,0 +1,46 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Resource\Provider; + +use KTXF\Json\JsonDeserializable; + +/** + * Resource Service Configurable Interface + * + * Extends base service interface with setter methods for mutable properties. + * Used for service configuration and updates. + * + * @since 2025.05.01 + */ +interface ResourceServiceMutateInterface extends ResourceServiceBaseInterface, JsonDeserializable { + + /** + * Sets the localized human-friendly name of this service (e.g. ACME Company Mail Service) + * + * @since 2025.05.01 + * + * @param string $value Service label + * + * @return self + */ + public function setLabel(string $value): self; + + /** + * Sets the active status of this service + * + * @since 2025.05.01 + * + * @param bool $value True to enable, false to disable + * + * @return self + */ + public function setEnabled(bool $value): self; + +} diff --git a/shared/lib/Security/Crypto.php b/shared/lib/Security/Crypto.php index ff903ea..6b78ba7 100644 --- a/shared/lib/Security/Crypto.php +++ b/shared/lib/Security/Crypto.php @@ -137,7 +137,7 @@ class Crypto private function tenantSecret(): ?string { $config = $this->sessionTenant->configuration(); - return $config['security']['code'] ?? null; + return $config->security()->code(); } // =========================================================================