Entities¶
The Tech Strategy Tool's domain model consists of a hierarchy of strategy entities. This page documents each entity type, its fields, behaviors, and relationships.
Entity Hierarchy¶
graph TD
S[Strategy] --> T[Team]
T --> G[Group]
T --> P[Principle]
T --> O[Objective]
O --> I[Initiative]
O -.->|links to| P
O -.->|assigned to| G
All entities live within a single Strategy document held in memory by the event processor. There are no separate database tables for entities — the state is derived entirely from events.
Strategy¶
The root document containing all teams. There is exactly one Strategy instance in the system.
| Field | Type | Description |
|---|---|---|
| Teams | List<Team> |
Ordered list of all teams |
Team¶
A team represents an engineering group with its own strategy space. Teams are the top-level organizational unit.
| Field | Type | Description |
|---|---|---|
| Id | Guid |
Unique identifier |
| Name | string |
Display name |
| Color | string |
Hex color code (e.g., #3498db) used for UI theming |
| Principles | List<Principle> |
Ordered list of guiding principles |
| Objectives | List<Objective> |
Ordered list of measurable goals |
| Groups | List<Group> |
Ordered list of groups for organizing objectives |
Behaviors¶
- Color validation: The
Colorfield must be a valid 6-digit hex color code (e.g.,#3498db). The processor validates this on create and update. - Cascading delete: Deleting a team removes all of its groups, principles, objectives, and initiatives.
- Admin-only operations: Creating, renaming, recoloring, and deleting teams require admin role.
Group¶
A grouping mechanism for objectives within a team. Groups provide visual organization in the Objectives view.
| Field | Type | Description |
|---|---|---|
| Id | Guid |
Unique identifier |
| Name | string |
Display name |
| Description | string |
Optional description |
Behaviors¶
- Cascading ungroup: Deleting a group unassigns all objectives from it (they become ungrouped), but does not delete the objectives.
- Deferred creation: In the UI, clicking "Add Group" creates a local-only placeholder rendered with the name field in edit mode. The
create_groupevent is only submitted after the user provides a name. Pressing Escape or leaving the name empty discards the placeholder with no server interaction. - Reordering: Groups can be reordered within a team via
reorder_group.
Principle¶
A guiding belief or standard that a team follows. Principles represent the "why" behind technology decisions.
| Field | Type | Description |
|---|---|---|
| Id | Guid |
Unique identifier |
| Title | string |
Principle title (supports *highlight* syntax) |
| Description | string |
Detailed description |
Behaviors¶
- Highlight syntax: Principle titles support
*highlighted text*notation. Text between asterisks is rendered in the team color in the UI. - Cross-team assignment: Principles can be copied to other teams via
assign_principle_to_objective. This creates an independent copy — changes to one do not affect the other. - Cascading reference removal: Deleting a principle removes it from the
PrincipleIdslist of all objectives in the same team. - Deferred creation: In the UI, clicking "Add Principle" creates a local-only placeholder rendered with the title field in edit mode. The
create_principleevent is only submitted after the user provides a title. Pressing Escape or leaving the title empty discards the placeholder with no server interaction. - Conflict detection: Title and description edits support
lastSeenSequencefor concurrent edit detection.
Objective¶
A measurable goal aligned to one or more principles. Objectives track progress through their initiatives.
| Field | Type | Description |
|---|---|---|
| Id | Guid |
Unique identifier |
| Title | string |
Objective title |
| Description | string |
Detailed description |
| GroupId | Guid? |
Optional group assignment |
| PrincipleIds | List<Guid> |
IDs of linked principles |
| Initiatives | List<Initiative> |
Ordered list of initiatives |
Behaviors¶
- Group assignment: Objectives can be assigned to a group (
assign_objective_group). Unassigned objectives appear in an "Ungrouped" section. - Principle links: Objectives link to principles via
add_objective_principleandremove_objective_principle. These are references (not copies). - Progress aggregation: Total progress is computed from the average of all initiative progress values.
- Reordering: Objectives can be reordered within a group and moved between groups via
reorder_objective. - Cascading delete: Deleting an objective removes all of its initiatives.
- Deferred creation: In the UI, clicking "Add Objective" creates a local-only placeholder rendered with the title field in edit mode. The
create_objectiveevent is only submitted after the user provides a title. Pressing Escape or leaving the title empty discards the placeholder with no server interaction. - Conflict detection: Title and description edits support
lastSeenSequence.
Initiative¶
A concrete project or work item that drives progress on an objective.
| Field | Type | Description |
|---|---|---|
| Id | Guid |
Unique identifier |
| Name | string |
Initiative name |
| Progress | int |
Completion percentage (0-100) |
| JiraKey | string? |
Optional Jira issue key |
Behaviors¶
- Progress range: Progress must be between 0 and 100 inclusive.
- Deferred creation: In the UI, initiatives are created in a "pending" state — the
create_initiativeevent is only submitted after the user provides a name. - Reordering: Initiatives can be reordered within their objective via
reorder_initiative. - Conflict detection: Name edits support
lastSeenSequence.
Collections and Ordering¶
All collections in the domain model use List<T>, which preserves insertion order and supports insert-at-index operations. This is important for:
- Display order: Entities are displayed in their list order in the UI
- Reorder events:
reorder_objective,reorder_initiative, andreorder_groupevents specify a target index - Drag-and-drop: The UI allows users to reorder entities via drag-and-drop, which maps to reorder events
Field Limits¶
The processor enforces maximum lengths on all text fields:
| Field | Max Length |
|---|---|
| Team name | Defined in FieldLimits |
| Group name | Defined in FieldLimits |
| Group description | Defined in FieldLimits |
| Principle title | Defined in FieldLimits |
| Principle description | Defined in FieldLimits |
| Objective title | Defined in FieldLimits |
| Objective description | Defined in FieldLimits |
| Initiative name | Defined in FieldLimits |
| Jira key | Defined in FieldLimits |
These limits are enforced server-side in the event processor's validation helpers. The UI also sets maxlength attributes on input fields for user experience.
Model Classes¶
Domain model classes live in src/TechStrat.Core/Model/. They are plain C# classes with { get; set; } properties — mutable, since the event processor modifies them in-place during event processing.
These classes have no external dependencies and no behavior — they are pure data containers. All business logic lives in the EventProcessor.