Skip to content

Extension points (interfaces + explicit @api markers + IDs)#

api, extension-points SOURCE: Interfaces

Interfaces#

// Structure of documents
└── src/
    └── Encryption/
        ├── EncryptorInterface.php
    └── KeyManagement/
        ├── KeyActivatorInterface.php
        ├── KeyGeneratorInterface.php
        ├── KeyPrunerInterface.php
        ├── KeyRotatorInterface.php
        ├── KeyUsageTrackerInterface.php
        ├── Observers/
           ├── KeyActivatedObserverInterface.php
           ├── KeyDeletedObserverInterface.php
        ├── Port/
           └── KeyRegistryInterface.php
           └── KeyUsageProviderInterface.php
           └── MutableKeyRegistryInterface.php
    └── KeyTransfer/
        ├── KeyTransferInterface.php
        ├── Port/
           └── KeyPackageCodecInterface.php
           └── KeyTransferPayloadHandlerInterface.php
    └── Sodium/
        └── SodiumKeyPairReadRepositoryInterface.php
        └── SodiumKeyPairWriteRepositoryInterface.php

Path: /src/Encryption/EncryptorInterface.php#

namespace Drupal\easy_encryption\Encryption;

/**
 * Defines an interface for encrypting and decrypting sensitive data.
 */
interface EncryptorInterface
{
    /**
     * Encrypts a value.
     *
     * @param string $value
     *   The plaintext value to encrypt.
     *
     * @return \Drupal\easy_encryption\Encryption\EncryptedValue
     *   The encrypted value with metadata.
     *
     * @throws \InvalidArgumentException
     *   If the value is empty.
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If encryption fails.
     */
    public function encrypt(
        #[\SensitiveParameter]
        string $value,
    ): EncryptedValue;


    /**
     * Decrypts a value.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptedValue $value
     *   The encrypted value to decrypt.
     *
     * @return string
     *   The decrypted plaintext.
     *
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If decryption fails.
     */
    public function decrypt(EncryptedValue $value): string;


    /**
     * Validates that encryption and decryption work correctly.
     *
     * Implementations may skip this test silently if the environment does not
     * support decryption (for example, when only a public key is available).
     *
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If the self-test fails.
     */
    public function selfTest(): void;
}

Path: /src/KeyManagement/KeyActivatorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for activating an encryption key.
 *
 * Activation sets which encryption key ID is considered active for new
 * encryption operations on the site.
 */
interface KeyActivatorInterface
{
    /**
     * Activates an existing encryption key by ID.
     *
     * Activation MUST be allowed when private key is missing, as long as a public
     * key exists (encrypt-only environments).
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   The encryption key identifier.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyActivatorException
     *   Thrown when activation fails.
     */
    public function activate(EncryptionKeyId $keyId): void;
}

Path: /src/KeyManagement/KeyGeneratorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for generating and activating encryption keys.
 *
 * This service returns key identifiers, not key material, to keep the
 * application layer decoupled from the underlying cryptographic library.
 */
interface KeyGeneratorInterface
{
    /**
     * Generates and persists an encryption key.
     *
     * If no ID is provided, the generator MUST create a new identifier.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $keyId
     *   (optional) The encryption key identifier to use.
     *
     * @return \Drupal\easy_encryption\Encryption\EncryptionKeyId
     *   The encryption key identifier that was generated.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyGeneratorException
     *   Thrown when the encryption key generation fails.
     */
    public function generate(?EncryptionKeyId $keyId = null): EncryptionKeyId;
}

Path: /src/KeyManagement/KeyPrunerInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Application service for pruning unused encryption keys.
 */
interface KeyPrunerInterface
{
    /**
     * Builds a non-mutating plan describing what would be pruned.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
     *   Thrown when the plan cannot be computed.
     */
    public function planPruning(): KeyPrunePlan;


    /**
     * Deletes unused encryption keys.
     *
     * This operation returns partial results: failures are reported in the result
     * object rather than aborting the whole run.
     *
     * @return \Drupal\easy_encryption\KeyManagement\KeyPruneResult
     *   The prune result.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
     *   Thrown when the prune operation cannot start
     *   (for example, planning fails).
     */
    public function pruneUnused(): KeyPruneResult;
}

Path: /src/KeyManagement/KeyRotatorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Application service for planning and performing encryption key rotation.
 */
interface KeyRotatorInterface
{
    /**
     * Builds a non-mutating plan describing what would change.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
     *   If the plan cannot be computed.
     */
    public function plan(bool $includeReencryptCounts = true): KeyRotationPlan;


    /**
     * Rotates the active encryption key and optionally re-encrypts credentials.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
     *   If rotation fails, or re-encryption fails and failOnReencryptErrors
     *   is TRUE.
     */
    public function rotate(KeyRotationOptions $options): KeyRotationResult;
}

Path: /src/KeyManagement/KeyUsageTrackerInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Public API for tracking encryption key usage across the entire system.
 */
interface KeyUsageTrackerInterface
{
    /**
     * Returns the aggregated mapping of all consumers and their encryption keys.
     *
     * @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   The 'result' is keyed by consumer ID.
     *   'cacheability' applies to the entire set.
     */
    public function getKeyUsageMapping(): array;
}

Path: /src/KeyManagement/Observers/KeyActivatedObserverInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Observers;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Contract for encryption key activation observers.
 */
interface KeyActivatedObserverInterface
{
    /**
     * Act when an encryption key gets activated.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $activeKeyId
     *   The ID of the activated encryption key.
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $previousKeyId
     *   The ID of the previously active key if there was any.
     */
    public function onKeyActivation(EncryptionKeyId $activeKeyId, ?EncryptionKeyId $previousKeyId): void;
}

Path: /src/KeyManagement/Observers/KeyDeletedObserverInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Observers;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Contract for encryption key deletion observers.
 */
interface KeyDeletedObserverInterface
{
    /**
     * Act when an encryption key gets deleted.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   The ID of the activated encryption key.
     */
    public function onKeyDeletion(EncryptionKeyId $keyId): void;
}

Path: /src/KeyManagement/Port/KeyRegistryInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Read-only registry of known encryption keys and the active key.
 */
interface KeyRegistryInterface
{
    /**
     * Lists encryption key IDs known to this site.
     *
     * @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId[], cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   Known key ids plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function listKnownKeyIds(): array;


    /**
     * Returns the active encryption key id, if any.
     *
     * @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId|null, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   Active key id plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function getActiveKeyId(): array;


    /**
     * Checks whether a key id is known to the registry.
     *
     * @return array{result: bool, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   TRUE if known plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function isKnown(EncryptionKeyId $key_id): array;
}

Path: /src/KeyManagement/Port/KeyUsageProviderInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

/**
 * Interface for reporters that identify encryption key dependencies.
 */
interface KeyUsageProviderInterface
{
    /**
     * Returns a mapping of consumers.
     *
     * @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   The 'result' is keyed by consumer ID. 'cacheability' applies to the
     *   entire set.
     */
    public function getKeyUsageMapping(): array;
}

Path: /src/KeyManagement/Port/MutableKeyRegistryInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Mutable registry of known encryption keys and the active key.
 */
interface MutableKeyRegistryInterface
{
    /**
     * Registers a key id as known.
     *
     * Implementations must be idempotent.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written.
     */
    public function register(EncryptionKeyId $key_id): void;


    /**
     * Unregisters a key id from the known list.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written.
     */
    public function unregister(EncryptionKeyId $key_id): void;


    /**
     * Sets the active encryption key id.
     *
     * Implementations should either:
     * - implicitly register the key id if missing, or
     * - throw unknownKey() if the key id is not registered.
     *
     * Pick one policy and keep it consistent. For export/import and for
     * predictable behavior, I recommend: throw if unknown.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written or the key is unknown.
     */
    public function setActive(EncryptionKeyId $key_id): void;
}

Path: /src/KeyTransfer/KeyTransferInterface.php#

namespace Drupal\easy_encryption\KeyTransfer;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for importing/exporting keys as portable packages.
 */
interface KeyTransferInterface
{
    /**
     * Exports a known key as a portable package string.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\KeyTransferException
     *   When export fails or cannot be performed.
     */
    public function exportKey(EncryptionKeyId $keyId): string;


    /**
     * Imports a portable package string & optionally activates the imported key.
     *
     * @return array{key_id: \Drupal\easy_encryption\Encryption\EncryptionKeyId, activated: bool}
     *   The imported key id and whether activation was requested/performed.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\KeyTransferException
     *   When import fails or the package is invalid/unsupported.
     */
    public function importKey(string $package, bool $activate = false): array;
}

Path: /src/KeyTransfer/Port/KeyPackageCodecInterface.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

/**
 * Encodes/decodes key transfer packages (envelope only).
 *
 * The codec is format-agnostic: algorithm-specific data is carried in the
 * payload structure and interpreted by payload handlers.
 */
interface KeyPackageCodecInterface
{
    /**
     * Encodes the package structure into a portable string.
     *
     * @param array<string,mixed> $data
     *   Package data, typically with keys like 'key_id' and 'payload'.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyPackageCodecException
     *   When the package cannot be encoded.
     */
    public function encode(array $data): string;


    /**
     * Decodes a portable string into the package structure.
     *
     * @return array<string,mixed>
     *   Package data.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyPackageCodecException
     *   When the package cannot be decoded.
     */
    public function decode(string $text): array;
}

Path: /src/KeyTransfer/Port/KeyTransferPayloadHandlerInterface.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Port for handling algorithm-specific key transfer payloads.
 *
 * Implementations are discovered via tagged services.
 *
 * @template TPayload of array
 */
interface KeyTransferPayloadHandlerInterface
{
    /**
     * Returns TRUE if this handler supports importing the given payload.
     *
     * This method must be defensive: it can receive any decoded payload data.
     *
     * @param array $payload
     *   Payload data.
     *
     * @phpstan-assert-if-true TPayload $payload
     */
    public function applies(array $payload): bool;


    /**
     * Exports key material as payload data.
     *
     * @return TPayload
     *   Payload data for this handler.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyTransferPayloadHandlerException
     *   When export cannot be performed.
     */
    public function exportPayload(EncryptionKeyId $keyId): array;


    /**
     * Imports key material from payload data for the provided key id.
     *
     * This method must not activate the key. Activation is application logic.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   Key identifier from the package envelope.
     * @param TPayload $payload
     *   Payload data for this handler.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyTransferPayloadHandlerException
     *   When import cannot be performed.
     */
    public function importPayload(EncryptionKeyId $keyId, array $payload): void;
}

Path: /src/Sodium/SodiumKeyPairReadRepositoryInterface.php#

namespace Drupal\easy_encryption\Sodium;

/**
 * Read-only repository for sodium key pairs.
 */
interface SodiumKeyPairReadRepositoryInterface
{
    /**
     * Returns a key pair by its identifier.
     *
     * Implementations MAY omit the private key when the current environment is
     * not allowed to perform decryption.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairNotFoundException
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     */
    public function getKeyPairById(string $id): SodiumKeyPair;


    /**
     * Returns identifiers for all stored key pairs.
     *
     * Implementations MUST return identifiers for all key pairs known to
     * the repository, regardless of whether the corresponding private
     * keys are available in the current environment.
     *
     * @return string[]
     *   An array of key pair identifiers.
     */
    public function listKeyPairIds(): array;
}

Path: /src/Sodium/SodiumKeyPairWriteRepositoryInterface.php#

namespace Drupal\easy_encryption\Sodium;

/**
 * Write repository for sodium key pairs.
 */
interface SodiumKeyPairWriteRepositoryInterface
{
    /**
     * Generates and persists a new key pair with the given id.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If generation or persistence fails.
     */
    public function generateKeyPair(string $id): void;


    /**
     * Deletes persisted key material for the given id.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If deletion fails.
     */
    public function deleteKeyPair(string $id): void;


    /**
     * Writes/updates public key material.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If persistence fails.
     */
    public function upsertPublicKey(string $id, string $publicKeyBin): void;


    /**
     * Writes/updates private key material.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If persistence fails.
     */
    public function upsertPrivateKey(string $id, string $privateKeyBin): void;
}

SOURCE: Explicit @api-marked elements (recommended)

Explicit @api-marked elements (recommended)#

// Structure of documents
No files found.

File Statistics - Size: 17.44 KB - Lines: 650 File: core/api-extension-points.md