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:
- Messages:
IMessageEnvelope(envelope) andIPayloadHandler(payload). - Routing:
IRoutingEngine(router),IMessageFilter(filter) andIRoutingRules(routing_rules). - Delivery:
IDeliveryManager(delivery) andIDeliveryGuarantee(guarantees). - Queues:
IQueue,IPriorityQueue(priority) andIQueueManager(queue and queue_manager). - Topics:
ITopicRegistry(topic_registry) andISubscriptionManager(subscription_manager). - Storage and replay:
IMessageStore(message_store),IReceiptStore(receipt_store) andIReplayEngine(replay_engine). - Operations:
IMetricsCollector(metrics),IErrorHandler(error_handler),IAdminInterface(admin) andIPostmanConfig(config).
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
Class diagram
Dependency diagram
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
"""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)
"""
...