## Goal Make `projection` and `aggregate` compatible to run behind the same gateway and against the same NATS JetStream cluster, with consistent shared types and operational conventions. ## Constraints - Keep both services independently deployable. - Preserve existing stream/subject conventions unless they are unsafe for multi-instance use. - Prefer backward-compatible changes in message formats (optional fields, tolerant decoding). - Keep changes minimal and verified by fmt/test/clippy. ## Compatibility Checklist ### JetStream / NATS - Stream name: `AGGREGATE_EVENTS` in both services. - Subject pattern: `tenant.*.aggregate.*.*` in both services. - Consumer durability: - Projection: stable durable name (or per-view derived durable). - Aggregate: avoid fixed durable names for ad-hoc fetch operations to prevent collisions across instances. ### Common Types - `TenantId`: identical newtype behavior across both codebases. - Event payload shape: - Aggregate publishes `types::Event` with `event_id`, `command_id`, `version`, etc. - Projection consumes an `EventEnvelope`; keep required fields stable and add optional fields to mirror aggregate where useful. ## Plan (Implementation Order) 1. Align projection’s event envelope schema to accept and (optionally) emit aggregate-compatible identifiers: - Add optional `event_id`, `command_id`, `version` fields. - Keep decoding tolerant with `#[serde(default)]`. - Avoid changing serialized output unless those fields are present. 2. Make aggregate’s JetStream fetch consumer safe for shared clusters: - Generate unique consumer names per fetch call (tenant + aggregate + uuid). - Use explicit ack policy. - Bound fetch loops by timeout/idle to avoid hanging. - Best-effort delete the consumer when done. 3. Enforce consistent “strict clippy” hygiene: - Remove trivial `assert!(true)` and other clippy warnings in aggregate so both crates can run `cargo clippy -- -D warnings`. 4. Verification: - `cargo fmt --check` - `cargo test` - `cargo clippy --all-targets -- -D warnings` ## Expected Outcomes - Both binaries can connect to the same JetStream cluster without consumer name collisions. - Projection can decode aggregate-published events and has access to event identifiers/versions when present. - Both repositories share the same strictness level for formatting and linting.