orchestrata_ultimate.postman.interfaces

Reference › orchestrata_ultimate › postman › interfaces

The contracts of the broker: one Protocol for each component, so that any piece (a queue backend, the routing engine, a store) can be replaced without changing its callers. Each concrete class in the postman package implements exactly one of them, and the module is imported by most of them. Its argument and result types come from types. The curated postman page explains the design.

The protocols, grouped by area, with the implementing module:

Several of them are marked runtime_checkable, and a few carry traces markers tying them to SPEC-002 requirements. The facade Postman implements the core IPostman protocol from core.protocols instead. The module holds only declarations; the method lists are in the API section below.

At a glance

Source src/orchestrata_ultimate/postman/interfaces.py
Lines of code 1366
Classes 19
Functions 0
Imports (internal) orchestrata_ultimate.core.base.traces, orchestrata_ultimate.postman.types
Imported by orchestrata_ultimate.postman.admin, orchestrata_ultimate.postman.config, orchestrata_ultimate.postman.delivery, orchestrata_ultimate.postman.envelope, orchestrata_ultimate.postman.error_handler, orchestrata_ultimate.postman.filter, orchestrata_ultimate.postman.guarantees, orchestrata_ultimate.postman.message_store, orchestrata_ultimate.postman.metrics, orchestrata_ultimate.postman.payload, orchestrata_ultimate.postman.priority, orchestrata_ultimate.postman.queue, orchestrata_ultimate.postman.queue_manager, orchestrata_ultimate.postman.receipt_store, orchestrata_ultimate.postman.replay_engine, orchestrata_ultimate.postman.router, orchestrata_ultimate.postman.routing_rules, orchestrata_ultimate.postman.subscription_manager, orchestrata_ultimate.postman.topic_registry
Tests that import it tests/postman/test_cov100_postman.py, tests/postman/test_coverage_routing_rules.py, tests/postman/test_delivery.py, tests/postman/test_interface_implementations.py, tests/postman/test_interfaces_extended.py, tests/postman/test_postman_signatures.py

Class diagram

Class diagram orchestrata_ultimate.postman.interfaces

Dependency diagram

Dependency diagram orchestrata_ultimate.postman.interfaces

API

Classes

IMessageEnvelope (protocol)

Bases: Protocol · Decorators: runtime_checkable · Line 39

Interface for message envelope handling (FR-001).

Method Signature Summary
create create(sender: str, recipient: str, content_type: str = 'application/json', priority: int = 2, ttl_seconds: int | None = None, correlation_id: str | None = None, reply_to: str | None = None) -> MessageEnvelope Create a new message envelope.
validate validate(envelope: MessageEnvelope) -> tuple[bool, str | None] Validate envelope fields.
serialize serialize(envelope: MessageEnvelope) -> bytes Serialize envelope to bytes.
deserialize deserialize(data: bytes) -> MessageEnvelope Deserialize envelope from bytes.

IPayloadHandler (protocol)

Bases: Protocol · Decorators: runtime_checkable · Line 116

Interface for message payload handling (FR-002).

Method Signature Summary
validate validate(payload: bytes, content_type: str, max_size: int = 1024 * 1024) -> tuple[bool, str | None] Validate payload.
compress compress(payload: bytes) -> bytes Compress payload using gzip.
decompress decompress(payload: bytes) -> bytes Decompress gzip payload.
create_payload create_payload(data: Any, content_type: str = 'application/json', compress: bool = False) -> MessagePayload Create a message payload.

IRoutingEngine (protocol)

Bases: Protocol · Line 194

Interface for message routing (FR-003).

Method Signature Summary
resolve async resolve(envelope: MessageEnvelope) -> list[str] Resolve envelope to destination agent IDs.
add_route async add_route(pattern: str, destinations: list[str]) -> None Add static route.
remove_route async remove_route(pattern: str) -> bool Remove route.
invalidate_cache invalidate_cache(pattern: str | None = None) -> None Invalidate route cache.

IDeliveryManager (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-US-001-001']) · Line 246

Interface for core message delivery (US-001).

Method Signature Summary
deliver async deliver(envelope: MessageEnvelope, payload: MessagePayload, mode: DeliveryMode = DeliveryMode.AT_LEAST_ONCE) -> DeliveryResult Deliver message to recipients.
get_status async get_status(message_id: str) -> DeliveryResult | None Get delivery status for message.
cancel async cancel(message_id: str) -> bool Cancel pending delivery.

IQueue (protocol)

Bases: Protocol · Decorators: runtime_checkable · Line 304

Interface for queue implementation (FR-004).

Attribute Type Default
name str
Method Signature Summary
enqueue async enqueue(entry: QueueEntry) -> str Add entry to queue.
dequeue async dequeue() -> QueueEntry | None Remove and return next entry.
peek async peek() -> QueueEntry | None View next entry without removing.
size async size() -> int Get current queue size.
clear async clear() -> int Clear all entries.
checkpoint async checkpoint() -> None Create persistence checkpoint.
recover async recover() -> int Recover from last checkpoint.
is_empty async is_empty() -> bool Check if queue is empty.
close async close() -> None Close queue and release resources.

IPriorityQueue (protocol)

Bases: IQueue, Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-US-004-006']) · Line 388

Interface for priority queue (US-004).

Method Signature Summary
enqueue_with_priority async enqueue_with_priority(entry: QueueEntry, priority: int) -> str Add entry with explicit priority.
boost_priority async boost_priority(entry_id: str, new_priority: int) -> bool Boost entry priority.
get_by_priority async get_by_priority(priority: int) -> list[QueueEntry] Get all entries at priority level.

IQueueManager (protocol)

Bases: Protocol · Line 433

Interface for queue management (US-003).

Method Signature Summary
create_queue async create_queue(name: str, config: QueueConfig) -> IQueue Create named queue.
delete_queue async delete_queue(name: str) -> bool Delete queue.
get_queue async get_queue(name: str) -> IQueue | None Get queue by name.
list_queues async list_queues() -> list[str] List all queue names.
get_status async get_status(name: str) -> QueueStatus | None Get queue status.
purge_queue async purge_queue(name: str) -> int Purge all messages from queue.
get_dead_letter_queue async get_dead_letter_queue() -> IQueue Get dead-letter queue.

IDeliveryGuarantee (protocol)

Bases: Protocol · Line 521

Interface for delivery guarantees (US-007).

Method Signature Summary
send async send(message_id: str, destinations: list[str], mode: DeliveryMode) -> DeliveryResult Send with delivery guarantee.
acknowledge async acknowledge(message_id: str, destination: str) -> None Acknowledge delivery.
negative_acknowledge async negative_acknowledge(message_id: str, destination: str, reason: str) -> None Negative acknowledge (NACK).
get_pending_acks async get_pending_acks(message_id: str) -> list[str] Get destinations pending acknowledgment.

ITopicRegistry (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-FR5-001']) · Line 591

Interface for topic management (FR-005).

Method Signature Summary
create_topic async create_topic(definition: TopicDefinition) -> str Create topic.
delete_topic async delete_topic(topic_id: str) -> bool Delete topic.
get_topic async get_topic(topic_id: str) -> TopicDefinition | None Get topic definition.
list_topics async list_topics(pattern: str | None = None) -> list[str] List topics matching pattern.
match_topics async match_topics(pattern: str) -> list[str] Find topics matching pattern (wildcard/regex).

ISubscriptionManager (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-US-002-001']) · Line 662

Interface for subscription management (FR-006, US-002).

Method Signature Summary
subscribe async subscribe(agent_id: str, topic_pattern: str, ttl_seconds: int | None = None, filters: dict[str, Any] | None = None) -> TopicSubscription Subscribe agent to topic pattern.
unsubscribe async unsubscribe(agent_id: str, topic_pattern: str) -> bool Unsubscribe agent from topic.
unsubscribe_all async unsubscribe_all(agent_id: str) -> int Unsubscribe agent from all topics.
get_subscribers async get_subscribers(topic: str) -> list[str] Get all subscribers for topic.
get_subscriptions async get_subscriptions(agent_id: str) -> list[TopicSubscription] Get all subscriptions for agent.
match_subscribers async match_subscribers(topic: str) -> list[str] Find all subscribers matching topic (including wildcards).

IMessageStore (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-US-006-001']) · Line 766

Interface for message persistence (US-006).

Method Signature Summary
store async store(message_id: str, envelope: MessageEnvelope, payload: MessagePayload) -> None Store message.
retrieve async retrieve(message_id: str) -> tuple[MessageEnvelope, MessagePayload] | None Retrieve message by ID.
delete async delete(message_id: str) -> bool Delete message.
query async query(sender: str | None = None, recipient: str | None = None, topic: str | None = None, start_time: datetime | None = None, end_time: datetime | None = None, limit: int = 100) -> list[str] Query message IDs.
cleanup async cleanup(older_than: datetime) -> int Remove messages older than timestamp.
get_stats async get_stats() -> dict[str, Any] Get storage statistics.

IReceiptStore (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-FR7-006']) · Line 862

Interface for delivery receipt storage (FR-007).

Method Signature Summary
store async store(receipt: DeliveryReceipt) -> None Store delivery receipt.
get async get(message_id: str) -> list[DeliveryReceipt] Get receipts for message.
query async query(sender: str | None = None, recipient: str | None = None, start_time: datetime | None = None, end_time: datetime | None = None, limit: int = 100) -> list[DeliveryReceipt] Query receipts.
expire async expire(older_than: datetime) -> int Expire old receipts.

IReplayEngine (protocol)

Bases: Protocol · Line 928

Interface for message replay (US-006).

Method Signature Summary
replay async replay(message_ids: list[str], options: ReplayOptions) -> ReplayResult Replay messages.
replay_by_query async replay_by_query(sender: str | None = None, recipient: str | None = None, topic: str | None = None, start_time: datetime | None = None, end_time: datetime | None = None, options: ReplayOptions | None = None) -> ReplayResult Replay messages matching query.
cancel_replay async cancel_replay(replay_id: str) -> bool Cancel in-progress replay.

IMetricsCollector (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-FR9-001']) · Line 996

Interface for metrics collection (US-008, FR-009).

Method Signature Summary
record_message_sent record_message_sent(size_bytes: int, latency_ms: float) -> None Record message sent.
record_message_received record_message_received(size_bytes: int) -> None Record message received.
record_message_failed record_message_failed(error_type: str) -> None Record message failure.
record_queue_depth record_queue_depth(queue_name: str, depth: int) -> None Record queue depth.
get_snapshot get_snapshot() -> MetricsSnapshot Get current metrics snapshot.
export_prometheus export_prometheus() -> str Export metrics in Prometheus format.
export_json export_json() -> dict[str, Any] Export metrics as JSON.

IErrorHandler (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-FR8-020']) · Line 1071

Interface for error handling (FR-008).

Method Signature Summary
handle async handle(error: Exception, context: dict[str, Any]) -> tuple[bool, str | None] Handle error.
is_circuit_open is_circuit_open(destination: str) -> bool Check if circuit breaker is open for destination.
record_success record_success(destination: str) -> None Record successful operation for circuit breaker.
record_failure record_failure(destination: str) -> None Record failed operation for circuit breaker.

IAdminInterface (protocol)

Bases: Protocol · Line 1128

Interface for administrative operations (FR-010).

Method Signature Summary
list_agents async list_agents() -> list[dict[str, Any]] List all connected agents.
disconnect_agent async disconnect_agent(agent_id: str, reason: str) -> bool Disconnect agent.
get_system_status async get_system_status() -> dict[str, Any] Get overall system status.
export_config async export_config() -> dict[str, Any] Export current configuration.
import_config async import_config(config: dict[str, Any]) -> bool Import configuration.

IMessageFilter (protocol)

Bases: Protocol · Decorators: traces(spec='002', story='US-001', reqs=['REQ-002-US-005-006']), runtime_checkable · Line 1196

Interface for message filtering (US-005).

Method Signature Summary
matches matches(envelope: MessageEnvelope, payload: MessagePayload, criteria: FilterCriteria) -> bool Check if message matches filter criteria.
compile_filter compile_filter(criteria: FilterCriteria) -> Callable Compile filter criteria for faster evaluation.

IRoutingRules (protocol)

Bases: Protocol · Line 1236

Interface for routing rules engine (US-005).

Method Signature Summary
add_rule async add_rule(rule: RoutingRule) -> str Add routing rule.
remove_rule async remove_rule(rule_id: str) -> bool Remove routing rule.
update_rule async update_rule(rule_id: str, rule: RoutingRule) -> bool Update routing rule.
list_rules async list_rules() -> list[RoutingRule] List all rules.
evaluate async evaluate(envelope: MessageEnvelope, payload: MessagePayload) -> list[str] Evaluate rules and return destinations.

IPostmanConfig (protocol)

Bases: Protocol · Line 1308

Interface for Postman configuration (US-009, FR-011).

Method Signature Summary
load load() -> PostmanConfig Load configuration from all sources.
reload reload() -> tuple[bool, str | None] Reload configuration.
get get(key: str, default: Any = None) -> Any Get configuration value.
validate validate(config: dict[str, Any]) -> tuple[bool, list[str]] Validate configuration.
on_change on_change(callback: Callable[[str, Any, Any], None]) -> None Register config change callback.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/src/orchestrata_ultimate/postman/interfaces.py

"""Postman Component Interfaces.

Defines all protocols/interfaces for the Postman message broker.
Each stream implements specific interfaces from this module.
"""

# Spec: 002 - Postman Message Broker

from collections.abc import Callable
from datetime import datetime
from typing import Any, Protocol, runtime_checkable

from orchestrata_ultimate.core.base.traces import traces
from orchestrata_ultimate.postman.types import (
    DeliveryMode,
    DeliveryReceipt,
    DeliveryResult,
    FilterCriteria,
    MessageEnvelope,
    MessagePayload,
    MetricsSnapshot,
    PostmanConfig,
    QueueConfig,
    QueueEntry,
    QueueStatus,
    ReplayOptions,
    ReplayResult,
    RoutingRule,
    TopicDefinition,
    TopicSubscription,
)

# =============================================================================
# Stream A: Message Core Interfaces
# =============================================================================


@runtime_checkable
class IMessageEnvelope(Protocol):
    """Interface for message envelope handling (FR-001).

    Responsible for:
    - Creating and validating message envelopes
    - Serializing/deserializing envelopes
    - Extracting routing and priority information
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR1-019"])
    def create(
        self,
        sender: str,
        recipient: str,
        content_type: str = "application/json",
        priority: int = 2,
        ttl_seconds: int | None = None,
        correlation_id: str | None = None,
        reply_to: str | None = None,
    ) -> MessageEnvelope:
        """Create a new message envelope.

        Args:
            sender: Sender agent ID
            recipient: Recipient agent ID or topic
            content_type: MIME type of payload
            priority: Priority level (0=CRITICAL to 4=BACKGROUND)
            ttl_seconds: Time-to-live in seconds
            correlation_id: For request-response correlation
            reply_to: Reply destination

        Returns:
            New MessageEnvelope instance
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR1-010"])
    def validate(self, envelope: MessageEnvelope) -> tuple[bool, str | None]:
        """Validate envelope fields.

        Args:
            envelope: Envelope to validate

        Returns:
            Tuple of (is_valid, error_message)
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR1-016"])
    def serialize(self, envelope: MessageEnvelope) -> bytes:
        """Serialize envelope to bytes.

        Args:
            envelope: Envelope to serialize

        Returns:
            Serialized bytes
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR1-015"])
    def deserialize(self, data: bytes) -> MessageEnvelope:
        """Deserialize envelope from bytes.

        Args:
            data: Serialized envelope data

        Returns:
            Deserialized MessageEnvelope

        Raises:
            ValueError: If data is malformed
        """
        ...


@runtime_checkable
class IPayloadHandler(Protocol):
    """Interface for message payload handling (FR-002).

    Responsible for:
    - Validating payloads (size, content type)
    - Compressing/decompressing payloads
    - Encrypting/decrypting payloads (optional)
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR2-006"])
    def validate(
        self, payload: bytes, content_type: str, max_size: int = 1024 * 1024
    ) -> tuple[bool, str | None]:
        """Validate payload.

        Args:
            payload: Payload bytes
            content_type: Declared content type
            max_size: Maximum allowed size in bytes

        Returns:
            Tuple of (is_valid, error_message)
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR2-004"])
    def compress(self, payload: bytes) -> bytes:
        """Compress payload using gzip.

        Args:
            payload: Uncompressed payload

        Returns:
            Compressed payload
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR2-012"])
    def decompress(self, payload: bytes) -> bytes:
        """Decompress gzip payload.

        Args:
            payload: Compressed payload

        Returns:
            Decompressed payload
        """
        ...

    @traces(
        spec="002",
        story="US-002-001",
        reqs=[
            "REQ-002-FR2-001",
            "REQ-002-FR2-002",
            "REQ-002-FR2-003",
            "REQ-002-FR2-004",
        ],
    )
    def create_payload(
        self,
        data: Any,
        content_type: str = "application/json",
        compress: bool = False,
    ) -> MessagePayload:
        """Create a message payload.

        Args:
            data: Payload data (will be serialized based on content_type)
            content_type: MIME type
            compress: Whether to compress

        Returns:
            MessagePayload instance
        """
        ...


class IRoutingEngine(Protocol):
    """Interface for message routing (FR-003).

    Responsible for:
    - Resolving message destinations
    - Caching routes
    - Supporting different routing modes
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR3-006", "REQ-002-FR3-007"])
    async def resolve(self, envelope: MessageEnvelope) -> list[str]:
        """Resolve envelope to destination agent IDs.

        Args:
            envelope: Message envelope with routing info

        Returns:
            List of destination agent IDs
        """
        ...

    async def add_route(self, pattern: str, destinations: list[str]) -> None:
        """Add static route.

        Args:
            pattern: Route pattern (agent ID, topic, or wildcard)
            destinations: List of destination agent IDs
        """
        ...

    async def remove_route(self, pattern: str) -> bool:
        """Remove route.

        Args:
            pattern: Route pattern to remove

        Returns:
            True if route was found and removed
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR3-012"])
    def invalidate_cache(self, pattern: str | None = None) -> None:
        """Invalidate route cache.

        Args:
            pattern: Specific pattern to invalidate, or None for all
        """
        ...


@traces(spec="002", story="US-001", reqs=["REQ-002-US-001-001"])
class IDeliveryManager(Protocol):
    """Interface for core message delivery (US-001).

    Responsible for:
    - Sending messages through the system
    - Tracking delivery status
    - Handling delivery errors
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-001-001"])
    async def deliver(
        self,
        envelope: MessageEnvelope,
        payload: MessagePayload,
        mode: DeliveryMode = DeliveryMode.AT_LEAST_ONCE,
    ) -> DeliveryResult:
        """Deliver message to recipients.

        Args:
            envelope: Message envelope
            payload: Message payload
            mode: Delivery guarantee mode

        Returns:
            DeliveryResult with status
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-001-005"])
    async def get_status(self, message_id: str) -> DeliveryResult | None:
        """Get delivery status for message.

        Args:
            message_id: Message ID to check

        Returns:
            DeliveryResult or None if not found
        """
        ...

    async def cancel(self, message_id: str) -> bool:
        """Cancel pending delivery.

        Args:
            message_id: Message ID to cancel

        Returns:
            True if cancelled, False if already delivered or not found
        """
        ...


# =============================================================================
# Stream B: Queue & Delivery Interfaces
# =============================================================================


@runtime_checkable
class IQueue(Protocol):
    """Interface for queue implementation (FR-004).

    Responsible for:
    - Basic queue operations (enqueue, dequeue, peek)
    - Persistence and recovery
    - Concurrent access safety
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-006"])
    async def enqueue(self, entry: QueueEntry) -> str:
        """Add entry to queue.

        Args:
            entry: Queue entry to add

        Returns:
            Entry ID
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-007"])
    async def dequeue(self) -> QueueEntry | None:
        """Remove and return next entry.

        Returns:
            Next entry or None if empty
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-008"])
    async def peek(self) -> QueueEntry | None:
        """View next entry without removing.

        Returns:
            Next entry or None if empty
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-009"])
    async def size(self) -> int:
        """Get current queue size.

        Returns:
            Number of entries in queue
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-010"])
    async def clear(self) -> int:
        """Clear all entries.

        Returns:
            Number of entries cleared
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-013"])
    async def checkpoint(self) -> None:
        """Create persistence checkpoint."""
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-014"])
    async def recover(self) -> int:
        """Recover from last checkpoint.

        Returns:
            Number of entries recovered
        """
        ...

    name: str
    """Queue identifier."""

    async def is_empty(self) -> bool:
        """Check if queue is empty."""
        ...

    async def close(self) -> None:
        """Close queue and release resources."""
        ...


@traces(spec="002", story="US-001", reqs=["REQ-002-US-004-006"])
class IPriorityQueue(IQueue, Protocol):
    """Interface for priority queue (US-004).

    Extends IQueue with priority-based operations.
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-004-012"])
    async def enqueue_with_priority(self, entry: QueueEntry, priority: int) -> str:
        """Add entry with explicit priority.

        Args:
            entry: Queue entry
            priority: Priority level (0=highest)

        Returns:
            Entry ID
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-004-012"])
    async def boost_priority(self, entry_id: str, new_priority: int) -> bool:
        """Boost entry priority.

        Args:
            entry_id: Entry to boost
            new_priority: New priority level

        Returns:
            True if boosted, False if not found
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR4-011"])
    async def get_by_priority(self, priority: int) -> list[QueueEntry]:
        """Get all entries at priority level.

        Args:
            priority: Priority level

        Returns:
            List of entries at that priority
        """
        ...


class IQueueManager(Protocol):
    """Interface for queue management (US-003).

    Responsible for:
    - Creating and managing named queues
    - Queue lifecycle operations
    - Dead-letter queue handling
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-001"])
    async def create_queue(self, name: str, config: QueueConfig) -> IQueue:
        """Create named queue.

        Args:
            name: Queue name
            config: Queue configuration

        Returns:
            Queue instance
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-002"])
    async def delete_queue(self, name: str) -> bool:
        """Delete queue.

        Args:
            name: Queue name

        Returns:
            True if deleted
        """
        ...

    async def get_queue(self, name: str) -> IQueue | None:
        """Get queue by name.

        Args:
            name: Queue name

        Returns:
            Queue instance or None
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-003"])
    async def list_queues(self) -> list[str]:
        """List all queue names.

        Returns:
            List of queue names
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-004"])
    async def get_status(self, name: str) -> QueueStatus | None:
        """Get queue status.

        Args:
            name: Queue name

        Returns:
            QueueStatus or None if not found
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-005"])
    async def purge_queue(self, name: str) -> int:
        """Purge all messages from queue.

        Args:
            name: Queue name

        Returns:
            Number of messages purged
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-003-009"])
    async def get_dead_letter_queue(self) -> IQueue:
        """Get dead-letter queue.

        Returns:
            Dead-letter queue instance
        """
        ...


class IDeliveryGuarantee(Protocol):
    """Interface for delivery guarantees (US-007).

    Responsible for:
    - Implementing delivery semantics (at-most-once, at-least-once, exactly-once)
    - Managing acknowledgments
    - Handling retries and timeouts
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-007-004"])
    async def send(
        self,
        message_id: str,
        destinations: list[str],
        mode: DeliveryMode,
    ) -> DeliveryResult:
        """Send with delivery guarantee.

        Args:
            message_id: Message ID
            destinations: Target destinations
            mode: Delivery mode

        Returns:
            DeliveryResult
        """
        ...

    @traces(spec="001", story="US-002", reqs=["REQ-001-US-002-034"])
    async def acknowledge(self, message_id: str, destination: str) -> None:
        """Acknowledge delivery.

        Args:
            message_id: Message ID
            destination: Acknowledging destination
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-007-008"])
    async def negative_acknowledge(
        self, message_id: str, destination: str, reason: str
    ) -> None:
        """Negative acknowledge (NACK).

        Args:
            message_id: Message ID
            destination: NACKing destination
            reason: Failure reason
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-007-018"])
    async def get_pending_acks(self, message_id: str) -> list[str]:
        """Get destinations pending acknowledgment.

        Args:
            message_id: Message ID

        Returns:
            List of destinations still pending
        """
        ...


# =============================================================================
# Stream C: Topic & Subscription Interfaces
# =============================================================================


@traces(spec="002", story="US-001", reqs=["REQ-002-FR5-001"])
class ITopicRegistry(Protocol):
    """Interface for topic management (FR-005).

    Responsible for:
    - Storing topic definitions
    - Topic CRUD operations
    - Persistence
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR5-006"])
    async def create_topic(self, definition: TopicDefinition) -> str:
        """Create topic.

        Args:
            definition: Topic definition

        Returns:
            Topic ID
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR5-007"])
    async def delete_topic(self, topic_id: str) -> bool:
        """Delete topic.

        Args:
            topic_id: Topic ID

        Returns:
            True if deleted
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR5-009"])
    async def get_topic(self, topic_id: str) -> TopicDefinition | None:
        """Get topic definition.

        Args:
            topic_id: Topic ID

        Returns:
            TopicDefinition or None
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR5-008"])
    async def list_topics(self, pattern: str | None = None) -> list[str]:
        """List topics matching pattern.

        Args:
            pattern: Optional filter pattern

        Returns:
            List of topic IDs
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR5-013", "REQ-002-FR5-014"])
    async def match_topics(self, pattern: str) -> list[str]:
        """Find topics matching pattern (wildcard/regex).

        Args:
            pattern: Match pattern

        Returns:
            List of matching topic IDs
        """
        ...


@traces(spec="002", story="US-001", reqs=["REQ-002-US-002-001"])
class ISubscriptionManager(Protocol):
    """Interface for subscription management (FR-006, US-002).

    Responsible for:
    - Managing topic subscriptions
    - Matching messages to subscribers
    - Subscription lifecycle
    """

    @traces(
        spec="002",
        story="US-002-001",
        reqs=["REQ-002-US-002-001", "REQ-002-US-005-001", "REQ-002-US-005-006"],
    )
    async def subscribe(
        self,
        agent_id: str,
        topic_pattern: str,
        ttl_seconds: int | None = None,
        filters: dict[str, Any] | None = None,
    ) -> TopicSubscription:
        """Subscribe agent to topic pattern.

        Args:
            agent_id: Subscribing agent
            topic_pattern: Topic pattern (supports wildcards)
            ttl_seconds: Optional subscription TTL
            filters: Optional key-value predicates evaluated against a
                publish payload (see ``subscription_manager.evaluate_filters``);
                omitted/empty means every payload on the topic is delivered.

        Returns:
            TopicSubscription instance
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-002-002"])
    async def unsubscribe(self, agent_id: str, topic_pattern: str) -> bool:
        """Unsubscribe agent from topic.

        Args:
            agent_id: Agent ID
            topic_pattern: Topic pattern

        Returns:
            True if unsubscribed
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR6-007"])
    async def unsubscribe_all(self, agent_id: str) -> int:
        """Unsubscribe agent from all topics.

        Args:
            agent_id: Agent ID

        Returns:
            Number of subscriptions removed
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR6-009"])
    async def get_subscribers(self, topic: str) -> list[str]:
        """Get all subscribers for topic.

        Args:
            topic: Topic ID

        Returns:
            List of subscriber agent IDs
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR6-008"])
    async def get_subscriptions(self, agent_id: str) -> list[TopicSubscription]:
        """Get all subscriptions for agent.

        Args:
            agent_id: Agent ID

        Returns:
            List of subscriptions
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR6-011"])
    async def match_subscribers(self, topic: str) -> list[str]:
        """Find all subscribers matching topic (including wildcards).

        Args:
            topic: Topic to match

        Returns:
            List of matching subscriber agent IDs
        """
        ...


# =============================================================================
# Stream D: Persistence & Replay Interfaces
# =============================================================================


@traces(spec="002", story="US-001", reqs=["REQ-002-US-006-001"])
class IMessageStore(Protocol):
    """Interface for message persistence (US-006).

    Responsible for:
    - Storing messages durably
    - Managing retention and cleanup
    - Supporting queries
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-006-001"])
    async def store(
        self,
        message_id: str,
        envelope: MessageEnvelope,
        payload: MessagePayload,
    ) -> None:
        """Store message.

        Args:
            message_id: Message ID
            envelope: Message envelope
            payload: Message payload
        """
        ...

    async def retrieve(
        self, message_id: str
    ) -> tuple[MessageEnvelope, MessagePayload] | None:
        """Retrieve message by ID.

        Args:
            message_id: Message ID

        Returns:
            Tuple of (envelope, payload) or None
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-006-009"])
    async def delete(self, message_id: str) -> bool:
        """Delete message.

        Args:
            message_id: Message ID

        Returns:
            True if deleted
        """
        ...

    async def query(
        self,
        sender: str | None = None,
        recipient: str | None = None,
        topic: str | None = None,
        start_time: datetime | None = None,
        end_time: datetime | None = None,
        limit: int = 100,
    ) -> list[str]:
        """Query message IDs.

        Args:
            sender: Filter by sender
            recipient: Filter by recipient
            topic: Filter by topic
            start_time: Filter by start time
            end_time: Filter by end time
            limit: Maximum results

        Returns:
            List of matching message IDs
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-006-008"])
    async def cleanup(self, older_than: datetime) -> int:
        """Remove messages older than timestamp.

        Args:
            older_than: Cutoff timestamp

        Returns:
            Number of messages removed
        """
        ...

    async def get_stats(self) -> dict[str, Any]:
        """Get storage statistics.

        Returns:
            Dict with storage stats (count, size, oldest, etc.)
        """
        ...


@traces(spec="002", story="US-001", reqs=["REQ-002-FR7-006"])
class IReceiptStore(Protocol):
    """Interface for delivery receipt storage (FR-007).

    Responsible for:
    - Storing delivery receipts
    - Receipt queries
    - Receipt expiration
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR7-006"])
    async def store(self, receipt: DeliveryReceipt) -> None:
        """Store delivery receipt.

        Args:
            receipt: Receipt to store
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR7-011"])
    async def get(self, message_id: str) -> list[DeliveryReceipt]:
        """Get receipts for message.

        Args:
            message_id: Message ID

        Returns:
            List of receipts
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR7-012"])
    async def query(
        self,
        sender: str | None = None,
        recipient: str | None = None,
        start_time: datetime | None = None,
        end_time: datetime | None = None,
        limit: int = 100,
    ) -> list[DeliveryReceipt]:
        """Query receipts.

        Args:
            sender: Filter by sender
            recipient: Filter by recipient
            start_time: Filter by start time
            end_time: Filter by end time
            limit: Maximum results

        Returns:
            List of matching receipts
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR7-010"])
    async def expire(self, older_than: datetime) -> int:
        """Expire old receipts.

        Args:
            older_than: Cutoff timestamp

        Returns:
            Number of receipts expired
        """
        ...


class IReplayEngine(Protocol):
    """Interface for message replay (US-006).

    Responsible for:
    - Replaying stored messages
    - Supporting different replay modes
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-006-014"])
    async def replay(
        self,
        message_ids: list[str],
        options: ReplayOptions,
    ) -> ReplayResult:
        """Replay messages.

        Args:
            message_ids: Messages to replay
            options: Replay options

        Returns:
            ReplayResult with status
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-006-015"])
    async def replay_by_query(
        self,
        sender: str | None = None,
        recipient: str | None = None,
        topic: str | None = None,
        start_time: datetime | None = None,
        end_time: datetime | None = None,
        options: ReplayOptions | None = None,
    ) -> ReplayResult:
        """Replay messages matching query.

        Args:
            sender: Filter by sender
            recipient: Filter by recipient
            topic: Filter by topic
            start_time: Filter by start time
            end_time: Filter by end time
            options: Replay options

        Returns:
            ReplayResult
        """
        ...

    async def cancel_replay(self, replay_id: str) -> bool:
        """Cancel in-progress replay.

        Args:
            replay_id: Replay ID to cancel

        Returns:
            True if cancelled
        """
        ...


# =============================================================================
# Stream E: Monitoring & Admin Interfaces
# =============================================================================


@traces(spec="002", story="US-001", reqs=["REQ-002-FR9-001"])
class IMetricsCollector(Protocol):
    """Interface for metrics collection (US-008, FR-009).

    Responsible for:
    - Collecting performance metrics
    - Aggregating and calculating percentiles
    - Exporting metrics
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-001"])
    def record_message_sent(self, size_bytes: int, latency_ms: float) -> None:
        """Record message sent.

        Args:
            size_bytes: Message size
            latency_ms: Send latency
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-002"])
    def record_message_received(self, size_bytes: int) -> None:
        """Record message received.

        Args:
            size_bytes: Message size
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-005"])
    def record_message_failed(self, error_type: str) -> None:
        """Record message failure.

        Args:
            error_type: Type of error
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-013"])
    def record_queue_depth(self, queue_name: str, depth: int) -> None:
        """Record queue depth.

        Args:
            queue_name: Queue name
            depth: Current depth
        """
        ...

    def get_snapshot(self) -> MetricsSnapshot:
        """Get current metrics snapshot.

        Returns:
            MetricsSnapshot with all current metrics
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-027"])
    def export_prometheus(self) -> str:
        """Export metrics in Prometheus format.

        Returns:
            Prometheus-formatted metrics string
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-008-028"])
    def export_json(self) -> dict[str, Any]:
        """Export metrics as JSON.

        Returns:
            Dict with all metrics
        """
        ...


@traces(spec="002", story="US-001", reqs=["REQ-002-FR8-020"])
class IErrorHandler(Protocol):
    """Interface for error handling (FR-008).

    Responsible for:
    - Handling and logging errors
    - Retry logic
    - Circuit breaker pattern
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR8-016"])
    async def handle(
        self,
        error: Exception,
        context: dict[str, Any],
    ) -> tuple[bool, str | None]:
        """Handle error.

        Args:
            error: Exception that occurred
            context: Error context (message_id, destination, etc.)

        Returns:
            Tuple of (should_retry, error_response)
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR8-020"])
    def is_circuit_open(self, destination: str) -> bool:
        """Check if circuit breaker is open for destination.

        Args:
            destination: Destination to check

        Returns:
            True if circuit is open (must not send)
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR8-020"])
    def record_success(self, destination: str) -> None:
        """Record successful operation for circuit breaker.

        Args:
            destination: Destination that succeeded
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR8-020"])
    def record_failure(self, destination: str) -> None:
        """Record failed operation for circuit breaker.

        Args:
            destination: Destination that failed
        """
        ...


class IAdminInterface(Protocol):
    """Interface for administrative operations (FR-010).

    Responsible for:
    - Admin queries and operations
    - Configuration management
    - Audit logging
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR10-001"])
    async def list_agents(self) -> list[dict[str, Any]]:
        """List all connected agents.

        Returns:
            List of agent info dicts
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR10-009"])
    async def disconnect_agent(self, agent_id: str, reason: str) -> bool:
        """Disconnect agent.

        Args:
            agent_id: Agent to disconnect
            reason: Disconnect reason

        Returns:
            True if disconnected
        """
        ...

    async def get_system_status(self) -> dict[str, Any]:
        """Get overall system status.

        Returns:
            Dict with system status
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR10-011"])
    async def export_config(self) -> dict[str, Any]:
        """Export current configuration.

        Returns:
            Configuration dict
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR10-012"])
    async def import_config(self, config: dict[str, Any]) -> bool:
        """Import configuration.

        Args:
            config: Configuration to import

        Returns:
            True if imported successfully
        """
        ...


# =============================================================================
# Stream F: Filtering & Configuration Interfaces
# =============================================================================


@traces(spec="002", story="US-001", reqs=["REQ-002-US-005-006"])
@runtime_checkable
class IMessageFilter(Protocol):
    """Interface for message filtering (US-005).

    Responsible for:
    - Filtering messages by various criteria
    - Composite filter logic
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-006"])
    def matches(
        self,
        envelope: MessageEnvelope,
        payload: MessagePayload,
        criteria: FilterCriteria,
    ) -> bool:
        """Check if message matches filter criteria.

        Args:
            envelope: Message envelope
            payload: Message payload
            criteria: Filter criteria

        Returns:
            True if matches
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-025"])
    def compile_filter(self, criteria: FilterCriteria) -> Callable:
        """Compile filter criteria for faster evaluation.

        Args:
            criteria: Filter criteria

        Returns:
            Compiled filter function
        """
        ...


class IRoutingRules(Protocol):
    """Interface for routing rules engine (US-005).

    Responsible for:
    - Managing routing rules
    - Evaluating rules against messages
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-012"])
    async def add_rule(self, rule: RoutingRule) -> str:
        """Add routing rule.

        Args:
            rule: Rule to add

        Returns:
            Rule ID
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-014"])
    async def remove_rule(self, rule_id: str) -> bool:
        """Remove routing rule.

        Args:
            rule_id: Rule ID

        Returns:
            True if removed
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-013"])
    async def update_rule(self, rule_id: str, rule: RoutingRule) -> bool:
        """Update routing rule.

        Args:
            rule_id: Rule ID
            rule: Updated rule

        Returns:
            True if updated
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-015"])
    async def list_rules(self) -> list[RoutingRule]:
        """List all rules.

        Returns:
            List of rules
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-005-018"])
    async def evaluate(
        self,
        envelope: MessageEnvelope,
        payload: MessagePayload,
    ) -> list[str]:
        """Evaluate rules and return destinations.

        Args:
            envelope: Message envelope
            payload: Message payload

        Returns:
            List of destination agent IDs from matching rules
        """
        ...


class IPostmanConfig(Protocol):
    """Interface for Postman configuration (US-009, FR-011).

    Responsible for:
    - Loading configuration from various sources
    - Hot-reload support
    - Validation
    """

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR11-004"])
    def load(self) -> PostmanConfig:
        """Load configuration from all sources.

        Returns:
            Merged PostmanConfig
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-009-025"])
    def reload(self) -> tuple[bool, str | None]:
        """Reload configuration.

        Returns:
            Tuple of (success, error_message)
        """
        ...

    def get(self, key: str, default: Any = None) -> Any:
        """Get configuration value.

        Args:
            key: Config key (dot-notation supported)
            default: Default value

        Returns:
            Config value
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-FR11-005"])
    def validate(self, config: dict[str, Any]) -> tuple[bool, list[str]]:
        """Validate configuration.

        Args:
            config: Config dict to validate

        Returns:
            Tuple of (is_valid, error_messages)
        """
        ...

    @traces(spec="002", story="US-002-001", reqs=["REQ-002-US-009-028"])
    def on_change(self, callback: Callable[[str, Any, Any], None]) -> None:
        """Register config change callback.

        Args:
            callback: Function(key, old_value, new_value)
        """
        ...