DEV Community

Alex Kane
Alex Kane

Posted on

n8n for AeroDefense SaaS Vendors: 5 Automations for ITAR, CMMC, FAA DO-178C, and MIL-STD Compliance

If you sell SaaS into the aerospace and defense market — to prime contractors, Tier 1 suppliers, satellite integrators, or defense electronics vendors — your customer agreements include compliance clauses your competitors have not automated yet. ITAR, CMMC Level 2/3, FAA DO-178C, MIL-STD-882E, and DFARS 252.204-7012 are not just customer requirements. They are your liability.

This article gives you five n8n workflows designed for AeroDefense SaaS platform operators. Each includes full import-ready JSON. Copy the JSON, paste into n8n, adapt the sheet IDs and Slack channels, and you have a compliance automation foundation most defense-adjacent SaaS companies do not have.


The Core Self-Hosting Argument for AeroDefense SaaS

Before the workflows: why self-hosted n8n specifically?

Requirement Zapier / Make Risk Self-Hosted n8n Solution
ITAR 22 CFR §120.50 — Deemed Export ITAR technical data routed through servers with non-US-person access = potential deemed export violation n8n on-prem / AWS GovCloud / Azure Government keeps controlled tech data inside authorized enclave
CMMC Level 2 — DFARS 252.204-7012 External CSO handling CUI is in-scope for CMMC assessment — Zapier/Make are not FedRAMP Moderate authorized Self-hosted n8n runs inside assessed boundary; no external CSO in-scope expansion
EAR 15 CFR §734.13 — Deemed Export Same logic as ITAR — ECCN-controlled technology data transiting third-party iPaaS = potential export without BIS license Self-hosted instance keeps ECCN data on authorized hardware
DFARS 252.204-7012 — CDI Audit Trail Zapier/Make do not provide git-versioned, tamper-evident audit trail for CDI incident response records Git-versioned n8n workflow JSON = immutable DFARS audit trail
NIST 800-171 §3.13.3 — CUI at Rest/Transit CUI flowing through Zapier = data protection outside your SPRS-assessed boundary CUI stays in-boundary; n8n webhook traffic terminates on your server

Workflow 1: AeroDefense Customer Onboarding Drip

What it does: Segments new customers (PRIME_DEFENSE_CONTRACTOR, TIER1_AEROSPACE_SUPPLIER, SPACE_SYSTEM_INTEGRATOR, DEFENSE_ELECTRONICS_VENDOR, DUAL_USE_TECH_VENDOR, SIMULATION_TRAINING_VENDOR, AERODEFENSE_STARTUP) on intake. Sets compliance flags (ITAR_USML_APPLICABLE, EAR_ECCN_CONTROLLED, CMMC_LEVEL_2_REQUIRED, CMMC_LEVEL_3_REQUIRED, FAA_DO178C_APPLICABLE, MIL_STD_882E_APPLICABLE, CLASSIFIED_CUI_HANDLER). Sends flag-specific onboarding emails at Day 0 / Day 3 / Day 7.

Why it matters: A PRIME_DEFENSE_CONTRACTOR onboarding email that mentions DFARS 252.204-7012 CDI handling and ITAR data perimeter architecture signals that your platform understands defense compliance. A generic 'Welcome to our SaaS' email signals the opposite — and costs you the renewal.

{"name": "AeroDefense Customer Onboarding Drip", "nodes": [{"id": "1", "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [250, 300], "parameters": {"path": "/aerodefense-customer", "httpMethod": "POST", "responseMode": "responseNode"}}, {"id": "2", "name": "Classify Customer", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [470, 300], "parameters": {"jsCode": "const d = $input.first().json;\nconst tier = d.contract_value_usd >= 5000000 ? 'PRIME_DEFENSE_CONTRACTOR'\n  : d.contract_value_usd >= 1000000 ? 'TIER1_AEROSPACE_SUPPLIER'\n  : d.business_type === 'space_integrator' ? 'SPACE_SYSTEM_INTEGRATOR'\n  : d.business_type === 'defense_electronics' ? 'DEFENSE_ELECTRONICS_VENDOR'\n  : d.revenue_usd >= 500000 ? 'DUAL_USE_TECH_VENDOR'\n  : d.business_type === 'simulation_training' ? 'SIMULATION_TRAINING_VENDOR'\n  : 'AERODEFENSE_STARTUP';\nconst flags = {\n  ITAR_USML_APPLICABLE: !!(d.usml_category || d.itar_registered),\n  EAR_ECCN_CONTROLLED: !!(d.eccn && d.eccn !== 'EAR99'),\n  CMMC_LEVEL_2_REQUIRED: !!(d.handles_cui || d.dfars_7012_obligated),\n  CMMC_LEVEL_3_REQUIRED: !!(d.classified_programs || d.dfars_7021_obligated),\n  FAA_DO178C_APPLICABLE: !!(d.airborne_software || d.do178c_required),\n  MIL_STD_882E_APPLICABLE: !!(d.mil_spec_contract || d.dod_prime_contractor),\n  CLASSIFIED_CUI_HANDLER: !!(d.cui_category || d.classified_system_access)\n};\nreturn [{ json: { ...d, tier, flags,\n  day0_subject: `Welcome to the platform, ${d.company_name} \u2014 your compliance setup guide`,\n  day3_subject: `${d.company_name}: integration checklist for your ${tier.replace(/_/g,' ').toLowerCase()} workflows`,\n  day7_subject: flags.ITAR_USML_APPLICABLE\n    ? `${d.company_name}: ITAR data flow architecture \u2014 keeping USML tech in your authorized enclave`\n    : flags.CMMC_LEVEL_2_REQUIRED\n    ? `${d.company_name}: CMMC Level 2 workflow audit trail \u2014 your DFARS 252.204-7012 checklist`\n    : `${d.company_name}: compliance automation quick wins for your team`\n}}];"}}, {"id": "3", "name": "Day 0 Welcome Email", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [690, 200], "parameters": {"operation": "send", "to": "={{ $json.contact_email }}", "subject": "={{ $json.day0_subject }}", "message": "Hi {{ $json.contact_name }},\n\nWelcome aboard. Your account is active.\n\nGiven your profile ({{ $json.tier.replace(/_/g, ' ') }}), here is what we recommend configuring first:\n\n{% if $json.flags.ITAR_USML_APPLICABLE %}\u2022 ITAR Data Perimeter: route all USML-controlled technical data through your on-premise n8n instance. Webhook endpoints should never forward controlled tech data to external services.\n\u2022 Authorization tracking: add your DSP-5 / TAA / MLA expiry dates to the ITAR Monitor sheet (link below).\n{% endif %}{% if $json.flags.CMMC_LEVEL_2_REQUIRED %}\u2022 CMMC Level 2 Audit Trail: enable workflow execution logging to Postgres. Each n8n run produces an immutable record satisfying NIST SP 800-171 \u00a73.3.1.\n\u2022 CUI Handling: confirm your n8n instance runs inside your assessed system boundary before connecting external APIs.\n{% endif %}{% if $json.flags.FAA_DO178C_APPLICABLE %}\u2022 DO-178C Traceability: link workflow versions to your software configuration management baseline. Git-versioned n8n JSON satisfies DO-178C \u00a711.16 lifecycle data.\n{% endif %}\n\nSetup guide: https://docs.example.com/aerodefense-onboarding\n\nBest,\nFlowKit Team"}}, {"id": "4", "name": "Log to Sheets", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [690, 400], "parameters": {"operation": "append", "documentId": "YOUR_SHEET_ID", "sheetName": "customers", "columns": {"mappingMode": "autoMapInputData"}}}, {"id": "5", "name": "Wait 3 Days", "type": "n8n-nodes-base.wait", "typeVersion": 1, "position": [900, 300], "parameters": {"amount": 3, "unit": "days"}}, {"id": "6", "name": "Day 3 Integration Tips", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [1110, 300], "parameters": {"operation": "send", "to": "={{ $json.contact_email }}", "subject": "={{ $json.day3_subject }}", "message": "Hi {{ $json.contact_name }},\n\nDay 3 check-in. A few integration patterns most {{ $json.tier.replace(/_/g,' ').toLowerCase() }} teams set up this week:\n\n1. **Export Authorization Webhook**: POST to /itar-auth-expiry from your contract management system \u2014 the ITAR Monitor workflow fires automatically when a DSP-5 approaches expiry.\n2. **CMMC Evidence Collection**: schedule a weekly Postgres snapshot of your workflow execution log as SOC 2 / CMMC evidence.\n3. **DFARS 72-Hour Clock**: wire the CDI Incident webhook to your SIEM so the 72-hour DoD CIO notification clock starts the moment an alert fires.\n\nNeed help? Reply to this email.\n\nFlowKit Team"}}, {"id": "7", "name": "Wait 4 Days", "type": "n8n-nodes-base.wait", "typeVersion": 1, "position": [1320, 300], "parameters": {"amount": 4, "unit": "days"}}, {"id": "8", "name": "Day 7 Compliance Guide", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [1530, 300], "parameters": {"operation": "send", "to": "={{ $json.contact_email }}", "subject": "={{ $json.day7_subject }}", "message": "Hi {{ $json.contact_name }},\n\nWeek 1 done. Compliance automation quick wins:\n\n\u2022 ITAR Monitor: running? Check that DSP-5 / TAA / MLA expiries are loaded into the ITAR Authorization sheet.\n\u2022 CMMC Deadline Tracker: add your C3PAO assessment date and DFARS annual review date. The tracker emails your compliance team 120/90/60/30/14 days out.\n\u2022 Incident Pipeline: test the ITAR_UNAUTHORIZED_DISCLOSURE webhook \u2014 confirm Slack #export-control and DDTC voluntary disclosure draft fire correctly.\n\nQuestions? Reply here.\n\nFlowKit Team"}}], "connections": {"Webhook": {"main": [[{"node": "Classify Customer", "type": "main", "index": 0}]]}, "Classify Customer": {"main": [[{"node": "Day 0 Welcome Email", "type": "main", "index": 0}, {"node": "Log to Sheets", "type": "main", "index": 0}]]}, "Day 0 Welcome Email": {"main": [[{"node": "Wait 3 Days", "type": "main", "index": 0}]]}, "Wait 3 Days": {"main": [[{"node": "Day 3 Integration Tips", "type": "main", "index": 0}]]}, "Day 3 Integration Tips": {"main": [[{"node": "Wait 4 Days", "type": "main", "index": 0}]]}, "Wait 4 Days": {"main": [[{"node": "Day 7 Compliance Guide", "type": "main", "index": 0}]]}}}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: ITAR / EAR Export Authorization Monitor

What it does: Reads a Google Sheet of ITAR/EAR authorizations (DSP-5 commercial export licenses, Technical Assistance Agreements, Manufacturing License Agreements, BIS export licenses). Calculates days to expiry. Routes by severity: EXPIRED → Slack #export-control critical alert + email with DDTC voluntary disclosure (22 CFR §127.12) language. CRITICAL (≤14d) → Slack + email auth owner. WARNING/NOTICE → Sheets log.

Why it matters: A single lapsed ITAR authorization carries a civil penalty of up to $1.3 million per violation under 22 CFR §127.10. Criminal penalties: $1 million + 20 years imprisonment (22 CFR §127.3). This workflow costs nothing to run and costs everything not to.

Authorization types tracked: DSP-5 (commercial export license), TAA (Technical Assistance Agreement — governs tech data sharing with foreign parties), MLA (Manufacturing License Agreement), ML (Manufacturing License), EAR BIS export license.

{"name": "ITAR/EAR Export Authorization Monitor", "nodes": [{"id": "1", "name": "Daily 7AM", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1, "position": [250, 300], "parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 7 * * *"}]}}}, {"id": "2", "name": "Get Auth Records", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [470, 300], "parameters": {"operation": "getAll", "documentId": "YOUR_SHEET_ID", "sheetName": "itar_authorizations", "options": {"returnAll": true}}}, {"id": "3", "name": "Classify Expiry", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [690, 300], "parameters": {"jsCode": "const today = new Date();\nreturn $input.all().map(item => {\n  const d = item.json;\n  const expiry = new Date(d.expiry_date);\n  const days = Math.ceil((expiry - today) / 86400000);\n  let severity, action;\n  if (days < 0) { severity = 'EXPIRED'; action = 'IMMEDIATE: authorization expired \u2014 exports halted'; }\n  else if (days <= 14) { severity = 'CRITICAL'; action = `CRITICAL: ${days}d to expiry \u2014 renew NOW. Civil penalty up to $1.3M/violation (22 CFR Part 127)`; }\n  else if (days <= 45) { severity = 'URGENT'; action = `URGENT: ${days}d to expiry`; }\n  else if (days <= 90) { severity = 'WARNING'; action = `WARNING: ${days}d to expiry`; }\n  else if (days <= 120) { severity = 'NOTICE'; action = `NOTICE: ${days}d to expiry`; }\n  else return null;\n  const reg_type = d.auth_type === 'DSP5' ? 'Commercial Export License (DSP-5)'\n    : d.auth_type === 'TAA' ? 'Technical Assistance Agreement (TAA)'\n    : d.auth_type === 'MLA' ? 'Manufacturing License Agreement (MLA)'\n    : d.auth_type === 'EAR_LICENSE' ? 'BIS Export License (EAR)'\n    : d.auth_type;\n  return { json: { ...d, severity, action, days_remaining: days, reg_type,\n    usml_note: d.usml_category ? `USML Cat ${d.usml_category} \u2014 State Dept DDTC jurisdiction` : '',\n    ear_note: d.eccn && d.eccn !== 'EAR99' ? `ECCN ${d.eccn} \u2014 BIS Commerce jurisdiction` : ''\n  }};\n}).filter(Boolean);"}}, {"id": "4", "name": "Route by Severity", "type": "n8n-nodes-base.switch", "typeVersion": 3, "position": [910, 300], "parameters": {"mode": "rules", "rules": {"values": [{"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "EXPIRED"}}, "outputIndex": 0}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "CRITICAL"}}, "outputIndex": 1}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "URGENT"}}, "outputIndex": 2}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "WARNING"}}, "outputIndex": 3}]}}}, {"id": "5", "name": "EXPIRED Alert", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [1130, 100], "parameters": {"channel": "#export-control", "text": "\ud83d\udea8 ITAR/EAR AUTHORIZATION EXPIRED\n*Auth*: {{ $json.auth_id }} ({{ $json.reg_type }})\n*Tech*: {{ $json.controlled_tech }} | *Destination*: {{ $json.destination_country }}\n*Expired*: {{ $json.expiry_date }}\n{{ $json.usml_note }}{{ $json.ear_note }}\n\u26a0\ufe0f All exports under this auth must stop immediately. Civil penalty: up to $1.3M/violation (22 CFR \u00a7127.10). Initiate voluntary disclosure review per 22 CFR \u00a7127.12."}}, {"id": "6", "name": "EXPIRED Email", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [1130, 220], "parameters": {"operation": "send", "to": "={{ $json.auth_owner_email }}", "cc": "export-control@yourcompany.com", "subject": "ITAR/EAR AUTHORIZATION EXPIRED \u2014 {{ $json.auth_id }} \u2014 ALL EXPORTS HALTED", "message": "AUTH {{ $json.auth_id }} ({{ $json.reg_type }}) expired {{ $json.expiry_date }}.\n\nAll controlled tech exports under this authorization must cease immediately.\n\nRequired actions:\n1. Halt all export activities covered by this auth\n2. Review 22 CFR \u00a7127.12 voluntary disclosure procedure\n3. Contact DDTC (USML) or BIS (EAR) to initiate renewal\n\nTech: {{ $json.controlled_tech }}\n{{ $json.usml_note }}\n{{ $json.ear_note }}\n\nExport Control Compliance System"}}, {"id": "7", "name": "CRITICAL Slack", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [1130, 380], "parameters": {"channel": "#export-control", "text": "\u26a0\ufe0f CRITICAL: ITAR/EAR Auth Expiring in {{ $json.days_remaining }} days\n*Auth*: {{ $json.auth_id }} \u2014 {{ $json.reg_type }}\n*Tech*: {{ $json.controlled_tech }} | *Country*: {{ $json.destination_country }}\n*Expiry*: {{ $json.expiry_date }}\n{{ $json.usml_note }}\n{{ $json.action }}"}}, {"id": "8", "name": "WARNING Sheets Log", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [1130, 560], "parameters": {"operation": "append", "documentId": "YOUR_SHEET_ID", "sheetName": "auth_alerts", "columns": {"mappingMode": "autoMapInputData"}}}], "connections": {"Daily 7AM": {"main": [[{"node": "Get Auth Records", "type": "main", "index": 0}]]}, "Get Auth Records": {"main": [[{"node": "Classify Expiry", "type": "main", "index": 0}]]}, "Classify Expiry": {"main": [[{"node": "Route by Severity", "type": "main", "index": 0}]]}, "Route by Severity": {"main": [[{"node": "EXPIRED Alert", "type": "main", "index": 0}, {"node": "EXPIRED Email", "type": "main", "index": 0}], [{"node": "CRITICAL Slack", "type": "main", "index": 0}], [{"node": "WARNING Sheets Log", "type": "main", "index": 0}], [{"node": "WARNING Sheets Log", "type": "main", "index": 0}]]}}}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: CMMC / DFARS / FAA DO-178C / MIL-STD Compliance Deadline Tracker

What it does: Monitors 12 deadline types daily (weekdays 8 AM). Routes OVERDUE items to Slack + email. CRITICAL/URGENT to Slack. WARNING/NOTICE to Sheets log.

12 deadline types:

  • CMMC_C3PAO_ASSESSMENT — CMMC Level 2 C3PAO third-party assessment (DFARS 252.204-7019)
  • CMMC_LEVEL3_ASSESSMENT — CMMC Level 3 DCSA government-led assessment (DFARS 252.204-7021)
  • DFARS_252_204_7012_ANNUAL — Annual CDI safeguarding review
  • NIST_800_171_SELF_ASSESSMENT — SPRS score update (DFARS 252.204-7020)
  • ITAR_DDTC_REGISTRATION — ITAR DDTC company registration renewal (22 CFR §122.3, 1–4 year cycle)
  • EAR_BIS_LICENSE_RENEWAL — BIS export license renewal (15 CFR §740)
  • FAA_DO178C_VALIDATION — FAA DO-178C software validation review (AC 20-115D)
  • MIL_STD_882E_HAZARD_ANALYSIS — System safety hazard analysis (MIL-STD-882E Task 202)
  • SECURITY_CLASSIFICATION_GUIDE — Annual SCG review
  • CUI_MARKING_AUDIT — CUI marking and handling audit (32 CFR §2002)
  • SOC2_TYPE2_RENEWAL — SOC 2 Type II audit renewal
  • ANNUAL_PENTEST — Annual penetration test (NIST SP 800-171 §3.11.2)
{"name": "CMMC / DFARS / FAA / MIL-STD Compliance Deadline Tracker", "nodes": [{"id": "1", "name": "Weekdays 8AM", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1, "position": [250, 300], "parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 8 * * 1-5"}]}}}, {"id": "2", "name": "Get Deadlines", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [470, 300], "parameters": {"operation": "getAll", "documentId": "YOUR_SHEET_ID", "sheetName": "compliance_deadlines", "options": {"returnAll": true}}}, {"id": "3", "name": "Classify Deadline", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [690, 300], "parameters": {"jsCode": "const today = new Date();\nconst deadlineLabels = {\n  CMMC_C3PAO_ASSESSMENT: 'CMMC Level 2 C3PAO Assessment \u2014 DFARS 252.204-7019',\n  CMMC_LEVEL3_ASSESSMENT: 'CMMC Level 3 Assessment \u2014 DFARS 252.204-7021 (DCSA)',\n  DFARS_252_204_7012_ANNUAL: 'DFARS 252.204-7012 Annual CDI Safeguarding Review',\n  NIST_800_171_SELF_ASSESSMENT: 'NIST SP 800-171 Self-Assessment \u2014 SPRS Score Update',\n  ITAR_DDTC_REGISTRATION: 'ITAR DDTC Registration Renewal \u2014 22 CFR \u00a7122.3 (1-4yr)',\n  EAR_BIS_LICENSE_RENEWAL: 'EAR BIS Export License Renewal \u2014 15 CFR \u00a7740',\n  FAA_DO178C_VALIDATION: 'FAA DO-178C Software Validation Review \u2014 AC 20-115D',\n  MIL_STD_882E_HAZARD_ANALYSIS: 'MIL-STD-882E System Safety Hazard Analysis \u2014 Task 202',\n  SECURITY_CLASSIFICATION_GUIDE: 'Security Classification Guide (SCG) Annual Review',\n  CUI_MARKING_AUDIT: 'CUI Marking & Handling Audit \u2014 32 CFR \u00a72002',\n  SOC2_TYPE2_RENEWAL: 'SOC 2 Type II Audit Renewal',\n  ANNUAL_PENTEST: 'Annual Penetration Test \u2014 NIST SP 800-171 \u00a73.11.2'\n};\nreturn $input.all().map(item => {\n  const d = item.json;\n  const due = new Date(d.due_date);\n  const days = Math.ceil((due - today) / 86400000);\n  let severity;\n  if (days < 0) severity = 'OVERDUE';\n  else if (days <= 7) severity = 'CRITICAL';\n  else if (days <= 21) severity = 'URGENT';\n  else if (days <= 45) severity = 'WARNING';\n  else if (days <= 60) severity = 'NOTICE';\n  else return null;\n  return { json: { ...d, severity, days_to_due: days,\n    label: deadlineLabels[d.deadline_type] || d.deadline_type }};\n}).filter(Boolean);"}}, {"id": "4", "name": "Route Severity", "type": "n8n-nodes-base.switch", "typeVersion": 3, "position": [910, 300], "parameters": {"mode": "rules", "rules": {"values": [{"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "OVERDUE"}}, "outputIndex": 0}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "CRITICAL"}}, "outputIndex": 1}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "URGENT"}}, "outputIndex": 2}, {"conditions": {"options": {"leftValue": "={{ $json.severity }}", "operation": "equals", "rightValue": "WARNING"}}, "outputIndex": 3}]}}}, {"id": "5", "name": "OVERDUE Slack", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [1130, 100], "parameters": {"channel": "#compliance-ops", "text": "\ud83d\udea8 OVERDUE: {{ $json.label }}\n*Owner*: {{ $json.owner }} | *Due*: {{ $json.due_date }} ({{ Math.abs($json.days_to_due) }}d overdue)\n*Contract*: {{ $json.contract_ref }}\nImmediate escalation required \u2014 DFARS/ITAR non-compliance risk."}}, {"id": "6", "name": "OVERDUE Email", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [1130, 220], "parameters": {"operation": "send", "to": "={{ $json.owner_email }}", "cc": "compliance@yourcompany.com", "subject": "OVERDUE COMPLIANCE DEADLINE \u2014 {{ $json.label }}", "message": "This compliance deadline is {{ Math.abs($json.days_to_due) }} days overdue.\n\n{{ $json.label }}\nDue: {{ $json.due_date }}\nContract: {{ $json.contract_ref }}\n\nImmediate action required. Non-compliance with DFARS/ITAR requirements can result in contract termination, debarment, or civil/criminal penalties.\n\nCompliance Automation System"}}, {"id": "7", "name": "URGENT Slack", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [1130, 380], "parameters": {"channel": "#compliance-ops", "text": "\u26a0\ufe0f {{ $json.severity }}: {{ $json.label }}\n*Due*: {{ $json.due_date }} ({{ $json.days_to_due }}d)\n*Owner*: {{ $json.owner }} | *Contract*: {{ $json.contract_ref }}"}}, {"id": "8", "name": "WARNING Sheets Log", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [1130, 560], "parameters": {"operation": "append", "documentId": "YOUR_SHEET_ID", "sheetName": "deadline_alerts", "columns": {"mappingMode": "autoMapInputData"}}}], "connections": {"Weekdays 8AM": {"main": [[{"node": "Get Deadlines", "type": "main", "index": 0}]]}, "Get Deadlines": {"main": [[{"node": "Classify Deadline", "type": "main", "index": 0}]]}, "Classify Deadline": {"main": [[{"node": "Route Severity", "type": "main", "index": 0}]]}, "Route Severity": {"main": [[{"node": "OVERDUE Slack", "type": "main", "index": 0}, {"node": "OVERDUE Email", "type": "main", "index": 0}], [{"node": "URGENT Slack", "type": "main", "index": 0}], [{"node": "URGENT Slack", "type": "main", "index": 0}], [{"node": "WARNING Sheets Log", "type": "main", "index": 0}]]}}}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: ITAR / CMMC Security Incident & DFARS 72-Hour Alert Pipeline

What it does: Webhook-triggered incident pipeline. Classifies 8 incident types, calculates notification deadline, fires Slack alert, routes ITAR/EAR incidents to export control counsel with DDTC voluntary disclosure language, routes CDI/CUI incidents to CISO with DFARS 72-hour clock language, writes Postgres audit trail.

8 incident types:

  • CDI_EXFILTRATION — 72h clock: DoD CIO + FBI Cyber Division (DFARS 252.204-7012 §3(c)(1)(ii))
  • ITAR_UNAUTHORIZED_DISCLOSURE — Immediate: State Dept DDTC voluntary disclosure (22 CFR §127.12)
  • CUI_UNAUTHORIZED_ACCESS — 72h clock: Cognizant Security Authority (NIST 800-171 §3.6.2)
  • CMMC_CONTROL_FAILURE — 96h: Contracting Officer notification + POAM (DFARS 252.204-7019)
  • CLASSIFIED_SPILL — 1h: ISSM + DISA/NSA per Classification Authority
  • MIL_SPEC_SAFETY_DEFECT — 24h: Contracting Officer + MIL-STD-882E Task 202 review board
  • SUPPLY_CHAIN_COMPROMISE — 72h: Contracting Officer + DCSA (DFARS 252.239-7010)
  • EAR_DEEMED_EXPORT_INCIDENT — Immediate: BIS voluntary self-disclosure (15 CFR §764.5)
{"name": "ITAR/CMMC Security Incident & DFARS 72-Hour Alert Pipeline", "nodes": [{"id": "1", "name": "Incident Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [250, 300], "parameters": {"path": "/aerodefense-incident", "httpMethod": "POST", "responseMode": "responseNode"}}, {"id": "2", "name": "Classify Incident", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [470, 300], "parameters": {"jsCode": "const d = $input.first().json;\nconst ts = new Date().toISOString();\nconst configs = {\n  CDI_EXFILTRATION: { hours: 72, authority: 'DoD CIO + FBI Cyber Division (DFARS 252.204-7012 \u00a73(c)(1)(ii))', severity: 'CRITICAL', channel: '#security-ops', itar_flag: false },\n  ITAR_UNAUTHORIZED_DISCLOSURE: { hours: 0, authority: 'State Dept DDTC \u2014 Voluntary Disclosure (22 CFR \u00a7127.12)', severity: 'CRITICAL', channel: '#export-control', itar_flag: true },\n  CUI_UNAUTHORIZED_ACCESS: { hours: 72, authority: 'Cognizant Security Authority (NIST 800-171 \u00a73.6.2)', severity: 'HIGH', channel: '#security-ops', itar_flag: false },\n  CMMC_CONTROL_FAILURE: { hours: 96, authority: 'Contracting Officer \u2014 POAM required (DFARS 252.204-7019)', severity: 'HIGH', channel: '#compliance-ops', itar_flag: false },\n  CLASSIFIED_SPILL: { hours: 1, authority: 'ISSM + DISA/NSA per Classification Authority guidance', severity: 'CRITICAL', channel: '#security-ops', itar_flag: false },\n  MIL_SPEC_SAFETY_DEFECT: { hours: 24, authority: 'Contracting Officer + MIL-STD-882E Task 202 review board', severity: 'HIGH', channel: '#engineering-ops', itar_flag: false },\n  SUPPLY_CHAIN_COMPROMISE: { hours: 72, authority: 'Contracting Officer + DCSA (DFARS 252.239-7010)', severity: 'CRITICAL', channel: '#security-ops', itar_flag: false },\n  EAR_DEEMED_EXPORT_INCIDENT: { hours: 0, authority: 'BIS Voluntary Self-Disclosure (15 CFR \u00a7764.5)', severity: 'HIGH', channel: '#export-control', itar_flag: true }\n};\nconst cfg = configs[d.incident_type] || { hours: 72, authority: 'Compliance team', severity: 'MEDIUM', channel: '#security-ops', itar_flag: false };\nconst deadline_ts = cfg.hours > 0 ? new Date(new Date(ts).getTime() + cfg.hours * 3600000).toISOString() : null;\nreturn [{ json: { ...d, ts, ...cfg,\n  deadline_ts,\n  deadline_label: cfg.hours > 0 ? `${cfg.hours}h notification deadline: ${deadline_ts}` : 'Immediate voluntary disclosure recommended',\n  incident_label: d.incident_type.replace(/_/g, ' ')\n}}];"}}, {"id": "3", "name": "Slack Alert", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [690, 200], "parameters": {"channel": "={{ $json.channel }}", "text": "\ud83d\udea8 {{ $json.severity }} SECURITY INCIDENT\n*Type*: {{ $json.incident_label }}\n*System*: {{ $json.affected_system }}\n*Detected*: {{ $json.ts }}\n*Authority*: {{ $json.authority }}\n*Clock*: {{ $json.deadline_label }}\n*Reporter*: {{ $json.reporter }}"}}, {"id": "4", "name": "ITAR/EAR Branch", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [690, 400], "parameters": {"conditions": {"options": {"leftValue": "={{ $json.itar_flag }}", "operation": "equals", "rightValue": true}}}}, {"id": "5", "name": "ITAR Disclosure Email", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [910, 300], "parameters": {"operation": "send", "to": "export-control@yourcompany.com", "cc": "legal@yourcompany.com", "subject": "ITAR/EAR INCIDENT \u2014 VOLUNTARY DISCLOSURE REVIEW REQUIRED \u2014 {{ $json.incident_label }}", "message": "Incident Type: {{ $json.incident_label }}\nDetected: {{ $json.ts }}\nAffected System: {{ $json.affected_system }}\nPotential Jurisdiction: {{ $json.authority }}\n\nRequired actions:\n1. Export Control Counsel review within 24 hours\n2. Assess 22 CFR \u00a7127.12 voluntary disclosure eligibility (ITAR) or 15 CFR \u00a7764.5 (EAR)\n3. Preserve all logs and communications \u2014 do not delete\n4. Brief CISO and General Counsel\n\nVoluntary disclosure can significantly mitigate civil/criminal penalties.\n\nCivil penalty: up to $1.3M/violation (ITAR) or $1M/violation (EAR)\nCriminal: up to $1M and 20 years imprisonment (ITAR \u00a7127.3)\n\nExport Compliance Automation System"}}, {"id": "6", "name": "DFARS Notification Email", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [910, 500], "parameters": {"operation": "send", "to": "ciso@yourcompany.com", "cc": "compliance@yourcompany.com", "subject": "{{ $json.severity }} INCIDENT \u2014 {{ $json.incident_label }} \u2014 {{ $json.deadline_label }}", "message": "Incident: {{ $json.incident_label }}\nDetected: {{ $json.ts }}\nAffected System: {{ $json.affected_system }}\nAuthority: {{ $json.authority }}\nNotification Deadline: {{ $json.deadline_ts }}\n\nDFARS 252.204-7012 \u00a73(c)(1)(ii) requires reporting to DoD CIO (dibnet.dod.mil) and FBI Cyber Division within 72 hours of CDI incident discovery.\n\nSecure the system, preserve evidence, initiate IR plan.\n\nSecurity Automation System"}}, {"id": "7", "name": "Postgres Audit Trail", "type": "n8n-nodes-base.postgres", "typeVersion": 2, "position": [1130, 400], "parameters": {"operation": "executeQuery", "query": "INSERT INTO security_incidents (incident_type, affected_system, reporter, detected_ts, deadline_ts, authority, severity, itar_flag, created_at) VALUES ('{{ $json.incident_type }}', '{{ $json.affected_system }}', '{{ $json.reporter }}', '{{ $json.ts }}', '{{ $json.deadline_ts }}', '{{ $json.authority }}', '{{ $json.severity }}', {{ $json.itar_flag }}, NOW()) ON CONFLICT DO NOTHING;"}}], "connections": {"Incident Webhook": {"main": [[{"node": "Classify Incident", "type": "main", "index": 0}]]}, "Classify Incident": {"main": [[{"node": "Slack Alert", "type": "main", "index": 0}, {"node": "ITAR/EAR Branch", "type": "main", "index": 0}]]}, "ITAR/EAR Branch": {"main": [[{"node": "ITAR Disclosure Email", "type": "main", "index": 0}, {"node": "Postgres Audit Trail", "type": "main", "index": 0}], [{"node": "DFARS Notification Email", "type": "main", "index": 0}, {"node": "Postgres Audit Trail", "type": "main", "index": 0}]]}}}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly AeroDefense Platform KPI Dashboard

What it does: Every Monday 8 AM, pulls platform metrics and compliance events from Sheets, builds an HTML KPI table segmented by customer tier (Prime / Tier 1 / Startup+Dual-Use), surfaces ITAR/CDI open incidents, CMMC findings, and export authorizations expiring in ≤30 days. Emails CEO with CISO BCC and posts Slack summary to #management.

Why CISO BCC is intentional: This closes the governance gap in most AeroDefense SaaS companies where the CISO only sees security incidents, not the MRR exposure from compliance-gated accounts. When a PRIME_DEFENSE_CONTRACTOR account has an open CDI incident and $500K MRR, both the CEO and CISO need that fact in the same email.

{"name": "Weekly AeroDefense Platform KPI Dashboard", "nodes": [{"id": "1", "name": "Monday 8AM", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1, "position": [250, 300], "parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 8 * * 1"}]}}}, {"id": "2", "name": "Get Platform Metrics", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [470, 300], "parameters": {"operation": "getAll", "documentId": "YOUR_SHEET_ID", "sheetName": "platform_metrics", "options": {"returnAll": true}}}, {"id": "3", "name": "Get Compliance Events", "type": "n8n-nodes-base.googleSheets", "typeVersion": 4, "position": [470, 500], "parameters": {"operation": "getAll", "documentId": "YOUR_SHEET_ID", "sheetName": "compliance_events", "options": {"returnAll": true}}}, {"id": "4", "name": "Build KPI Report", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [690, 400], "parameters": {"jsCode": "const metrics = $('Get Platform Metrics').all().map(i => i.json);\nconst events = $('Get Compliance Events').all().map(i => i.json);\nconst thisWeek = new Date(); thisWeek.setDate(thisWeek.getDate() - 7);\nconst m = metrics[0] || {};\nconst mrrTotal = (m.mrr_prime || 0) + (m.mrr_tier1 || 0) + (m.mrr_startup || 0) + (m.mrr_dual_use || 0);\nconst mrrWoW = m.mrr_prev_week > 0 ? (((mrrTotal - m.mrr_prev_week) / m.mrr_prev_week) * 100).toFixed(1) : 'N/A';\nconst recentEvents = events.filter(e => new Date(e.event_ts) >= thisWeek);\nconst itarOpen = recentEvents.filter(e => e.incident_type && e.incident_type.includes('ITAR') && e.status !== 'CLOSED').length;\nconst cdiOpen = recentEvents.filter(e => e.incident_type === 'CDI_EXFILTRATION' && e.status !== 'CLOSED').length;\nconst cmmcFindings = recentEvents.filter(e => e.incident_type === 'CMMC_CONTROL_FAILURE').length;\nconst authExpiring = events.filter(e => e.type === 'auth_expiry' && e.days_remaining <= 30).length;\nconst mrrFlag = parseFloat(mrrWoW) < -5 ? '\u26a0\ufe0f' : '';\nconst secFlag = (itarOpen + cdiOpen) > 0 ? '\ud83d\udea8' : '';\nconst html = '<h2>AeroDefense SaaS Platform \u2014 Weekly KPI</h2>' +\n  '<table border=\"1\" cellpadding=\"8\" style=\"border-collapse:collapse\"><tr><th>Metric</th><th>Value</th><th>WoW</th></tr>' +\n  '<tr><td>Total MRR</td><td>$' + mrrTotal.toLocaleString() + '</td><td>' + mrrWoW + '% ' + mrrFlag + '</td></tr>' +\n  '<tr><td>MRR \u2014 Prime Contractors</td><td>$' + (m.mrr_prime||0).toLocaleString() + '</td><td></td></tr>' +\n  '<tr><td>MRR \u2014 Tier 1 Suppliers</td><td>$' + (m.mrr_tier1||0).toLocaleString() + '</td><td></td></tr>' +\n  '<tr><td>MRR \u2014 Startups / Dual-Use</td><td>$' + ((m.mrr_startup||0)+(m.mrr_dual_use||0)).toLocaleString() + '</td><td></td></tr>' +\n  '<tr><td>ITAR Incidents Open ' + secFlag + '</td><td>' + itarOpen + '</td><td></td></tr>' +\n  '<tr><td>CDI Incidents Open ' + secFlag + '</td><td>' + cdiOpen + '</td><td></td></tr>' +\n  '<tr><td>CMMC Control Findings</td><td>' + cmmcFindings + '</td><td></td></tr>' +\n  '<tr><td>Export Auths Expiring \u226430d</td><td>' + authExpiring + '</td><td></td></tr>' +\n  '<tr><td>Active Accounts</td><td>' + (m.active_accounts||0) + '</td><td></td></tr>' +\n  '<tr><td>New Trials This Week</td><td>' + (m.new_trials||0) + '</td><td></td></tr>' +\n  '</table>';\nconst slack_msg = 'AeroDefense Weekly: MRR $' + mrrTotal.toLocaleString() + ' (' + mrrWoW + '% WoW) ' + mrrFlag +\n  ' | ITAR Open: ' + itarOpen + ' ' + secFlag +\n  ' | CDI Open: ' + cdiOpen +\n  ' | CMMC Findings: ' + cmmcFindings +\n  ' | Auth Expiring \u226430d: ' + authExpiring;\nreturn [{ json: { html, slack_msg, mrrTotal, itarOpen, cdiOpen, cmmcFindings, authExpiring }}];"}}, {"id": "5", "name": "Email CEO + CISO", "type": "n8n-nodes-base.gmail", "typeVersion": 2, "position": [910, 300], "parameters": {"operation": "send", "to": "ceo@yourcompany.com", "bcc": "ciso@yourcompany.com", "subject": "AeroDefense Weekly KPI \u2014 {{ new Date().toISOString().split('T')[0] }}", "message": "={{ $json.html }}"}}, {"id": "6", "name": "Slack Summary", "type": "n8n-nodes-base.slack", "typeVersion": 2, "position": [910, 500], "parameters": {"channel": "#management", "text": "={{ $json.slack_msg }}"}}], "connections": {"Monday 8AM": {"main": [[{"node": "Get Platform Metrics", "type": "main", "index": 0}, {"node": "Get Compliance Events", "type": "main", "index": 0}]]}, "Get Platform Metrics": {"main": [[{"node": "Build KPI Report", "type": "main", "index": 0}]]}, "Get Compliance Events": {"main": [[{"node": "Build KPI Report", "type": "main", "index": 0}]]}, "Build KPI Report": {"main": [[{"node": "Email CEO + CISO", "type": "main", "index": 0}, {"node": "Slack Summary", "type": "main", "index": 0}]]}}}
Enter fullscreen mode Exit fullscreen mode

Buyer Q&A: 5 Questions Defense Customers Will Ask

Q: Does Zapier process ITAR-controlled technical data?
A: Any routing of USML-category technical data through a SaaS iPaaS with non-US-person employees constitutes a "deemed export" under 22 CFR §120.50, which covers intangible transfers. State Dept DDTC does not distinguish between physical shipment and electronic transmission. If your n8n instance runs on-prem or in AWS GovCloud, the controlled data stays inside your authorized enclave.

Q: Will adding Zapier expand our CMMC Level 2 assessment boundary?
A: Yes. Under DFARS 252.204-7012, any external cloud service provider that processes, stores, or transmits CDI is in-scope for your CMMC assessment. Zapier and Make are not FedRAMP Moderate authorized. A C3PAO finding your workflows routing CUI through Zapier can expand your assessment scope and require a POAM. Self-hosted n8n runs inside your assessed boundary.

Q: Our prime contractor requires we demonstrate CDI containment for DFARS 252.204-7012. How does n8n help?
A: Git-versioned n8n workflow JSON gives you an immutable audit trail of every automation that touches CDI — who wrote it, when it changed, what it does. That satisfies DFARS 252.204-7012's documentation requirements and gives your C3PAO assessor a clean chain of custody.

Q: We need to demonstrate NIST 800-171 §3.13.3 (protection of CUI at rest and in transit). Does Zapier qualify?
A: Zapier does not guarantee FedRAMP Moderate-equivalent encryption controls for CUI in transit or at rest between their servers. Self-hosted n8n with TLS termination on your infrastructure and encryption at rest for your database satisfies §3.13.3 with controls you control and can document.

Q: Our legal team flagged that routing flight test telemetry through Make could be a deemed export. Are they right?
A: Likely yes, if the telemetry contains USML-category data or ECCN-controlled technology parameters. The ITAR definition of "export" (22 CFR §120.50) covers any release of technical data to a foreign person regardless of location — including an employee of a US company who is a non-US person. Self-hosted n8n running in your accredited facility eliminates that exposure.


What to configure first

  1. ITAR/EAR Authorization Sheet — add your DSP-5 / TAA / MLA / BIS license expiry dates immediately. The monitor runs daily and requires no other setup.
  2. Incident webhook — wire your SIEM alert to /aerodefense-incident. This starts the DFARS 72-hour clock automatically.
  3. Compliance Deadline Tracker — add your CMMC C3PAO assessment date and DFARS annual review date. The tracker gives you 120/90/60/30/14 day warnings.
  4. Onboarding drip — connect to your CRM webhook so new defense customers receive ITAR/CMMC-specific content automatically.

All 5 workflows are available as part of the FlowKit n8n automation template pack: stripeai.gumroad.com


FlowKit builds n8n automation templates for compliance-sensitive industries. All workflows are self-hosted — your data stays on your infrastructure.

Top comments (0)