DEV Community

Alex Kane
Alex Kane

Posted on

n8n for SpaceTech & Defense SaaS Vendors: 5 Automations for ITAR, DFARS 252.204-7012, CMMC 2.0, and EAR Compliance

Your defense SaaS platform just processed a contractor's Technical Data Package. That TDP contains CUI — Controlled Unclassified Information. The DFARS 252.204-7012(m)(1) 72-hour clock just started. Your incident response automation should already be running.

But does it know the difference between a CUI breach (72h to DC3) and an ITAR unlicensed disclosure (voluntary disclosure to DDTC, no fixed deadline but criminal risk at $1M + 20 years)? Does it know that NDAA §889 requires you to notify the Contracting Officer within 24 hours of discovering a prohibited component?

This guide shows five production-ready n8n workflows for SpaceTech and Defense SaaS vendors, including full JSON you can import today.

Who This Is For

These automations are built for SaaS companies selling into defense and space:

  • Launch vehicle operations platforms (tracking ITAR USML Cat IV/XV)
  • Defense supply chain software (DFARS 252.204-7012 CUI handlers)
  • Dual-use AI/ML platforms bridging commercial and DoD
  • UAS/autonomous systems vendors (ITAR USML Cat VIII)
  • Space data analytics companies (EAR CCL ECCN classifications)
  • Any SaaS with CMMC Level 2 requirements in their contract
Customer Tier Typical Profile Key Compliance Obligations
PRIME_DEFENSE_CONTRACTOR_SAAS Top-5 defense prime selling SaaS to DoD CMMC L2+, DFARS 7012, ITAR, EAR, FedRAMP Mod
SPACE_LAUNCH_SAAS_VENDOR Launch vehicle ops, sat-ops software ITAR USML Cat IV/XV, FAA Part 460, FCC Part 25
DIB_MIDMARKET_SAAS Mid-size Tier-2/3 defense supply chain CMMC L2, DFARS 7012, NIST 800-171, NDAA §889
DUAL_USE_TECH_SAAS Commercial-to-defense bridge (AI, ML, sensors) EAR CCL ECCN 3E002+, CMMC L1, NDAA §889
AUTONOMOUS_SYSTEMS_SAAS Drone/UAS/autonomous ground vehicle software ITAR USML Cat VIII/XI, FAA Part 107, NDAA §889
DEFENSE_INTELLIGENCE_SAAS IC-adjacent analytics/data platforms ITAR, EAR, FISMA High, ICD 503, CJIS
SPACETECH_STARTUP_SAAS Startups entering defense/space market ITAR registration (22 CFR §122.1), EAR classification, CMMC roadmap

Why Self-Hosted n8n for Defense and Space

Using Zapier or Make.com to route defense-related data creates a deemed export problem. When your workflow automation platform is a US-based cloud SaaS, every non-US employee of that vendor who can theoretically access your automation logs may constitute an unlicensed export of ITAR-controlled technical data.

Self-hosted n8n eliminates this entirely:

Risk Factor Zapier/Make Self-Hosted n8n
CUI data in cloud SaaS logs Yes — DFARS 7012 finding No — stays in your enclave
ITAR deemed export via cloud vendor Possible Not applicable
CMMC L2 vendor risk finding CC9.2 Closed — no external SaaS
Audit trail for DC3 report Not guaranteed Git-versioned JSON
FedRAMP boundary expansion CC9.2 scope issue In-boundary by design

Workflow 1: ITAR/EAR Export Authorization Monitor

Monitors all active ITAR/EAR licenses and agreements. Alerts export control officers before any expiry creates an unlicensed export.

Tracks: DSP-5, DSP-73, TAA (Technical Assistance Agreement), MLA (Manufacturing License Agreement), CCL export licenses

Triggers at: EXPIRED → CRITICAL (≤14d) → URGENT (≤45d) → WARNING (≤90d) → NOTICE (≤120d)

{
  "name": "ITAR/EAR Export Authorization Monitor",
  "nodes": [
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000001",
      "name": "Daily 7AM Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * 1-5"
            }
          ]
        }
      }
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000002",
      "name": "Read Authorizations",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        460,
        300
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id, auth_type, auth_number, country, technology_category, expiry_date, responsible_ecc_officer, customer_tier, CURRENT_DATE::text AS today, (expiry_date - CURRENT_DATE) AS days_remaining FROM export_authorizations WHERE expiry_date IS NOT NULL AND (expiry_date - CURRENT_DATE) <= 120 AND status = 'ACTIVE' ORDER BY expiry_date ASC"
      }
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000003",
      "name": "Classify Urgency",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\nfor (const item of items) {\n  const d = item.json;\n  const days = parseInt(d.days_remaining);\n  let urgency, slackChannel, escalate;\n  if (days < 0) {\n    urgency = 'EXPIRED';\n    slackChannel = '#export-control-urgent';\n    escalate = true;\n  } else if (days <= 14) {\n    urgency = 'CRITICAL';\n    slackChannel = '#export-control-urgent';\n    escalate = true;\n  } else if (days <= 45) {\n    urgency = 'URGENT';\n    slackChannel = '#export-control';\n    escalate = false;\n  } else if (days <= 90) {\n    urgency = 'WARNING';\n    slackChannel = '#export-control';\n    escalate = false;\n  } else {\n    urgency = 'NOTICE';\n    slackChannel = '#export-control';\n    escalate = false;\n  }\n  const authTypeLabel = {\n    'DSP5': 'DSP-5 Export License',\n    'DSP73': 'DSP-73 Temporary Export',\n    'TAA': 'Technical Assistance Agreement',\n    'MLA': 'Manufacturing License Agreement',\n    'AES_EEI': 'EAR Electronic Export Info',\n    'CCL_LICENSE': 'CCL Export License'\n  }[d.auth_type] || d.auth_type;\n  results.push({ json: { ...d, urgency, slackChannel, escalate, authTypeLabel, daysRemaining: days } });\n}\nreturn results.filter(r => r.json.urgency !== 'NOTICE' || true);"
      }
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000004",
      "name": "Slack Export Control",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        900,
        220
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "post",
        "channel": "={{ $json.slackChannel }}",
        "text": "={{ $json.urgency }} \u2014 Export Authorization {{ $json.auth_number }} ({{ $json.authTypeLabel }}) for {{ $json.country }} expires {{ $json.expiry_date }} ({{ $json.daysRemaining }} days). ECC Officer: {{ $json.responsible_ecc_officer }}. Auth type: {{ $json.auth_type }}. Tier: {{ $json.customer_tier }}."
      }
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000005",
      "name": "Log to Postgres",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        900,
        380
      ],
      "parameters": {
        "operation": "insert",
        "schema": "public",
        "table": "export_auth_alerts",
        "columns": "auth_id,urgency,days_remaining,alert_sent_at",
        "values": "={{ $json.id }},={{ $json.urgency }},={{ $json.daysRemaining }},={{ new Date().toISOString() }}"
      }
    }
  ],
  "connections": {
    "Daily 7AM Check": {
      "main": [
        [
          {
            "node": "Read Authorizations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Authorizations": {
      "main": [
        [
          {
            "node": "Classify Urgency",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Urgency": {
      "main": [
        [
          {
            "node": "Slack Export Control",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log to Postgres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 2: DFARS 252.204-7012 CUI 72-Hour Incident Pipeline

When a CUI incident hits your platform, this workflow fires immediately — classifies the incident type, calculates the regulatory deadline, alerts your CISO, and opens a logged record for the DC3 report.

Incident types handled:

  • CUI_UNAUTHORIZED_ACCESS / CUI_DATA_EXFILTRATION → 72h to DC3 (DFARS 252.204-7012(m)(1))
  • ITAR_UNLICENSED_DISCLOSURE → DDTC voluntary disclosure (22 CFR §127.12)
  • NDAA_889_PROHIBITED_ITEM → 24h to Contracting Officer
  • CLASSIFIED_SPILL → Immediate FSO notification (DoD 5200.01 Vol 3)
{
  "name": "DFARS 252.204-7012 CUI 72-Hour Incident Pipeline",
  "nodes": [
    {
      "id": "b2c3d4e5-0002-0002-0002-000000000001",
      "name": "CUI Incident Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "cui-incident",
        "responseMode": "responseNode"
      }
    },
    {
      "id": "b2c3d4e5-0002-0002-0002-000000000002",
      "name": "Classify Incident",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "jsCode": "const d = $input.first().json.body || $input.first().json;\nconst incidentTypes = {\n  'CUI_UNAUTHORIZED_ACCESS': { deadline: 72, regulation: 'DFARS 252.204-7012(m)(1)', reportTo: 'DC3' },\n  'CUI_DATA_EXFILTRATION': { deadline: 72, regulation: 'DFARS 252.204-7012(m)(1)', reportTo: 'DC3' },\n  'SYSTEM_COMPROMISE_WITH_CUI': { deadline: 72, regulation: 'DFARS 252.204-7012(m)(1)', reportTo: 'DC3' },\n  'ITAR_UNLICENSED_DISCLOSURE': { deadline: 0, regulation: '22 CFR \u00a7127.12 voluntary disclosure', reportTo: 'DDTC' },\n  'EAR_UNAUTHORIZED_EXPORT': { deadline: 0, regulation: '15 CFR \u00a7764.5', reportTo: 'BIS' },\n  'CMMC_CONTROL_FAILURE': { deadline: 72, regulation: 'DFARS 252.204-7021(c)(4)', reportTo: 'DIBNet' },\n  'NDAA_889_PROHIBITED_ITEM': { deadline: 24, regulation: 'NDAA \u00a7889(b)(1)', reportTo: 'Contracting Officer' },\n  'CLASSIFIED_SPILL': { deadline: 0, regulation: 'DoD 5200.01 Vol 3', reportTo: 'FSO' }\n};\nconst incType = d.incident_type || 'CUI_UNAUTHORIZED_ACCESS';\nconst cfg = incidentTypes[incType] || incidentTypes['CUI_UNAUTHORIZED_ACCESS'];\nconst now = new Date();\nconst deadlineTs = cfg.deadline > 0 ? new Date(now.getTime() + cfg.deadline * 3600 * 1000).toISOString() : 'IMMEDIATE';\nreturn [{ json: { ...d, incidentType: incType, deadlineHours: cfg.deadline, deadlineTimestamp: deadlineTs, regulation: cfg.regulation, reportTo: cfg.reportTo, detectedAt: now.toISOString(), incidentId: `CUI-${Date.now()}` } }];"
      }
    },
    {
      "id": "b2c3d4e5-0002-0002-0002-000000000003",
      "name": "Alert CISO",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        680,
        220
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "post",
        "channel": "#ciso-security-incidents",
        "text": "DFARS CUI INCIDENT \u2014 ID: {{ $json.incidentId }}\\nType: {{ $json.incidentType }}\\nRegulation: {{ $json.regulation }}\\nReport to: {{ $json.reportTo }}\\nDeadline: {{ $json.deadlineHours }}h \u2192 {{ $json.deadlineTimestamp }}\\nSystem: {{ $json.affected_system }}\\nCustomer: {{ $json.customer_id }}\\nDetected: {{ $json.detectedAt }}"
      }
    },
    {
      "id": "b2c3d4e5-0002-0002-0002-000000000004",
      "name": "Log Incident",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        680,
        380
      ],
      "parameters": {
        "operation": "insert",
        "schema": "public",
        "table": "cui_incidents",
        "columns": "incident_id,incident_type,regulation,report_to,deadline_hours,deadline_ts,affected_system,customer_id,detected_at,status",
        "values": "={{ $json.incidentId }},={{ $json.incidentType }},={{ $json.regulation }},={{ $json.reportTo }},={{ $json.deadlineHours }},={{ $json.deadlineTimestamp }},={{ $json.affected_system }},={{ $json.customer_id }},={{ $json.detectedAt }},'OPEN'"
      }
    },
    {
      "id": "b2c3d4e5-0002-0002-0002-000000000005",
      "name": "Respond 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        460,
        460
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ received: true, incidentId: $json.incidentId, deadlineTs: $json.deadlineTimestamp }) }}"
      }
    }
  ],
  "connections": {
    "CUI Incident Webhook": {
      "main": [
        [
          {
            "node": "Classify Incident",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond 200",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Incident": {
      "main": [
        [
          {
            "node": "Alert CISO",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Incident",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 3: CMMC 2.0 / NIST 800-171 Compliance Deadline Tracker

Runs every weekday morning and surfaces upcoming compliance deadlines before they become violations. DFARS 252.204-7021 requires flow-down to all subcontractors handling CUI — this workflow tracks your own obligations and those you manage on behalf of customers.

Deadline types tracked: CMMC C3PAO assessment, NIST 800-171 self-assessment + SPRS score update, ITAR registration renewal (22 CFR §122.1), EAR CCL license renewal, DFARS 7012 annual system review, NDAA §889 annual attestation, AECA compliance audit, SBIR/STTR milestones, SOC 2, FedRAMP ConMon, annual pentest, IR drill (NIST 800-171 3.6.3)

{
  "name": "CMMC 2.0 / NIST 800-171 Compliance Deadline Tracker",
  "nodes": [
    {
      "id": "c3d4e5f6-0003-0003-0003-000000000001",
      "name": "Weekdays 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1-5"
            }
          ]
        }
      }
    },
    {
      "id": "c3d4e5f6-0003-0003-0003-000000000002",
      "name": "Read Compliance Items",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        460,
        300
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id, deadline_type, description, due_date, assigned_to, customer_tier, compliance_framework, (due_date - CURRENT_DATE) AS days_remaining FROM compliance_deadlines WHERE due_date IS NOT NULL AND (due_date - CURRENT_DATE) <= 90 AND status NOT IN ('COMPLETE','WAIVED') ORDER BY due_date ASC"
      }
    },
    {
      "id": "c3d4e5f6-0003-0003-0003-000000000003",
      "name": "Classify Priority",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst seen = new Set();\nconst results = [];\nfor (const item of items) {\n  const d = item.json;\n  const days = parseInt(d.days_remaining);\n  const key = `${d.id}-${new Date().toISOString().slice(0,10)}`;\n  if (seen.has(key)) continue;\n  seen.add(key);\n  let priority, emoji, channel;\n  const deadlineLabels = {\n    'CMMC_C3PAO_ASSESSMENT': 'CMMC L2 C3PAO Assessment (DFARS 252.204-7021)',\n    'NIST_800_171_SELF_ASSESSMENT': 'NIST 800-171 Self-Assessment + SPRS Update',\n    'ITAR_REGISTRATION_RENEWAL': 'ITAR Registration Renewal (22 CFR \u00a7122.1)',\n    'EAR_CCL_LICENSE_RENEWAL': 'EAR CCL Export License Renewal (15 CFR \u00a7750)',\n    'DFARS_7012_ANNUAL_REVIEW': 'DFARS 252.204-7012 Annual System Review',\n    'NDAA_889_ATTESTATION': 'NDAA \u00a7889 Annual Attestation to CO',\n    'AECA_COMPLIANCE_AUDIT': 'AECA Arms Export Compliance Audit',\n    'SBIR_PHASE_MILESTONE': 'SBIR/STTR Phase Milestone Report',\n    'SOC2_TYPE2_RENEWAL': 'SOC 2 Type II Renewal',\n    'FEDRAMP_CONMON_REVIEW': 'FedRAMP ConMon Monthly Review',\n    'PENTEST_ANNUAL': 'Annual Penetration Test',\n    'INCIDENT_RESPONSE_DRILL': 'IR Plan Annual Drill (NIST 800-171 3.6.3)'\n  };\n  if (days < 0) { priority='OVERDUE'; emoji='\ud83d\udea8'; channel='#compliance-critical'; }\n  else if (days <= 7) { priority='CRITICAL'; emoji='\ud83d\udd34'; channel='#compliance-critical'; }\n  else if (days <= 21) { priority='URGENT'; emoji='\ud83d\udfe0'; channel='#compliance-team'; }\n  else if (days <= 45) { priority='WARNING'; emoji='\ud83d\udfe1'; channel='#compliance-team'; }\n  else { priority='NOTICE'; emoji='\ud83d\udd35'; channel='#compliance-team'; }\n  results.push({ json: { ...d, priority, emoji, channel, deadlineLabel: deadlineLabels[d.deadline_type] || d.deadline_type, daysRemaining: days } });\n}\nreturn results;"
      }
    },
    {
      "id": "c3d4e5f6-0003-0003-0003-000000000004",
      "name": "Slack Compliance Team",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        900,
        220
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "post",
        "channel": "={{ $json.channel }}",
        "text": "={{ $json.emoji }} {{ $json.priority }} \u2014 {{ $json.deadlineLabel }}\\nDue: {{ $json.due_date }} ({{ $json.daysRemaining }} days)\\nAssigned: {{ $json.assigned_to }}\\nFramework: {{ $json.compliance_framework }}\\nCustomer tier: {{ $json.customer_tier }}"
      }
    },
    {
      "id": "c3d4e5f6-0003-0003-0003-000000000005",
      "name": "Email Owner",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        900,
        400
      ],
      "parameters": {
        "operation": "send",
        "toList": "={{ $json.assigned_to }}",
        "subject": "={{ $json.priority }}: {{ $json.deadlineLabel }} due {{ $json.due_date }} ({{ $json.daysRemaining }}d)",
        "message": "<p>{{ $json.emoji }} <strong>{{ $json.priority }}</strong>: {{ $json.deadlineLabel }}</p><p>Due: {{ $json.due_date }} ({{ $json.daysRemaining }} days remaining)<br/>Framework: {{ $json.compliance_framework }}<br/>Customer tier: {{ $json.customer_tier }}</p><p>Action required: ensure evidence artifacts are collected and controls documented before the deadline.</p>"
      }
    }
  ],
  "connections": {
    "Weekdays 8AM": {
      "main": [
        [
          {
            "node": "Read Compliance Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Compliance Items": {
      "main": [
        [
          {
            "node": "Classify Priority",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Priority": {
      "main": [
        [
          {
            "node": "Slack Compliance Team",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 4: NDAA §889 Banned Component & Supplier Screen

NDAA §889(b)(1) prohibits US government contractors from using or procuring equipment, systems, or services from Huawei, ZTE, Hytera Communications, Hangzhou Hikvision, and Dahua Technology — or their subsidiaries and affiliates. This webhook fires whenever a new supplier or hardware component is onboarded.

Screen logic: checks supplier name, domain, and component manufacturer against the §889(f)(3) prohibited entity list. PROHIBITED result requires 24-hour Contracting Officer notification under DFARS 252.204-7021(c)(5).

{
  "name": "NDAA \u00a7889 Banned Component & Supplier Screen",
  "nodes": [
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000001",
      "name": "New Supplier Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "supplier-screen",
        "responseMode": "responseNode"
      }
    },
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000002",
      "name": "Screen Against \u00a7889 List",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "jsCode": "const d = $input.first().json.body || $input.first().json;\n// NDAA \u00a7889(f)(3) prohibited entities (Huawei, ZTE, Hytera, Hikvision, Dahua, affiliates)\nconst prohibitedEntities = [\n  'huawei','zte corporation','hytera communications','hangzhou hikvision','dahua technology',\n  'hikvision','dahua','hytera','seafar','panda international'\n];\nconst prohibitedDomains = ['huawei.com','zte.com.cn','hikvision.com','dahuasecurity.com'];\nconst supplierName = (d.supplier_name || '').toLowerCase();\nconst supplierDomain = (d.supplier_domain || '').toLowerCase();\nconst componentMfr = (d.component_manufacturer || '').toLowerCase();\nconst nameMatch = prohibitedEntities.find(e => supplierName.includes(e) || componentMfr.includes(e));\nconst domainMatch = prohibitedDomains.find(dom => supplierDomain.includes(dom));\nconst flagged = !!(nameMatch || domainMatch);\nconst screenId = `NDAA889-${Date.now()}`;\nreturn [{ json: {\n  ...d,\n  screenId,\n  flagged,\n  matchedEntity: nameMatch || domainMatch || null,\n  screenedAt: new Date().toISOString(),\n  regulation: 'NDAA \u00a7889(b)(1)(A)/(B) \u2014 2019 NDAA',\n  riskLevel: flagged ? 'PROHIBITED' : 'CLEARED',\n  contractorNotificationRequired: flagged\n} }];"
      }
    },
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000003",
      "name": "Flagged?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.1,
      "position": [
        680,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true
          },
          "conditions": [
            {
              "id": "cond1",
              "leftValue": "={{ $json.flagged }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000004",
      "name": "Alert Procurement",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        900,
        200
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "post",
        "channel": "#procurement-compliance",
        "text": "NDAA \u00a7889 PROHIBITED ENTITY DETECTED\\nScreen ID: {{ $json.screenId }}\\nSupplier: {{ $json.supplier_name }}\\nMatched: {{ $json.matchedEntity }}\\nRegulation: {{ $json.regulation }}\\nAction: DO NOT ONBOARD \u2014 notify Contracting Officer within 24h per DFARS 252.204-7021(c)(5)"
      }
    },
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000005",
      "name": "Log Screen Result",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        900,
        400
      ],
      "parameters": {
        "operation": "insert",
        "schema": "public",
        "table": "supplier_screens",
        "columns": "screen_id,supplier_name,flagged,matched_entity,risk_level,regulation,screened_at",
        "values": "={{ $json.screenId }},={{ $json.supplier_name }},={{ $json.flagged }},={{ $json.matchedEntity || 'none' }},={{ $json.riskLevel }},={{ $json.regulation }},={{ $json.screenedAt }}"
      }
    },
    {
      "id": "d4e5f6a7-0004-0004-0004-000000000006",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        460,
        460
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ screenId: $json.screenId, riskLevel: $json.riskLevel, flagged: $json.flagged }) }}"
      }
    }
  ],
  "connections": {
    "New Supplier Webhook": {
      "main": [
        [
          {
            "node": "Screen Against \u00a7889 List",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Screen Against \u00a7889 List": {
      "main": [
        [
          {
            "node": "Flagged?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Screen Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flagged?": {
      "main": [
        [
          {
            "node": "Alert Procurement",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Workflow 5: Weekly Defense Platform KPI Dashboard

Every Monday morning, sends a combined business + compliance health report to your CEO and CISO. Keeps leadership informed on MRR, prime contractor account penetration, and open CMMC/ITAR/NDAA items — in one email, not five spreadsheets.

{
  "name": "Weekly Defense Platform KPI Dashboard",
  "nodes": [
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000001",
      "name": "Monday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      }
    },
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000002",
      "name": "Platform Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        460,
        220
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(*) FILTER (WHERE status='ACTIVE') AS active_accounts, COUNT(*) FILTER (WHERE status='TRIAL') AS trial_accounts, SUM(mrr_usd) FILTER (WHERE status='ACTIVE') AS total_mrr, COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '7 days') AS new_this_week, COUNT(*) FILTER (WHERE status='CHURNED' AND updated_at >= NOW() - INTERVAL '7 days') AS churned_this_week, COUNT(*) FILTER (WHERE customer_tier='PRIME_DEFENSE_CONTRACTOR') AS prime_contractor_count FROM accounts"
      }
    },
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000003",
      "name": "Compliance Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        460,
        400
      ],
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT COUNT(*) FILTER (WHERE status='OPEN' AND deadline_type LIKE 'CMMC%') AS cmmc_open, COUNT(*) FILTER (WHERE status='OPEN' AND deadline_type LIKE 'ITAR%') AS itar_open, COUNT(*) FILTER (WHERE status='OPEN' AND deadline_type LIKE 'NDAA%') AS ndaa_open, COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '7 days') AS incidents_this_week, COUNT(*) FILTER (WHERE status='OPEN' AND (due_date - CURRENT_DATE) <= 30) AS critical_deadlines FROM compliance_deadlines WHERE status NOT IN ('COMPLETE','WAIVED')"
      }
    },
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000004",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "combineAll"
      }
    },
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000005",
      "name": "Build HTML Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "jsCode": "const p = $input.first().json;\nconst c = $input.last().json;\nconst mrr = parseFloat(p.total_mrr || 0).toFixed(0);\nconst html = `<h2>Defense SaaS Weekly KPI \u2014 ${new Date().toISOString().slice(0,10)}</h2><table border='1' cellpadding='6'><tr><th>Metric</th><th>Value</th></tr><tr><td>Active Accounts</td><td>${p.active_accounts}</td></tr><tr><td>Trial Accounts</td><td>${p.trial_accounts}</td></tr><tr><td>Total MRR</td><td>$${mrr}</td></tr><tr><td>New This Week</td><td>${p.new_this_week}</td></tr><tr><td>Churned This Week</td><td>${p.churned_this_week}</td></tr><tr><td>Prime Contractor Accounts</td><td>${p.prime_contractor_count}</td></tr><tr><td colspan='2'><strong>Compliance</strong></td></tr><tr><td>CMMC Open Items</td><td>${c.cmmc_open}</td></tr><tr><td>ITAR Open Items</td><td>${c.itar_open}</td></tr><tr><td>NDAA \u00a7889 Open Items</td><td>${c.ndaa_open}</td></tr><tr><td>Incidents This Week</td><td>${c.incidents_this_week}</td></tr><tr><td>Critical Deadlines \u226430d</td><td>${c.critical_deadlines}</td></tr></table>`;\nreturn [{ json: { html, reportDate: new Date().toISOString().slice(0,10) } }];"
      }
    },
    {
      "id": "e5f6a7b8-0005-0005-0005-000000000006",
      "name": "Email Leadership",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "operation": "send",
        "toList": "ceo@yourcompany.com",
        "ccList": "ciso@yourcompany.com,vp-compliance@yourcompany.com",
        "subject": "Defense SaaS Weekly KPI \u2014 {{ $json.reportDate }}",
        "message": "={{ $json.html }}"
      }
    }
  ],
  "connections": {
    "Monday 8AM": {
      "main": [
        [
          {
            "node": "Platform Metrics",
            "type": "main",
            "index": 0
          },
          {
            "node": "Compliance Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Platform Metrics": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compliance Metrics": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Build HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build HTML Report": {
      "main": [
        [
          {
            "node": "Email Leadership",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Compliance Coverage Summary

Regulation Key Deadline Workflow
DFARS 252.204-7012(m)(1) 72h to DC3 after CUI incident Workflow 2
ITAR 22 CFR §127.12 Voluntary disclosure, no fixed clock Workflow 2
NDAA §889(b)(1) 24h to CO after prohibited item found Workflow 4
ITAR 22 CFR §122.1 Registration renewal (annual) Workflow 3
CMMC 2.0 Level 2 C3PAO Assessment cycle per contract Workflow 3
EAR CCL license expiry Per license terms Workflow 1
NIST 800-171 SPRS update Before each contract award Workflow 3

Customizations to Add

  1. SBIR/STTR tracking: Add SBIR_PHASE_MILESTONE deadline types with program office email routing
  2. Multi-program isolation: Add a program_id field and route alerts to program-specific Slack channels
  3. DSP-83 nontransfer tracking: Log nontransfer/retransfer certificates alongside TAAs in Workflow 1
  4. SPRS score automation: After completing NIST 800-171 assessment, auto-calculate score and flag for PIEE submission
  5. Contract vehicle alerts: Add IDIQ/GWAC task order windows as deadline types in Workflow 3

All five workflows are available in the FlowKit n8n template store along with 10 other ready-to-run automations for SaaS operations.

Top comments (0)