Skip to content

Event Types

The Tech Strategy Tool processes 29 event types across 5 entity categories plus 1 system event. All events are submitted via POST /api/events and processed by the event processor.

Quick Reference

Event Entity Description
create_team Team Create a new team
update_team_name Team Rename a team
update_team_color Team Change a team's color
delete_team Team Delete a team and all its contents
create_group Group Create a group within a team
update_group_name Group Rename a group
update_group_description Group Update a group's description
delete_group Group Delete a group (objectives become ungrouped)
reorder_group Group Change a group's position within its team
create_principle Principle Create a principle within a team
update_principle_title Principle Update a principle's title
update_principle_description Principle Update a principle's description
delete_principle Principle Delete a principle (removed from all objectives)
reorder_principle Principle Change a principle's position within its team
create_objective Objective Create an objective within a team
update_objective_title Objective Update an objective's title
assign_objective_to_group Objective Assign an objective to a group
remove_objective_from_group Objective Remove an objective from its group
assign_principle_to_objective Objective Link a principle to an objective
remove_principle_from_objective Objective Remove a principle link from an objective
delete_objective Objective Delete an objective and its initiatives
reorder_objective Objective Change an objective's position within its group
create_initiative Initiative Create an initiative within an objective
update_initiative_name Initiative Update an initiative's name
update_initiative_progress Initiative Set an initiative's completion percentage
set_initiative_jira_key Initiative Set or update the Jira issue key
remove_initiative_jira_key Initiative Clear the Jira issue key
delete_initiative Initiative Delete an initiative
reorder_initiative Initiative Change an initiative's position within its objective
restore_history System Restore the strategy to a previous point in time

Event Structure

Every event submission includes:

Field Type Description
eventType string One of the 29 event types listed below
targetId string (GUID) The entity being acted upon (see conventions below)
data object Key-value pairs specific to the event type
lastSeenSequence long (optional) For conflict detection on supported field edits

lastSeenSequence is a top-level field

lastSeenSequence is a top-level field on the SubmitEventRequest, not a key inside the data dictionary. It is only meaningful for the 7 event types that support conflict detection.

TargetId conventions

Event Category TargetId Meaning
Create events Parent entity ID (the team or objective that owns the new entity)
Update/delete events The entity being modified or deleted
create_team (not set — teams have no parent)
restore_history (not set)

For create events, the new entity's ID is always in data.id.

Field Limits

All text fields are validated server-side against maximum lengths. Exceeding a limit causes the event to be rejected.

Field Max Length
Team name 100
Team color 7 (# + 6 hex digits)
Group name 100
Group description 200
Principle title 300
Principle description 2000
Objective title 300
Initiative name 200
Jira issue key 50

Team Events

Team events require the admin role. Non-admin users receive a 403 response.

create_team

Creates a new team.

Data Field Required Description
id Yes GUID for the new team
name Yes Team display name (max 100)
color No Hex color code (e.g., #3498db). Defaults to #000000 if omitted

targetId is null — teams have no parent.

{
  "eventType": "create_team",
  "targetId": null,
  "data": {
    "id": "a1b2c3d4-...",
    "name": "Platform Team",
    "color": "#3498db"
  }
}

update_team_name

Updates a team's display name. No conflict detection.

Data Field Required Description
name Yes New team name (max 100)

update_team_color

Updates a team's color. Validated via regex ^#[0-9A-Fa-f]{6}$. No conflict detection.

Data Field Required Description
color Yes New hex color code (e.g., #3498db)

delete_team

Deletes a team and all of its contents (groups, principles, objectives, initiatives).

No data fields required. targetId is the team to delete.


Group Events

create_group

Creates a new group within a team.

Data Field Required Description
id Yes GUID for the new group
name Yes Group display name (max 100)

targetId is the parent team ID.

update_group_name

Updates a group's name. Supports conflict detection.

Data Field Required Description
name Yes New group name (max 100)

update_group_description

Updates a group's description. Supports conflict detection.

Data Field Required Description
description Yes New group description (max 200)

delete_group

Deletes a group. Objectives assigned to this group become ungrouped (they are not deleted).

No data fields required. targetId is the group to delete.

reorder_group

Changes the position of a group within its team.

Data Field Required Description
index Yes New zero-based target position (clamped to valid range)

No-op if the group is already at the requested position.


Principle Events

create_principle

Creates a new principle within a team.

Data Field Required Description
id Yes GUID for the new principle
title Yes Principle title (max 300, must be non-empty)
description No Principle description (max 2000)

targetId is the parent team ID.

update_principle_title

Updates a principle's title. Supports conflict detection. Titles support *highlight* syntax for emphasizing key terms in the team color.

Data Field Required Description
title Yes New title (max 300)

update_principle_description

Updates a principle's description. Supports conflict detection.

Data Field Required Description
description Yes New description (max 2000)

delete_principle

Deletes a principle and removes it from all objectives that reference it — across all teams. Emits cascade card-changed notifications for every affected objective.

No data fields required. targetId is the principle to delete.

reorder_principle

Changes the position of a principle within its owning team's list.

Data Field Required Description
index Yes New zero-based target position (clamped to valid range)

Objective Events

create_objective

Creates a new objective within a team.

Data Field Required Description
id Yes GUID for the new objective
title Yes Objective title (max 300, must be non-empty)
groupId No GUID of the group to place the objective in

targetId is the parent team ID. The objective is inserted at the end of the group's slice (or the ungrouped section if no groupId is provided).

update_objective_title

Updates an objective's title. Supports conflict detection.

Data Field Required Description
title Yes New title (max 300)

assign_objective_to_group

Assigns an objective to a group. The group must exist in the same team. The objective is relocated to the end of the target group's slice.

Data Field Required Description
groupId Yes GUID of the target group

remove_objective_from_group

Removes an objective from its current group, moving it to the ungrouped section.

No data fields required. targetId is the objective.

assign_principle_to_objective

Links a principle to an objective.

Data Field Required Description
principleId Yes GUID of the principle to link

targetId is the objective.

Cross-team decomposition

If the principle belongs to a different team than the objective, the processor decomposes this into 2 derived events:

  1. create_principle — creates a copy in the objective's team with title, description, and sourceTeamId in data
  2. assign_principle_to_objective — links the copy to the objective

Each derived event is stored separately in the event log. The sourceTeamId in the first derived event enables the entity history to show "Created principle (copied from 'Team Name')" for cross-team copies. For same-team principles, the assignment is direct with no decomposition.

remove_principle_from_objective

Removes a principle reference from an objective. The principle itself is not deleted.

Data Field Required Description
principleId Yes GUID of the principle to unlink

delete_objective

Deletes an objective and all of its initiatives.

No data fields required. targetId is the objective to delete.

reorder_objective

Changes the position of an objective within its current group's slice.

Data Field Required Description
index Yes New zero-based index within the group slice

Initiative Events

create_initiative

Creates a new initiative within an objective.

Data Field Required Description
id Yes GUID for the new initiative
name Yes Initiative name (max 200)

targetId is the parent objective ID.

update_initiative_name

Updates an initiative's name. Supports conflict detection.

Data Field Required Description
name Yes New initiative name (max 200)

update_initiative_progress

Updates an initiative's progress percentage. Supports conflict detection. The objective's total progress bar recalculates automatically.

Data Field Required Description
progress Yes Completion percentage (0-100 inclusive, integer)

set_initiative_jira_key

Sets or updates the Jira issue key for an initiative. No conflict detection.

Data Field Required Description
jiraKey Yes Jira issue key (e.g., PROJ-123, max 50)

remove_initiative_jira_key

Clears the Jira issue key from an initiative. No-op if the key is already null.

No data fields required. targetId is the initiative.

delete_initiative

Deletes an initiative.

No data fields required. targetId is the initiative to delete.

reorder_initiative

Changes the position of an initiative within its parent objective's initiative list.

Data Field Required Description
index Yes New zero-based index position

System Events

restore_history

Restores the system state to a previous point in time. Requires the admin role.

Data Field Required Description
restoreToSequence Yes Sequence number to restore to

targetId is null. This event is always recorded as applied in the log (it serves as a marker). The actual state restoration is handled by the API layer after the event is logged.

Conflict Detection

Seven field-edit event types support conflict detection via lastSeenSequence. The processor uses the HasConflict helper to compare the request's lastSeenSequence against the field's current sequence in the FieldSequences dictionary. If the field was modified since the client's last read, the event is rejected.

Event Type Field Checked
update_group_name name
update_group_description description
update_principle_title title
update_principle_description description
update_objective_title title
update_initiative_name name
update_initiative_progress progress

All other event types ignore lastSeenSequence even if provided.

On conflict rejection, the response includes:

Field Value
status "rejected"
rejectionReason Description of the conflict
conflictingServerValue The current server value the client is out of sync with

On successful application of a field-edit event, the response includes:

Field Value
status "applied"
previousValue The field's value before the change (for history)

See Conflict Resolution for the full design rationale and client-side handling.

No-Op Detection

All update events compare the new value against the current value (trimmed). If they are identical, the processor returns a no-op result — no event is persisted and no SSE notification is broadcast. The API returns "no_change" as the status.

Envelope Validation

Before reaching the event processor, the API layer validates the request envelope:

  • eventType must be non-empty and one of the 29 recognized types (from EventTypes.All)
  • targetId is required for all event types except create_team and restore_history (listed in EventTypes.NoTargetIdRequired)

Invalid envelopes receive a 400 Bad Request response. This is distinct from domain rejections (200 OK with status: "rejected"), which indicate valid requests rejected by business rules.