Unified reliability layer for cross-context messaging: NATS JetStream with outbox/inbox patterns, canonical event envelopes, per-context streams, deduplication, DLQ handling, and external integration transports.
Consolidation Note: This plan merges P006 (Integration Gateway) and the previous P017 (Messaging Infrastructure) per ADR-032, which defines outbox/inbox + JetStream as a unified reliability pattern.
| ADR ID | Decision Title | Impact on This Plan |
|---|---|---|
| ADR-032 | NATS JetStream Messaging Architecture | Establishes outbox/inbox + subject versioning, per-context streams, delivery semantics. |
| ADR-033 | Kernel-Shell Architecture | Integration is a shell concern: translate protocols → publish/consume events. |
| ADR-011 | Internal Federated Ledger (IFL) | All externally significant events should be attestable and traceable. |
| PRD ID | Requirement Title | Satisfied By (SDS) | Acceptance Criteria |
|---|---|---|---|
| PRD-022 | Reliable Cross-Context Messaging Platform | SDS-047 | REQ-050..REQ-056 (outbox/inbox, dedupe, streams) |
| PRD-003 | Internal Federated Ledger + Identity Tokens | SDS-050 | Provenance + identity anchoring for emitted artifacts |
| SDS ID | Service/Component | Bounded Context | SEA-DSL Spec File | Implementation Status |
|---|---|---|---|---|
| SDS-047 | Messaging Infrastructure Service | shared |
N/A | Draft |
| SDS-030 | Semantic Observability Envelope | shared |
N/A | Draft |
graph TD
ADR32[ADR-032: JetStream + Outbox/Inbox] --> PRD22[PRD-022: Cross-Context Messaging]
ADR11[ADR-011: IFL] --> PRD3[PRD-003: IFL + Identity Tokens]
PRD22 --> SDS47[SDS-047: Messaging Infrastructure]
PRD3 --> SDS30[SDS-030: Observability Envelope]
SDS47 --> Impl[Implementation]
SDS30 --> Impl
.v1, .v2) and immutable meaning (ADR-032). Per-context streams are mandatory.Nats-Msg-Id; inbox processing dedupe via inbox PK.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌─────────────────────────────────────────────────────────────────────────┐
│ Messaging Substrate │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Internal Messaging Layer │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Outbox │───────▶│ JetStream │◀───────│ Inbox │ │ │
│ │ │ Publisher │ │ Streams │ │ Consumer │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌───────────────────────────────────────────────────────────┐ │ │
│ │ │ PostgreSQL (per-context DB) │ │ │
│ │ │ outbox_events │ inbox_messages │ │ │
│ │ └───────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Integration Layer (Shell) │ │
│ │ ┌─────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Outbound Edge │ │ Inbound Edge │ │ │
│ │ │ (JetStream → │ │ (Partner Signal → │ │ │
│ │ │ Webhooks/A2A) │ │ Kernel Command) │ │ │
│ │ └─────────────────┘ └─────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
| Dependency | Type | Version | NPM/PyPI Package | Justification | ADR/SDS Reference |
|---|---|---|---|---|---|
| NATS Client | Node/Python Library | 2.x |
nats (Node); nats-py (Python) |
Publish/subscribe to JetStream streams. | ADR-032, SDS-047 |
| NATS Server | Docker Service | 2.10.x |
nats:2.10-alpine (Docker) |
JetStream-enabled message broker. | ADR-032 |
| Dependency | Type | Version | NPM/PyPI Package | Justification | ADR/SDS Reference |
|---|---|---|---|---|---|
| ts-event-bus | Node Library | 4.x |
ts-event-bus |
Transactional outbox pattern implementation. | PRD-022, SDS-047 |
| uuid | Node/Python Library | 10.x |
uuid (Node); uuid (Python) |
Generate idempotency keys for message deduplication. | SDS-047 |
| Dependency | Type | Version | Crate | Justification | ADR/SDS Reference |
|---|---|---|---|---|---|
| async-nats | Rust Library | 0.34.x |
async-nats |
JetStream client for Rust worker. | SDS-047 |
| sqlx | Rust Library | 0.8.x |
sqlx |
Compile-time checked PostgreSQL queries. | SDS-047 |
| tokio | Rust Library | 1.x |
tokio |
Async runtime. | SDS-047 |
| reqwest | Rust Library | 0.12.x |
reqwest |
HTTP client for calling FastAPI handlers. | SDS-047 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Node.js dependencies
pnpm add nats ts-event-bus uuid
# Python dependencies
pip install nats-py uuid
# Docker (add to infra/docker-compose.yml)
# nats:
# image: nats:2.10-alpine
# command: ["--jetstream", "--store_dir=/data"]
# ports: ["4222:4222"]
# Rust dependencies (in Cargo.toml)
# async-nats = "0.34"
# sqlx = { version = "0.8", features = ["postgres", "runtime-tokio"] }
# tokio = { version = "1", features = ["full"] }
# reqwest = { version = "0.12", features = ["json"] }
Outbound (Internal → External):
Inbound (External → Internal):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/
├── schemas/events/
│ ├── envelope-v1.schema.json # Canonical event envelope
│ └── messaging/ # Outbox/inbox schemas
│ ├── outbox-event.schema.json
│ └── inbox-message.schema.json
├── docs/specs/shared/
│ ├── adr/032-nats-jetstream-messaging.md
│ └── sds/047-messaging-infrastructure.md
├── libs/shared/messaging/ # Messaging library (TS)
│ └── src/gen/** # Generated adapters/publishers
└── apps/sea-mq-worker/ # Rust worker
└── src/
├── outbox_publisher.rs
├── inbox_consumer.rs
└── main.rs
| Cycle | Branch | Wave | Files Modified | Files Created | Specs Implemented |
|---|---|---|---|---|---|
| C1A | cycle/p017-c1a-outbox-inbox-schemas |
1 | docs/specs/shared/sds/047-messaging-infrastructure.md |
schemas/events/messaging/* |
Outbox/inbox entities, event envelopes |
| C1B | cycle/p017-c1b-streams-subjects |
1 | docs/specs/shared/adr/032-nats-jetstream-messaging.md |
— | Per-context streams + subject versioning |
| C2A | cycle/p017-c2a-outbox-publisher |
2 | — | apps/sea-mq-worker/src/outbox_publisher.rs |
Outbound publishing with dedupe |
| C2B | cycle/p017-c2b-inbox-consumer |
2 | — | apps/sea-mq-worker/src/inbox_consumer.rs |
Inbound processing with dedupe |
| C3A | cycle/p017-c3a-dlq-handling |
3 | docs/specs/shared/sds/047-messaging-infrastructure.md |
— | Poison handling + DLQ routing |
| C3B | cycle/p017-c3b-envelope-validation |
3 | schemas/events/envelope-v1.schema.json |
schemas/events/integration/* |
Canonical envelope for external transports |
| C4A | cycle/p017-c4a-inbound-adapters |
4 | docs/specs/shared/sds/030-semantic-observability.md |
generated **/src/gen/** |
Partner signal normalization + correlation |
docs/specs/shared/sds/047-messaging-infrastructure.md, schemas/events/messaging/*docs/specs/shared/adr/032-nats-jetstream-messaging.mdNats-Msg-Id dedupeapps/sea-mq-worker/src/outbox_publisher.rsapps/sea-mq-worker/src/inbox_consumer.rsdocs/specs/shared/sds/047-messaging-infrastructure.mdschemas/events/envelope-v1.schema.json, schemas/events/integration/*docs/specs/shared/sds/030-semantic-observability.md, generated **/src/gen/**{context}.event.{name}.v{n} (ADR-032)schemas/events/envelope-v1.schema.jsonNats-Msg-Id header set)inbox_messages PK dedupe)| INV-ID | Invariant | Enforcement |
|---|---|---|
| INV-020 | At-least-once delivery | JetStream redelivery |
| INV-021 | Exactly-once processing | Inbox PK constraint |
| INV-022 | State and event atomically written | Same DB transaction |
| INV-023 | Events versioned immutably | Subject naming |
| # | Question | Resolution |
|---|---|---|
| 1 | Which contexts should have streams in MVP? | sea, vibespro, governance |
| 2 | What is the dedupe window for JetStream? | 2 minutes, configured in jetstream.conf |
| 3 | Which transport(s) are in MVP? | JetStream only (webhooks/A2A post-MVP) |
| 4 | Where is the canonical list of external event contracts? | schemas/events/<ctx>/ + versioned JSON |
| 5 | Which events are external-facing vs internal-only? | x-sea-visibility annotation in envelope |
| 6 | “Replay from offset” workflow? | Deferred (post-MVP) |
| Risk | Likelihood | Impact | Mitigation Strategy |
|---|---|---|---|
| Incorrect subject versioning causes contract drift | Medium | High | Enforce naming rules + schema-lint checks for subjects. |
| Inbox table grows unbounded | Medium | Medium | Add retention policies + archiving strategy. |
| Event contract drift across transports | Medium | High | Single envelope schema + versioned subjects + contract tests. |
| Leaking sensitive provenance externally | Medium | High | Use SDS-030 payload modes and sensitivity rules; strip/aggregate by default. |
| Type | ID/Doc | Document |
|---|---|---|
| ADR | ADR-032 | docs/specs/shared/adr/032-nats-jetstream-messaging.md |
| ADR | ADR-033 | docs/specs/shared/adr/033-kernel-shell-architecture.md |
| ADR | ADR-011 | docs/specs/shared/adr/011-internal-federated-ledger.md |
| PRD | PRD-022 | docs/specs/shared/prd/022-cross-context-messaging.md |
| PRD | PRD-003 | docs/specs/shared/prd/003-internal-federated-ledger.md |
| SDS | SDS-047 | docs/specs/shared/sds/047-messaging-infrastructure.md |
| SDS | SDS-030 | docs/specs/shared/sds/030-semantic-observability.md |