Skip to content

Event Types

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

Entity creation, deletion, name/description updates, and reordering are handled by generic polymorphic events (create_entity, delete_entity, update_name, update_description, reorder_entity) that work across all entity types via the required targetType field.

EventCategoryDescription
create_entityGenericCreate any entity (team, group, principle, objective, initiative)
delete_entityGenericDelete any entity with cascading side effects
update_nameGenericRename any named entity
update_descriptionGenericUpdate the description of any described entity
reorder_entityGenericChange the position of any orderable entity
update_team_colorTeamChange a team’s color
assign_objective_to_groupObjectiveAssign an objective to a group
remove_objective_from_groupObjectiveRemove an objective from its group
assign_principle_to_objectiveObjectiveLink a principle to an objective
remove_principle_from_objectiveObjectiveRemove a principle link from an objective
update_initiative_progressInitiativeSet an initiative’s completion percentage
set_initiative_jira_keyInitiativeSet or update the Jira issue key
remove_initiative_jira_keyInitiativeClear the Jira issue key
restore_historySystemRestore the strategy to a previous point in time
import_teamSystemAudit marker for a bulk team import

Every event submission includes:

FieldTypeDescription
eventTypestringOne of the recognized event types listed above
targetIdstring (GUID)The entity being acted upon (see conventions below)
targetTypestringRequired for generic events: "Team", "Group", "Principle", "Objective", or "Initiative"
dataobjectKey-value pairs specific to the event type
lastSeenSequencelong (optional)For conflict detection on supported field edits
EventTargetId Meaning
create_entityParent entity ID (team ID for groups/principles/objectives; objective ID for initiatives); null for teams
All other eventsThe entity being modified or deleted
restore_history(not set)
import_team(not set — generated internally)

For create_entity, the new entity’s ID is always in data.id.

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

FieldMax Length
Team name100
Team color7 (# + 6 hex digits)
Group name100
Group description200
Principle name300
Principle description2000
Objective name300
Initiative name200
Jira issue key50

These five events work across all entity types. The targetType field is required and determines which entity kind the event applies to and which field limits are enforced.

Creates a new entity of any type. Requires the admin role when targetType is "Team".

FieldTypeDescription
targetTypestringRequired. "Team", "Group", "Principle", "Objective", or "Initiative"
targetIdGUIDParent entity ID (null for teams)
Data FieldRequiredDescription
idYesGUID for the new entity
nameYesDisplay name (max length depends on entity type)
descriptionNoDescription text (Groups, Principles, Objectives only)
colorNoHex color code for teams only (e.g., #3498db)
groupIdNoGroup assignment for objectives only

create_entity decomposes into multiple stored events: the create_entity itself plus a derived update_name event (and optionally update_description, update_team_color, and/or assign_objective_to_group). Each is stored separately in the event log.

{
"eventType": "create_entity",
"targetType": "Group",
"targetId": "<teamId>",
"data": {
"id": "a1b2c3d4-...",
"name": "Infrastructure",
"description": "Platform and tooling objectives"
}
}

Deletes any entity. Requires the admin role when targetType is "Team".

FieldTypeDescription
targetTypestringRequired. Entity type to delete
targetIdGUIDThe entity to delete

No data fields required.

Cascade effects:

  • Team: deletes all groups, principles, objectives, and initiatives
  • Group: objectives in the group are unassigned (not deleted); emits remove_objective_from_group + delete_entity as derived events
  • Principle: removed from all objectives that reference it; emits remove_principle_from_objective for each affected objective + delete_entity as derived events. Cascade card-changed notifications are emitted for affected objectives.
  • Objective: deletes all initiatives
  • Initiative: removed from parent objective

Renames any entity that implements INamedEntity (Team, Group, Principle, Objective, Initiative). Requires the admin role when targetType is "Team". Supports conflict detection.

FieldTypeDescription
targetTypestringRequired. Entity type being renamed
targetIdGUIDThe entity to rename
Data FieldRequiredDescription
nameYesNew name. Max length: Team/Group → 100, Objective/Principle → 300, Initiative → 200

Updates the description of any entity that implements IDescribedEntity (Group, Principle, Objective). Supports conflict detection.

FieldTypeDescription
targetTypestringRequired. Entity type being updated
targetIdGUIDThe entity to update
Data FieldRequiredDescription
descriptionYesNew description (may be empty to clear). Max length: Group → 200, Principle → 2000

Changes the position of any orderable entity (Group, Principle, Objective, Initiative). Teams cannot be reordered.

FieldTypeDescription
targetTypestringOptional. Entity type — inferred from entity if omitted
targetIdGUIDThe entity to reorder
Data FieldRequiredDescription
indexYesNew zero-based target position (clamped to valid range; must be a valid integer)

No-op if the entity is already at the requested position (after clamping).


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

Team creation and deletion are handled by create_entity / delete_entity with targetType: "Team".

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

Data FieldRequiredDescription
colorYesNew hex color code (e.g., #3498db)

targetId is the team to update.


Group creation, deletion, renaming, and reordering are handled by generic events with targetType: "Group".


Principle creation, deletion, renaming, description updates, and reordering are handled by generic events with targetType: "Principle".


Objective creation and deletion are handled by create_entity / delete_entity with targetType: "Objective".

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 FieldRequiredDescription
groupIdYesGUID of the target group

targetId is the objective.

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

No data fields required. targetId is the objective.

Links a principle to an objective.

Data FieldRequiredDescription
principleIdYesGUID of the principle to link

targetId is the objective.

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

Data FieldRequiredDescription
principleIdYesGUID of the principle to unlink

targetId is the objective.

Objective reordering is handled by reorder_entity with targetType: "Objective" (index is group-slice-relative).


Initiative creation and deletion are handled by create_entity / delete_entity with targetType: "Initiative".

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

Data FieldRequiredDescription
progressYesCompletion percentage (0-100 inclusive, integer)

targetId is the initiative.

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

Data FieldRequiredDescription
jiraKeyYesJira issue key (e.g., PROJ-123, max 50)

targetId is the initiative.

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

No data fields required. targetId is the initiative.

Initiative reordering is handled by reorder_entity with targetType: "Initiative".


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

Data FieldRequiredDescription
restoreToSequenceYesSequence 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.

An audit marker automatically inserted by POST /api/teams/import. This event is never submitted directly by clients — the import endpoint generates it internally.

Data FieldDescription
sourceTeamIdOriginal team ID from the export
sourceTeamNameOriginal team name from the export
exportedAtTimestamp when the export was created
eventCountNumber of events in the import batch

targetId is null. targetType is null.


Three 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 NameSequence, DescriptionSequence, or FieldSequences["progress"] on the entity. If the field was modified since the client’s last read, the event is rejected.

Event TypeField Checked
update_nameNameSequence on the target entity
update_descriptionDescriptionSequence on the target entity
update_initiative_progressprogress key in FieldSequences
update_team_colorcolor key in FieldSequences

All other event types ignore lastSeenSequence even if provided.

On conflict rejection, the response includes:

FieldValue
status"rejected"
rejectionReasonDescription of the conflict
conflictingServerValueThe current server value the client is out of sync with

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

FieldValue
status"applied"
previousValueThe field’s value before the change (for history)

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

All update events compare the new value against the current value (exact match). 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.

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

  • eventType must be non-empty and one of the recognized types (from EventTypes.All)
  • targetId is required for all event types except create_entity, restore_history, and import_team (listed in EventTypes.NoTargetIdRequired)
  • targetType is required for create_entity, delete_entity, update_name, and update_description; it is optional for reorder_entity (inferred from the entity if omitted)

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.