Back to Cybersecurity Incident Response

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

Cybersecurity Incident Response

[YourCompany.com] · IT Department · Prepared by FullSpec · [Today's Date]

This document is the primary technical reference for the FullSpec team building the Cybersecurity Incident Response automation. It contains the full current-state process map with bottleneck flags, specifications for each of the three agents, the end-to-end data flow trace, and the recommended build stack with estimated hours. The IT Manager's role in the automated flow is preserved at the containment decision step; everything before and after that step is handled by the automation platform.

01Process snapshot

Step
Name
Description
1
Receive and Read Alert
IT Manager reads the alert notification from Microsoft Defender and decides whether it warrants investigation. Time cost: 10 min.
2
Classify Alert Severity
Severity is assigned manually based on individual judgement with no standardised scoring rubric, introducing inconsistency at the earliest triage stage. Time cost: 15 min.
3
Pull Relevant Logs
Log data for the affected user or device is located manually, requiring login to multiple Microsoft 365 consoles. This is the single largest time sink in the early response window. Time cost: 25 min.
4
Open a Tracking Ticket
A Jira ticket is created by hand with fields populated from whatever details have been gathered at that point. Time cost: 10 min.
5
Notify Relevant Stakeholders
The IT Manager drafts and sends a Slack message to relevant team members or management. Time cost: 10 min.
6
Investigate and Contain Threat
The team investigates the alert, isolates affected accounts or devices, and applies initial containment steps based on experience. Time cost: 60 min.
7
Escalate to Senior Staff if Needed
A separate escalation message is sent to leadership or an external provider if the threat exceeds the IT Manager's authority. Time cost: 10 min.
8
Document Incident Details
The incident record is written in Notion from memory after containment, covering timeline, affected systems, and actions taken. Memory-based documentation introduces errors and gaps in the audit trail. Time cost: 30 min.
9
Update Ticket and Close
The Jira ticket is updated with resolution details and closed manually. Time cost: 10 min.
10
Send Post-Incident Summary
A Slack message is sent to stakeholders confirming resolution and any required follow-up actions. Time cost: 15 min.
Time cost summary: Total manual time per incident cycle is 195 minutes (3 hours 15 min). At 12 to 20 alerts per week requiring triage, this accounts for approximately 7 hours of IT Manager time per week. Steps 1 through 5 and 7 (the Triage Agent and Notification Agent) and steps 8 through 10 (the Incident Documentation Agent) are replaced by automation. Step 6 (Investigate and Contain Threat) and the human review gate remain with the IT Manager. Bottlenecks are at steps 2, 3, and 8: severity classification without a rubric, manual log retrieval across consoles, and post-incident documentation written from memory.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Triage Agent

Classifies incoming Microsoft Defender alerts against a standardised severity rubric and automatically pulls supporting log data from Microsoft 365 to give the IT Manager a complete, pre-populated picture before they review the ticket. The agent removes the two costliest bottlenecks in the current process: unguided severity judgement and manual log retrieval across multiple consoles. It creates the Jira incident ticket with severity tag, alert summary, affected asset, and attached log excerpts, so the IT Manager opens a ticket that is already investigation-ready. Estimated build time: 16 hours. Complexity: Complex.

Trigger
New alert received from Microsoft Defender via the Defender API (Security Alerts endpoint) or configured webhook.
Tools
Microsoft Defender, Microsoft 365, Jira
Replaces steps
Steps 1, 2, 3, and 4
Estimated build
16 hours | Complex
// Input
defender.alert {
  alert_id: string,
  alert_title: string,
  alert_category: string,          // e.g. 'Malware', 'Credential theft', 'Lateral movement'
  affected_user_upn: string,
  affected_device_id: string,
  alert_severity_raw: string,       // Defender's own severity label (pre-rubric)
  detected_at: ISO8601 timestamp,
  tenant_id: string
}

// Output
jira.ticket {
  project_key: 'SEC',
  issue_type: 'Incident',
  summary: '[{severity_tag}] {alert_title} — {affected_user_upn}',
  severity_tag: 'Critical' | 'High' | 'Medium' | 'Low',
  description: {alert_summary} + {log_excerpt_markdown},
  labels: [severity_tag],
  custom_field_defender_alert_id: alert_id,
  custom_field_affected_asset: affected_device_id,
  custom_field_detected_at: detected_at,
  attachments: [log_extract.json]
}

// Log pull from Microsoft 365
m365.audit_log_query {
  user_upn: affected_user_upn,
  device_id: affected_device_id,
  time_window_hours: 24,
  record_types: ['AzureActiveDirectory', 'Exchange', 'SharePoint', 'SecurityComplianceCenter']
}
  • Microsoft Defender API requires the SecurityEvents.Read.All and ThreatIndicators.Read.All application permissions in Azure AD. These must be granted by a Global Administrator before the build begins. Confirm this with the IT Manager before starting the Triage Agent build.
  • Microsoft 365 audit log access requires the Office 365 Management Activity API with the ActivityFeed.Read application permission, plus unified audit logging enabled in the Microsoft Purview compliance portal. Confirm unified audit logging is active before testing.
  • The severity rubric must be agreed and documented before the classification logic is coded. The rubric maps alert_category plus affected_asset_criticality to a four-point scale (Critical, High, Medium, Low). If the rubric is not signed off before build, the agent will default to Defender's native severity label as a fallback, which must be flagged in the ticket description.
  • Jira project key SEC must exist and the automation platform service account must have the Create Issues and Attach Files permissions in that project. Confirm Jira tier: the Standard plan or above is required for API access.
  • Deduplication: before creating a ticket, query Jira for open tickets with matching custom_field_defender_alert_id. If a match is found, update the existing ticket rather than creating a duplicate.
  • Log excerpt size must be capped at 1 MB per attachment to avoid Jira attachment limits. Truncate and note in the description if the raw extract exceeds this.
Notification Agent

Routes the incident notification to the correct Slack channel based on severity and, for Critical or High severity tickets, immediately escalates to the on-call responder via PagerDuty without waiting for a manual escalation decision. This agent eliminates the manual Slack drafting step and the separately triggered escalation step, reducing mean time to first notification from 15 to 45 minutes to under 2 minutes. The agent fires as soon as the Triage Agent creates the Jira ticket with a severity tag. Estimated build time: 10 hours. Complexity: Moderate.

Trigger
Jira ticket created in project SEC with a severity label set by the Triage Agent (webhook on Jira issue_created event).
Tools
Slack, PagerDuty
Replaces steps
Steps 5 and 7
Estimated build
10 hours | Moderate
// Input
jira.ticket {
  ticket_id: string,
  ticket_url: string,
  severity_tag: 'Critical' | 'High' | 'Medium' | 'Low',
  summary: string,
  affected_user_upn: string,
  detected_at: ISO8601 timestamp
}

// Output — all severity levels
slack.message {
  channel: '#it-incidents',         // or '#it-incidents-critical' for Critical
  text: ':red_circle: [{severity_tag}] {summary}',
  blocks: [
    { type: 'section', fields: [severity_tag, affected_user_upn, detected_at, ticket_url] }
  ]
}

// Output — Critical or High severity only
pagerduty.incident {
  service_id: '<SEC_ONCALL_SERVICE_ID>',
  title: '[{severity_tag}] {summary}',
  body: 'Jira: {ticket_url} | Asset: {affected_user_upn} | Detected: {detected_at}',
  urgency: 'high',
  escalation_policy_id: '<ESCALATION_POLICY_ID>'
}
  • Slack channel routing table must be confirmed before build: Critical alerts route to '#it-incidents-critical', High and Medium to '#it-incidents', and Low to '#it-alerts-low' (or suppressed if agreed with the IT Manager). These channel names must be confirmed as existing in the Slack workspace.
  • PagerDuty service_id and escalation_policy_id for the security on-call rotation must be provided before build. Confirm that the PagerDuty account is on the Professional plan or above to support API-triggered incidents.
  • The Slack integration must use a dedicated bot token (xoxb-) with the chat:write and chat:write.public OAuth scopes. A bot user named 'FullSpec Incident Bot' should be created and added to each target channel.
  • Fallback behaviour: if the PagerDuty API call fails for a Critical or High ticket, the agent must post a direct Slack message to the IT Manager's user ID as a fallback notification and log the PagerDuty failure to the error log table.
  • A Jira webhook must be configured in the Jira project settings to POST to the automation platform's inbound webhook URL on issue_created events filtered to project SEC.
Incident Documentation Agent

Compiles the full incident record in real time by pulling alert data, log excerpts, and all ticket updates from Jira into a structured Notion page as the incident progresses, then sends the post-incident summary to the Slack IT channel once the Jira ticket is resolved. This agent eliminates the highest-friction post-incident task: writing the report from memory. Because data is pulled from Jira at the point of resolution rather than reconstructed later, the Notion page is accurate, complete, and consistently formatted every time. Estimated build time: 12 hours. Complexity: Moderate.

Trigger
Jira ticket in project SEC updated with resolution details and transitioned to Done status (webhook on Jira issue_updated event, filtered to status_changed_to = 'Done').
Tools
Notion, Jira, Slack
Replaces steps
Steps 8, 9, and 10
Estimated build
12 hours | Moderate
// Input
jira.ticket_resolved {
  ticket_id: string,
  ticket_url: string,
  severity_tag: string,
  summary: string,
  description: string,
  affected_user_upn: string,
  affected_device_id: string,
  detected_at: ISO8601 timestamp,
  resolved_at: ISO8601 timestamp,
  resolution_notes: string,
  comments: [{ author: string, body: string, created_at: ISO8601 }],
  attachments: [{ filename: string, url: string }]
}

// Output — Notion page
notion.page {
  parent_database_id: '<INCIDENT_LOG_DATABASE_ID>',
  properties: {
    Title: '[{severity_tag}] {summary}',
    Severity: severity_tag,
    Status: 'Resolved',
    Detected: detected_at,
    Resolved: resolved_at,
    Affected_User: affected_user_upn,
    Jira_Ticket: ticket_url
  },
  content_blocks: [
    { heading: 'Incident Summary', text: description },
    { heading: 'Timeline', text: comments_formatted },
    { heading: 'Log Excerpts', text: log_excerpt_from_attachment },
    { heading: 'Resolution', text: resolution_notes },
    { heading: 'Actions Taken', text: parsed_from_comments }
  ]
}

// Output — post-incident Slack summary
slack.message {
  channel: '#it-incidents',
  text: ':white_check_mark: RESOLVED [{severity_tag}] {summary}',
  blocks: [
    { type: 'section', fields: [severity_tag, detected_at, resolved_at, affected_user_upn] },
    { type: 'actions', elements: [{ text: 'View Report', url: notion_page_url }] }
  ]
}
  • Notion integration requires an internal integration token with Insert content and Update content capabilities. The Notion incident log database must be shared with the integration before the agent is tested. Confirm the database ID with the IT Manager.
  • Notion database must have the following properties pre-created with correct types: Title (title), Severity (select: Critical/High/Medium/Low), Status (select: Open/In Progress/Resolved), Detected (date), Resolved (date), Affected_User (rich text), Jira_Ticket (url). The agent will fail silently if property names do not match exactly.
  • Jira comments are parsed in chronological order. The agent must handle empty comments arrays gracefully, inserting a 'No comments recorded' placeholder in the Timeline block rather than throwing an error.
  • The agent must fetch the log_extract.json attachment from the Jira ticket via the Jira attachment API before constructing the Notion page. If the attachment is unavailable, the Log Excerpts block should note 'Log attachment not retrievable' and continue.
  • A second Jira webhook must be configured on issue_updated events filtered to project SEC and status = 'Done'. Ensure this webhook does not overlap with the Notification Agent's issue_created webhook in a way that causes duplicate Slack messages on resolution.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow — Cybersecurity Incident Response automation
// ============================================================
// TRIGGER
// ============================================================
// Source: Microsoft Defender Security Alerts API
// Event:  New alert raised (alert_status = 'newAlert')
// Poll interval: 60 seconds OR webhook push if Defender webhook configured

defender.alert_payload {
  alert_id,
  alert_title,
  alert_category,
  affected_user_upn,
  affected_device_id,
  alert_severity_raw,
  detected_at,
  tenant_id
}

// ============================================================
// AGENT 1: TRIAGE AGENT
// ============================================================
// Step 1: Dedupe check — query Jira SEC project for open ticket
//         with custom_field_defender_alert_id = alert_id
//         IF match found -> update existing ticket, skip to AGENT 2
//         IF no match    -> continue

// Step 2: Severity classification via rubric lookup
//   Inputs: alert_category, affected_device_id, affected_user_upn
//   Rubric table: alert_category x asset_criticality -> severity_tag
//   severity_tag: 'Critical' | 'High' | 'Medium' | 'Low'
//   Fallback: if rubric returns no match -> use alert_severity_raw, flag in ticket

triage.classification {
  severity_tag,
  alert_summary,          // constructed from alert_title + affected_user_upn + detected_at
  rubric_match: boolean
}

// Step 3: Log retrieval from Microsoft 365
//   API: Office 365 Management Activity API
//   Query: affected_user_upn + affected_device_id, last 24 hours
//   Record types: AzureActiveDirectory, Exchange, SharePoint, SecurityComplianceCenter
//   Output: log_extract.json (capped at 1 MB)

m365.log_extract {
  raw_events: [...],
  extracted_at: ISO8601,
  truncated: boolean
}

// Step 4: Jira ticket creation
//   Project: SEC | Issue type: Incident
//   Fields: summary, severity_tag, description (alert_summary + log_excerpt_markdown),
//           custom_field_defender_alert_id, custom_field_affected_asset,
//           custom_field_detected_at, labels=[severity_tag]
//   Attachment: log_extract.json

jira.ticket_created {
  ticket_id,
  ticket_url,
  severity_tag,
  summary,
  detected_at,
  affected_user_upn
}

// ============================================================
// AGENT 1 -> AGENT 2 HANDOFF
// Trigger: Jira issue_created webhook fires on project SEC
// Payload passed: ticket_id, ticket_url, severity_tag, summary,
//                 affected_user_upn, detected_at
// ============================================================

// ============================================================
// AGENT 2: NOTIFICATION AGENT
// ============================================================
// Step 5: Slack channel routing
//   severity_tag = 'Critical'         -> #it-incidents-critical
//   severity_tag = 'High' | 'Medium'  -> #it-incidents
//   severity_tag = 'Low'              -> #it-alerts-low (or suppressed)

slack.message_sent {
  channel,
  severity_tag,
  summary,
  ticket_url,
  timestamp: ISO8601
}

// Step 6: Escalation decision
//   IF severity_tag IN ['Critical', 'High'] -> trigger PagerDuty
//   ELSE                                    -> no PagerDuty call

// Step 7: PagerDuty incident creation (Critical/High only)
//   service_id: SEC_ONCALL_SERVICE_ID
//   urgency: 'high'
//   escalation_policy_id: ESCALATION_POLICY_ID
//   Fallback on API failure: DM IT Manager Slack user ID + log error

pagerduty.incident_created {
  pd_incident_id,
  pd_incident_url,
  triggered_at: ISO8601
}

// ============================================================
// HUMAN GATE — IT MANAGER REVIEW (NOT AUTOMATED)
// IT Manager reviews Jira ticket + Slack notification.
// Confirms or overrides containment action in Jira.
// Adds resolution notes and comments to ticket.
// Transitions ticket to 'Done' on resolution.
// Estimated time: 20 min (post-automation, investigation only).
// ============================================================

// ============================================================
// AGENT 2 -> AGENT 3 HANDOFF
// Trigger: Jira issue_updated webhook fires on project SEC,
//          filtered to status_changed_to = 'Done'
// Payload passed: ticket_id, ticket_url, severity_tag, summary,
//                 description, affected_user_upn, affected_device_id,
//                 detected_at, resolved_at, resolution_notes,
//                 comments[], attachment_url (log_extract.json)
// ============================================================

// ============================================================
// AGENT 3: INCIDENT DOCUMENTATION AGENT
// ============================================================
// Step 8: Fetch Jira ticket full detail + comments + attachment
//   attachment: GET /rest/api/3/attachment/content/{attachment_id}
//   comments:   GET /rest/api/3/issue/{ticket_id}/comment

// Step 9: Create Notion page
//   Database: INCIDENT_LOG_DATABASE_ID
//   Properties: Title, Severity, Status='Resolved', Detected,
//               Resolved, Affected_User, Jira_Ticket
//   Content blocks: Incident Summary, Timeline, Log Excerpts,
//                   Resolution, Actions Taken

notion.page_created {
  notion_page_id,
  notion_page_url,
  created_at: ISO8601
}

// Step 10: Post-incident Slack summary
//   Channel: #it-incidents
//   Content: severity_tag, summary, detected_at, resolved_at,
//            affected_user_upn, notion_page_url (linked button)

slack.post_incident_summary_sent {
  channel: '#it-incidents',
  notion_page_url,
  timestamp: ISO8601
}

// ============================================================
// END OF AUTOMATED FLOW
// Complete audit trail: Jira ticket + Notion page + Slack thread
// ============================================================
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
One workflow per agent (three workflows total) within a single automation platform instance. All credentials stored in the platform's shared credential store. No credentials hardcoded in workflow nodes. A fourth utility workflow handles error logging writes to the Supabase error table.
Webhook configuration
Two inbound webhooks required in the automation platform. Webhook A: receives Jira issue_created events from project SEC (triggers Notification Agent). Webhook B: receives Jira issue_updated events from project SEC filtered to status_changed_to = 'Done' (triggers Incident Documentation Agent). Microsoft Defender alerts are polled on a 60-second interval via the Defender Security Alerts API unless Defender webhook push is available and configured in the tenant. All inbound webhook URLs must be registered in the respective tool's webhook settings before testing.
Templating approach
Slack message blocks use JSON block kit templates stored as workflow-level variables, parameterised with severity_tag, summary, ticket_url, and timestamps at runtime. Notion page content blocks are constructed via the Notion API append_block_children endpoint using a fixed block schema. The severity rubric is stored as a lookup table (JSON array) in a platform-level variable or a Supabase reference table so it can be updated without redeploying the workflow.
Error logging
All API call failures are caught with try/catch or equivalent error branch nodes and written to a Supabase table named 'incident_automation_errors' with columns: error_id (uuid), workflow_name (text), step_name (text), error_message (text), payload_snapshot (jsonb), occurred_at (timestamptz). On any write to this table, a Slack alert is posted to '#it-automation-errors' tagging the IT Manager. PagerDuty API failures for Critical or High alerts additionally trigger a direct Slack DM to the IT Manager as a secondary fallback.
Testing approach
All three agents are built and tested against sandbox or staging instances first. Microsoft Defender testing uses the Defender API test alert endpoint to inject synthetic alerts. Jira testing uses a dedicated SEC-TEST project that mirrors the production project schema. Notion testing uses a duplicate of the incident log database in a test workspace. PagerDuty testing uses the Events API v2 with a test service to verify escalation without paging on-call staff. Production webhooks are not activated until all three agents pass sandbox testing.
Credential store entries required
1. Microsoft Defender: Azure AD application client_id + client_secret + tenant_id (grant: SecurityEvents.Read.All, ThreatIndicators.Read.All). 2. Microsoft 365: Azure AD application client_id + client_secret + tenant_id (grant: ActivityFeed.Read). 3. Jira: API token + account email + base URL (e.g. https://[yourcompany].atlassian.net). 4. PagerDuty: REST API key + Events API v2 integration key for SEC_ONCALL_SERVICE_ID. 5. Slack: Bot OAuth token (xoxb-) with chat:write, chat:write.public, users:read scopes. 6. Notion: Internal integration token. 7. Supabase: Project URL + service role key (write access to incident_automation_errors table).
Estimated total build time
Triage Agent: 16 hours. Notification Agent: 10 hours. Incident Documentation Agent: 12 hours. End-to-end integration testing and production deployment: 10 hours. Total: 48 hours.
Critical pre-build confirmations: (1) Microsoft 365 Global Administrator must grant the Azure AD application permissions for both the Defender and M365 audit log APIs before any agent build begins. (2) The IT Manager must sign off the severity rubric document before the Triage Agent classification logic is coded. (3) Jira project SEC must exist with the custom fields and service account permissions confirmed. (4) Notion incident log database must be created with the exact property names and types listed in the Incident Documentation Agent spec before testing. Raise any blockers to support@gofullspec.com before proceeding.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Cybersecurity Incident Response.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Integration and API Spec
Technical · Developer
View
Test and QA Plan
Quality · Developer
View