Problem
Case_Timeline_Event in app/db_class/db.py currently has one required description field. The create/edit routes in app/case/case.py, core methods in app/case/CaseCore.py, and app/static/js/case/timeline_view.js use that field for both the concise event identity and any supporting detail.
The timeline form labels description as Description and renders it in a textarea. TimelineJS then uses the same value as both headline and body text. This encourages long summaries, duplicates content in the graphical view, and makes the event list harder to scan.
Analysts need two distinct concepts:
- Event: a short one-line statement, for example
Tartempion logged in.
- Additional Note: optional multiline context, for example evidence from Windows event 4624, the domain controller, session start, and affected host.
MISP import currently combines [MISP] <object name> and all attribute details into description, then parses that string in the frontend to derive a headline. Structured fields would remove this coupling for new imports.
Proposed approach
Keep the existing required DB and JSON field description for backward compatibility, but relabel it as Event in the UI and render it with a single-line text input. Renaming the stored/API field would break existing consumers and is not required for the requested user-facing terminology.
Add a nullable multiline additional_note field to Case_Timeline_Event through an Alembic migration. Include it in to_json(), core create/edit methods, and timeline request handling.
Creation behavior:
description remains required and represents the Event summary.
additional_note is optional and defaults to null or empty.
Edit behavior must distinguish an omitted additional_note key from an explicitly empty value. Omission by an older client preserves the existing note; an explicit empty or null value clears it.
Update app/static/js/case/timeline_view.js so forms use a one-line Event input and a multiline Additional Note textarea. The table displays separate Event and Additional Note content. TimelineJS uses Event as headline and Additional Note as body text without duplicating the headline when no note exists.
For new MISP imports, store the concise MISP object identity in description and attribute details in additional_note. Preserve existing imported rows without attempting a risky content-splitting migration.
Treat both fields as untrusted text. Fully escape text before adding line-break markup or sanitize the constructed TimelineJS HTML with the already-loaded DOMPurify. Rendering must not interpret analyst content as HTML.
This requires model, migration, core, route, serialization, frontend, tests, and documentation changes. No external dependency or deployment configuration change is required.
Scope
- Add nullable
additional_note storage to Case_Timeline_Event.
- Add Alembic upgrade and downgrade paths compatible with PostgreSQL and SQLite.
- Preserve
description as the required internal and JSON field for compatibility.
- Relabel Description as Event in timeline create/edit/list UI.
- Replace the Event textarea with a single-line input.
- Add optional multiline Additional Note controls for creation and editing.
- Serialize, create, update, preserve, and explicitly clear
additional_note.
- Render Event as TimelineJS headline and Additional Note as body content.
- Preserve multiline formatting while safely escaping or sanitizing both fields.
- Split new MISP imports into concise Event and detailed Additional Note values.
- Keep existing timeline rows unchanged; no heuristic backfill of old descriptions.
- Add automated backend tests for migration defaults, serialization, create/edit behavior, omission compatibility, explicit clearing, and MISP import.
- Add frontend regression coverage where supported; otherwise document focused manual verification of forms, table, TimelineJS, multiline display, and malicious markup.
- Update
doc/technical-specifications.md and relevant user documentation.
- Keep rich-text or Markdown editing, attachments, source records, arbitrary size limits, and API field renaming outside scope.
Acceptance criteria
- Create form shows required Event as a one-line input and optional Additional Note as a multiline textarea.
- An event can be created with
description: "Tartempion logged in" and a multiline additional_note.
- An event can be created without Additional Note.
- Edit form loads and saves both values.
- An edit request that omits
additional_note preserves its existing value for backward compatibility.
- An edit request with explicit null or empty
additional_note clears the note.
- Empty or whitespace-only Event remains rejected server-side.
- Non-string values for Event or Additional Note are rejected with a controlled client error and no partial update.
- Event table presents concise Event and Additional Note as distinct content.
- TimelineJS uses Event as headline and Additional Note as body, without repeating Event when no note exists.
- Line breaks in Additional Note remain visible.
- HTML and script payloads in either field render as inert text in both Vue and TimelineJS views.
- New MISP imports place object identity in Event and attribute details in Additional Note while preserving the MISP icon and linkage.
- Existing events remain readable and editable with
additional_note null after migration.
- Existing date parsing, sorting, normalized date display, event links, sources, deletion, and permissions remain unchanged.
- Automated tests cover required/optional values, old-client omission, explicit clearing, multiline serialization, MISP import, and XSS-safe rendering behavior.
- Migration upgrade preserves all existing descriptions. Downgrade behavior documents that newly stored Additional Notes are lost unless backed up first.
- Technical and user documentation use Event and Additional Note terminology consistently.
Dependencies
Problem
Case_Timeline_Eventinapp/db_class/db.pycurrently has one requireddescriptionfield. The create/edit routes inapp/case/case.py, core methods inapp/case/CaseCore.py, andapp/static/js/case/timeline_view.jsuse that field for both the concise event identity and any supporting detail.The timeline form labels
descriptionas Description and renders it in a textarea. TimelineJS then uses the same value as bothheadlineand body text. This encourages long summaries, duplicates content in the graphical view, and makes the event list harder to scan.Analysts need two distinct concepts:
Tartempion logged in.MISP import currently combines
[MISP] <object name>and all attribute details intodescription, then parses that string in the frontend to derive a headline. Structured fields would remove this coupling for new imports.Proposed approach
Keep the existing required DB and JSON field
descriptionfor backward compatibility, but relabel it as Event in the UI and render it with a single-line text input. Renaming the stored/API field would break existing consumers and is not required for the requested user-facing terminology.Add a nullable multiline
additional_notefield toCase_Timeline_Eventthrough an Alembic migration. Include it into_json(), core create/edit methods, and timeline request handling.Creation behavior:
descriptionremains required and represents the Event summary.additional_noteis optional and defaults to null or empty.Edit behavior must distinguish an omitted
additional_notekey from an explicitly empty value. Omission by an older client preserves the existing note; an explicit empty or null value clears it.Update
app/static/js/case/timeline_view.jsso forms use a one-line Event input and a multiline Additional Note textarea. The table displays separate Event and Additional Note content. TimelineJS uses Event asheadlineand Additional Note as body text without duplicating the headline when no note exists.For new MISP imports, store the concise MISP object identity in
descriptionand attribute details inadditional_note. Preserve existing imported rows without attempting a risky content-splitting migration.Treat both fields as untrusted text. Fully escape text before adding line-break markup or sanitize the constructed TimelineJS HTML with the already-loaded DOMPurify. Rendering must not interpret analyst content as HTML.
This requires model, migration, core, route, serialization, frontend, tests, and documentation changes. No external dependency or deployment configuration change is required.
Scope
additional_notestorage toCase_Timeline_Event.descriptionas the required internal and JSON field for compatibility.additional_note.doc/technical-specifications.mdand relevant user documentation.Acceptance criteria
description: "Tartempion logged in"and a multilineadditional_note.additional_notepreserves its existing value for backward compatibility.additional_noteclears the note.additional_notenull after migration.Dependencies