zuraffa_messaging 0.1.0
zuraffa_messaging: ^0.1.0 copied to clipboard
Interface-based messaging for the Zuraffa ecosystem: pluggable transports behind one channel-routed facade, with send history, read receipts, and the versioned platform-channel contract the federated [...]
zuraffa_messaging #
Interface-based messaging for the Zuraffa ecosystem — any messaging backend (SMS gateway, push service, SMTP, chat webhook) implements MessageTransport behind one channel-routed facade.
Usage #
final messaging = MessagingService()
..register(InMemoryTransport('sms')) // swap in a TwilioTransport, FcmTransport, …
..register(InMemoryTransport('push'));
final message = await messaging.send('sms', OutboundMessage(
senderId: 'app', recipientId: '+1555…', body: 'Code 1234'));
await messaging.markRead(message.id);
Design #
- MessageTransport — one adapter interface per channel: send + acknowledge (receipts). The datasource pattern applied to transports.
- MessagingService — channel routing (no transport registered = typed error), send history, markRead receipts.
- InMemoryTransport — pure-Dart default with send recording, blocked-recipient scripting, and acknowledgment logs.
- Message entity + MessageDeliveryState enum via the zfa CLI (Zorphy).
- Typed MessagingException (no_transport / undeliverable).
Platform packages (android · ios · macos) #
This package stays pure Dart; the native stores live in the federated platform packages of the monorepo:
| Package | Native plugin | Store |
|---|---|---|
zuraffa_messaging_android |
Kotlin ZuraffaMessagingPlugin |
SharedPreferences |
zuraffa_messaging_ios |
Swift ZuraffaMessagingPlugin |
UserDefaults |
zuraffa_messaging_macos |
Swift ZuraffaMessagingPlugin |
UserDefaults |
Every platform serves one versioned channel contract — MessagingChannelContract: channel plugins.zuraffa.dev/messaging, method table send · acknowledge · blockRecipient · sent · reset, error code undeliverable, the msg-<channel>-<n> id grammar, and the seven-state delivery vocabulary. This package exposes the seam a Flutter host wires:
// in the consuming Flutter app — the only Flutter-dependent line:
class MethodChannelBridge implements MessagingBridge {
@override
Future<Object?> invoke(String method, Object? arguments) =>
const MethodChannel('plugins.zuraffa.dev/messaging')
.invokeMethod(method, arguments); // map PlatformException.code == 'undeliverable'
} // to MessagingBridgeException
final messaging = MessagingService()
..register(BridgeTransport('sms', MethodChannelBridge()));
Each platform package also ships a conformance kit (AndroidMessagingContract, IosMessagingContract, MacosMessagingContract) pinning its platform identifier to the shared contract so host apps can diff-check their wired channel.
TDD discipline #
Both behavioral surfaces are driven by the zfa tdd cycle (plan → gen → verify-red → make → refactor → run → verify) with journals, mutation audits, and proof receipts (kept at the monorepo root):
specs/001-messaging-port— the channel-routed core: engine 19/19 green, 60/60 mutants killed.specs/002-platform-transports— the bridge seam and platform packages: engine 17/17 green, 111/111 mutants killed.
Out of scope (v1) #
- Real transport adapters (HTTP gateways, push services) — transports are the plug-in seam.
- Prefix-ambiguous channel names —
markRead's prefix router matches the first registered channel whosemsg-<channel>-prefix fits. - Message metadata transport —
OutboundMessage.metadatais transport-internal input. - Delivery retry/receipt lifecycle beyond
acknowledge— state transitions are transport-owned.