Organize all product strategy and domain modeling documentation into a dedicated .product-strategy directory for better separation from code. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
349 lines
12 KiB
Markdown
349 lines
12 KiB
Markdown
# Aether Product Strategy Chain
|
|
|
|
This directory contains the complete product strategy chain for Aether, from organizational values to executable work.
|
|
|
|
## The Chain (Product Strategy Framework)
|
|
|
|
```
|
|
Manifesto (Flowmade values)
|
|
↓ (constraints + outcomes)
|
|
vision.md (what Aether does)
|
|
↓ (events + decisions)
|
|
PROBLEM_MAP.md (problem space)
|
|
↓ (boundaries)
|
|
BOUNDED_CONTEXT_MAP.md (domain boundaries)
|
|
↓ (invariants)
|
|
Domain Models (not yet; next step)
|
|
↓ (system abilities)
|
|
Capabilities (not yet; next step)
|
|
↓ (user value)
|
|
Features (not yet; next step)
|
|
↓ (executable)
|
|
Issues (not yet; generated from features)
|
|
```
|
|
|
|
## Documents in This Repository
|
|
|
|
### 1. [vision.md](./vision.md)
|
|
**What:** Product vision statement
|
|
**Answers:**
|
|
- Who is Aether for? (Go teams building event-sourced systems; Flowmade internally)
|
|
- What pain does it solve? (Distributed event sourcing without heavyweight frameworks)
|
|
- What won't we do? (No opinionated multi-tenancy, no domain modeling, no UI)
|
|
|
|
**Output:** 1-page product promise
|
|
|
|
---
|
|
|
|
### 2. [PROBLEM_MAP.md](./PROBLEM_MAP.md)
|
|
**What:** Problem space analysis through developer journeys
|
|
**Covers:**
|
|
- 4 developer journeys (single-node, scaling, namespace isolation, concurrency)
|
|
- 25+ business events across domains
|
|
- 6 decision points with trade-offs
|
|
- 6 risk areas with expensive mistakes
|
|
- Code observations (intended vs actual implementation)
|
|
|
|
**Key Insight:** Don't start with DDD; first understand the problem from users' perspective
|
|
|
|
**Output:** Timeline of events, decisions, risks (no entities yet)
|
|
|
|
---
|
|
|
|
### 3. [BOUNDED_CONTEXT_MAP.md](./BOUNDED_CONTEXT_MAP.md)
|
|
**What:** Domain boundaries identified from problem space
|
|
**Contains:**
|
|
- 5 bounded contexts (Event Sourcing, Optimistic Concurrency, Namespace Isolation, Cluster Coordination, Event Bus)
|
|
- For each context:
|
|
- Purpose & core responsibility
|
|
- Ubiquitous language (domain vocabulary)
|
|
- Key entities & events
|
|
- Interfaces to other contexts
|
|
- Lifecycle patterns
|
|
- Current code locations
|
|
- Alignment with vision
|
|
- Gaps & observations
|
|
- Context relationships (producer/consumer, dependencies, orthogonal patterns)
|
|
- Boundary rules (language, lifecycle, ownership, scaling)
|
|
- Code alignment analysis (intended vs actual)
|
|
- Refactoring backlog
|
|
|
|
**Key Insight:** Boundaries cut by language differences, lifecycle differences, ownership, and scaling needs
|
|
|
|
**Output:** Clear domain boundaries; ready for aggregates & invariants
|
|
|
|
---
|
|
|
|
### 4. [CONTEXT_MAP_DIAGRAM.md](./CONTEXT_MAP_DIAGRAM.md)
|
|
**What:** Visual representation of bounded contexts
|
|
**Contains:**
|
|
- ASCII diagram of 5 contexts
|
|
- Single-node system interaction
|
|
- Multi-node cluster interaction
|
|
- Multi-tenant scenario
|
|
- Ownership matrix
|
|
- Lifecycle timelines (events, shards, subscriptions)
|
|
- Invariants per context
|
|
- Dependency summary
|
|
- Testing strategy
|
|
|
|
**Output:** Visual clarity; communication tool for team discussions
|
|
|
|
---
|
|
|
|
## Next Steps in Strategy Chain
|
|
|
|
### Step 4: Domain Models (per context)
|
|
**Goal:** Capture business invariants and define aggregates
|
|
|
|
**For each bounded context:**
|
|
1. Identify invariants ("what must never break?")
|
|
2. Define aggregates (clusters of entities that must be consistent)
|
|
3. Define commands (intent to change state)
|
|
4. Define events (facts that happened)
|
|
5. Define value objects (immutable, identity-less concepts)
|
|
6. Define read models (views optimized for queries)
|
|
|
|
**Example for Event Sourcing context:**
|
|
- Aggregate: ActorEventLog (root); contains Events
|
|
- Invariant: "Version must be strictly monotonic"
|
|
- Commands: SaveEvent (internal), ApplySnapshot
|
|
- Events: EventStored, VersionConflict, SnapshotCreated
|
|
- Value Objects: Version, EventType, Timestamp
|
|
|
|
**Deliverable:** Domain models document per context
|
|
|
|
---
|
|
|
|
### Step 5: Capabilities (system abilities)
|
|
**Goal:** Bridge domain thinking to roadmap thinking
|
|
|
|
**For each domain model:**
|
|
- "Store events durably with conflict detection" (Event Sourcing)
|
|
- "Detect concurrent writes and fail fast" (Optimistic Concurrency)
|
|
- "Isolate logical domains using namespace patterns" (Namespace Isolation)
|
|
- "Distribute actors across cluster nodes" (Cluster Coordination)
|
|
- "Route events to subscribers with filtering" (Event Bus)
|
|
|
|
**Rule:** Capabilities survive UI rewrites; they're about what the system CAN DO
|
|
|
|
**Deliverable:** Capability map
|
|
|
|
---
|
|
|
|
### Step 6: Features
|
|
**Goal:** Define user-visible value slices
|
|
|
|
**Process:**
|
|
1. What capability does this feature enable?
|
|
2. Who needs it? (user persona)
|
|
3. Why now? (market/business reason)
|
|
4. How do you demo it?
|
|
|
|
**Example features:**
|
|
- "Developer can save events to in-memory store for fast iteration"
|
|
- "Developer can scale single-node system to cluster without rewriting"
|
|
- "Operator can configure namespace prefixes for multi-tenant isolation"
|
|
- "Leader automatically elected on cluster formation"
|
|
- "Subscriber can filter events by type and actor pattern"
|
|
|
|
**Deliverable:** Feature list with business context
|
|
|
|
---
|
|
|
|
### Step 7: Issues (executable work)
|
|
**Goal:** Decompose features into implementable tasks
|
|
|
|
**Structure per issue:**
|
|
- User story: "As a [who], I want [what], so that [why]"
|
|
- Acceptance criteria: "Given [context], when [action], then [outcome]"
|
|
- Domain reference: Link to bounded context, aggregate, invariant
|
|
- Technical approach: What commands/events/queries involved
|
|
|
|
**Example issue:**
|
|
```
|
|
User Story: As a developer, I want to save events with automatic version conflict detection,
|
|
so that concurrent writes don't silently lose data.
|
|
|
|
Acceptance Criteria:
|
|
1. SaveEvent validates version > current latest
|
|
2. Returns VersionConflictError with ActorID, attempted, current versions
|
|
3. GetLatestVersion returns 0 for new actors
|
|
4. Conflict detection is fast (<1ms per write)
|
|
|
|
Linked to: Bounded Context: Event Sourcing
|
|
Aggregate: ActorEventLog
|
|
Invariant: Monotonic versions
|
|
Event: VersionConflict
|
|
```
|
|
|
|
**Deliverable:** GitHub issues with domain language
|
|
|
|
---
|
|
|
|
## How to Use This Chain
|
|
|
|
### For Technical Decisions
|
|
1. Read **vision.md** - What are we building? Why?
|
|
2. Read **PROBLEM_MAP.md** - What are users trying to do?
|
|
3. Read **BOUNDED_CONTEXT_MAP.md** - What are the boundaries?
|
|
4. Identify which context your decision touches
|
|
5. Check: Does it violate a context invariant?
|
|
|
|
### For New Contributors
|
|
1. Start with **vision.md** (2 min read)
|
|
2. Read the 4 journeys in **PROBLEM_MAP.md** (10 min)
|
|
3. Focus on relevant context in **BOUNDED_CONTEXT_MAP.md** (10 min)
|
|
4. Refer to **CONTEXT_MAP_DIAGRAM.md** when confused about interactions
|
|
|
|
### For Roadmap Planning
|
|
1. Current state: BOUNDED_CONTEXT_MAP.md identifies gaps
|
|
2. Define domain models per context (Step 4)
|
|
3. List capabilities (Step 5)
|
|
4. Prioritize features (Step 6)
|
|
5. Break into issues (Step 7)
|
|
|
|
### For Code Review
|
|
1. Does this code touch multiple bounded contexts?
|
|
- If yes: Are boundaries clear? Is translation happening at seam?
|
|
2. Does this change a context's invariant?
|
|
- If yes: Is new invariant documented?
|
|
3. Does this add new language (terms)?
|
|
- If yes: In which context? Is it consistent?
|
|
|
|
---
|
|
|
|
## Key Principles (from Vision)
|
|
|
|
### Primitives Over Frameworks
|
|
- Aether provides composition points (interfaces), not opinions
|
|
- Each context has clear boundaries; app wires them together
|
|
- Example: SaveEvent returns error; app decides retry strategy
|
|
|
|
### NATS-Native
|
|
- Built for JetStream from the start
|
|
- Event distribution, durability, and clustering all via NATS
|
|
- Not a bolted-on abstraction
|
|
|
|
### Resource Conscious
|
|
- Efficient on modest hardware
|
|
- ARM64 friendly
|
|
- No heavy dependencies
|
|
|
|
### Events as Complete History
|
|
- Events are source of truth
|
|
- State is derived by replay
|
|
- Audit trail is native
|
|
|
|
---
|
|
|
|
## Boundary Rules (Summary)
|
|
|
|
### Language Boundaries
|
|
Different terms → Different contexts. Example:
|
|
- "Event" in Event Sourcing = immutable fact
|
|
- "Event" in CQRS read models = notification of change
|
|
- These are different concepts; keep separate
|
|
|
|
### Lifecycle Boundaries
|
|
Different timescales → Different contexts. Example:
|
|
- Event lifetime: Create → Persist → Replay forever
|
|
- Shard lifetime: Assign → Migrate → Reassign
|
|
- These have different operations; different contexts
|
|
|
|
### Ownership Boundaries
|
|
Different owners → Different contexts. Example:
|
|
- Event Sourcing: App writes events; Library stores
|
|
- Cluster Coordination: Library manages; App doesn't directly control
|
|
- Each context has clear ownership
|
|
|
|
### Scaling Boundaries
|
|
Different performance needs → Different contexts. Example:
|
|
- Event Bus: Must be fast (us); non-blocking
|
|
- Cluster Coordination: Can be slow (seconds); eventual consistency OK
|
|
- Different scaling strategies
|
|
|
|
---
|
|
|
|
## How Bounded Contexts Emerged
|
|
|
|
### From Problem Space
|
|
1. **Event Sourcing journey** → Events are facts, versions matter, replay needed
|
|
2. **Scaling journey** → Cluster leadership, shard distribution needed
|
|
3. **Namespace journey** → Isolation patterns, wildcard risks
|
|
4. **Concurrency journey** → Version conflicts, retry strategy needed
|
|
5. **Distribution journey** → Event bus, cross-node routing needed
|
|
|
|
### Cut by Boundaries
|
|
- **Language**: Each journey uses different terms
|
|
- **Lifecycle**: Events persist forever; leases expire; subscriptions created/destroyed
|
|
- **Ownership**: App writes events; Library coordinates cluster; App filters subscriptions
|
|
- **Scaling**: Single actor scales by snapshots; cluster scales by shards; bus scales by subscribers
|
|
|
|
### Validated Against Code
|
|
- Each context has dedicated module(s)
|
|
- Code structure aligns with intended boundaries
|
|
- Gaps identified (actor migration, snapshot strategy, namespace validation)
|
|
|
|
---
|
|
|
|
## Anti-Patterns Avoided
|
|
|
|
| Anti-Pattern | What Aether Does Instead | Why |
|
|
|---|---|---|
|
|
| One big event model | Generic Event struct; domain language in strings | Primitives approach |
|
|
| Automatic retry on conflict | Return error to app | App owns retry strategy |
|
|
| Opinionated multi-tenancy | Namespace primitives; app defines semantics | Avoid framework opinions |
|
|
| Wildcard subscriptions default | Explicit namespace; wildcard opt-in with warnings | Security-first |
|
|
| Shared state across contexts | Events flow between contexts; each owns its data | Clean boundaries |
|
|
|
|
---
|
|
|
|
## Decision Gates
|
|
|
|
**After vision:** Can you crisply answer who/what/why?
|
|
- ✓ Aether: For Go teams; removes distributed complexity; no framework opinions
|
|
|
|
**After problem space:** Do you see events, not just CRUD?
|
|
- ✓ Aether: 25+ business events across 4 journeys; clear decisions and risks
|
|
|
|
**After contexts:** Are boundaries clear?
|
|
- ✓ Aether: 5 contexts with distinct language, lifecycle, ownership, scaling
|
|
|
|
**After domain models:** Does each aggregate enforce an invariant?
|
|
- → Next step (not yet done)
|
|
|
|
**After capabilities:** Can each capability be demoed?
|
|
- → Next step (not yet done)
|
|
|
|
**After features:** Does each feature move a capability?
|
|
- → Next step (not yet done)
|
|
|
|
---
|
|
|
|
## Related Documents
|
|
|
|
- **Organization Manifesto**: [flowmade-one/architecture/manifesto.md](https://git.flowmade.one/flowmade-one/architecture/src/branch/main/manifesto.md) - Who Flowmade is; what we believe
|
|
- **Repository Map**: [flowmade-one/architecture/repos.md](https://git.flowmade.one/flowmade-one/architecture/src/branch/main/repos.md) - How Aether fits in Flowmade ecosystem
|
|
- **README.md**: Quick start, setup, architecture
|
|
- **CLAUDE.md**: Development instructions for AI assistants
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Aether is at **Step 3 of the strategy chain: Bounded Contexts Identified**.
|
|
|
|
**What's done:**
|
|
- Vision: Clear product promise (primitives for distributed event sourcing)
|
|
- Problem space: 4 journeys, 25+ events, 6 decisions, 6 risks
|
|
- Bounded contexts: 5 contexts with clear boundaries; code aligns
|
|
|
|
**What's next:**
|
|
- Domain models: Define aggregates and invariants per context
|
|
- Capabilities: System abilities (what can developers do?)
|
|
- Features: User value slices (what's on the roadmap?)
|
|
- Issues: Executable work (what's the next sprint?)
|
|
|
|
**Team alignment:** Use BOUNDED_CONTEXT_MAP.md + CONTEXT_MAP_DIAGRAM.md to verify all stakeholders understand the domain boundaries before diving into implementation.
|