Your GovTech or CivicTech SaaS company serves federal agencies, state governments, public safety departments, courts, election administrators, or emergency management offices. You know the compliance matrix. What you may not have considered: every third-party iPaaS integration you use to automate your own operations creates an authorization boundary problem.
When a federal agency's data — or Controlled Unclassified Information (CUI) flowing through your platform — passes through a Zapier workflow, Make scenario, or cloud automation tool that is not within your FedRAMP ATO authorization boundary, you have a CUI spillage event. NIST SP 800-171 Rev2 §3.6.2 requires incident reporting within 72 hours. Your cloud iPaaS vendor is not covered by your ATO. Your CJIS terminal agency agreement does not extend to their infrastructure. Your FOIA response clock does not pause because your workflow tool was unavailable.
This article maps five import-ready n8n automation workflows for GovTech/CivicTech SaaS vendors — covering FISMA, FedRAMP, NIST SP 800-171, CMMC 2.0, CJIS Security Policy 5.9.1, FOIA 5 USC §552, Section 508, and HAVA VVSG 2.0. All workflows run on self-hosted n8n inside your authorization boundary. Zero data flows to external cloud vendors.
GovTech/CivicTech SaaS Vendor Tiers
| Tier | Primary Compliance Framework |
|---|---|
FEDERAL_SAAS |
FedRAMP ATO (High/Moderate/Low) + FISMA 44 USC §3553 + NIST SP 800-53 Rev5 |
STATE_MUNICIPAL_SAAS |
StateRAMP + state FOIA/open records + NIST SP 800-171 self-attestation |
PUBLIC_SAFETY_SAAS |
FBI CJIS Security Policy 5.9.1 + NCIC access + 1-hour incident reporting |
COURT_CASE_MGMT_SAAS |
CJIS Security Policy 5.9.1 + SJI court tech standards + sealed records rules |
ELECTION_TECH_SAAS |
HAVA VVSG 2.0 + EAC certification (5-year) + CISA election security guidance |
EMERGENCY_MGMT_SAAS |
DHS NIMS + FEMA IS-700.b + CISA directives + FCC EAS integration |
GOVTECH_STARTUP |
FedRAMP Ready pathway + NIST 800-171 self-attestation + StateRAMP prep |
Compliance Flags
| Flag | Regulation | Fastest Clock |
|---|---|---|
FISMA_ANNUAL_AUTH |
FISMA 44 USC §3553(a)(2) | 365-day ATO renewal |
FEDRAMP_CONMON_MONTHLY |
FedRAMP ConMon | 30-day monthly vuln scan |
NIST_800_171_CUI_INCIDENT_72H |
NIST SP 800-171 Rev2 §3.6.2 | 72-hour CUI spillage report |
FOIA_20_BUSINESS_DAY |
FOIA 5 USC §552(a)(6)(A)(i) | 20 business days (~28 calendar) |
CJIS_SECURITY_INCIDENT_1H |
CJIS Security Policy 5.9.1 §5.4.1 | 1-hour incident report |
CMMC_L2_C3PAO_TRIENNIAL |
CMMC 2.0 Level 2 | 3-year C3PAO assessment |
SECTION_508_VPAT_ANNUAL |
29 USC §794d | Annual VPAT/ACR update |
EAC_CERT_5_YEAR |
HAVA VVSG 2.0 | 5-year EAC certification |
FEDRAMP_POAM_MONTHLY |
FedRAMP POA&M | Monthly submission to JAB/AO |
STATERAMP_ANNUAL |
StateRAMP | Annual security review |
FOIA_UNUSUAL_10_DAY |
FOIA 5 USC §552(a)(6)(B) | 10-day extension notification |
CJIS_NCIC_AUDIT_ANNUAL |
CJIS Policy §4.1.1 | Annual NCIC terminal agency audit |
Workflow 1: Tier-Segmented Compliance Onboarding Drip
When a new GovTech account signs up, route them through a compliance-aware welcome sequence. A FEDERAL_SAAS customer needs to hear about your FedRAMP ATO boundary immediately — before they import data. A PUBLIC_SAFETY_SAAS customer needs your CJIS terminal agency agreement process. A GOVTECH_STARTUP customer needs the FedRAMP Ready pathway checklist. One generic onboarding email is not compliant posture.
{
"name": "GovTech Tier-Segmented Compliance Onboarding Drip",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "govtech-onboard",
"responseMode": "lastNode",
"options": {}
},
"id": "wh1",
"name": "Webhook \u2013 New GovTech Account",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "a1",
"name": "vendor_tier",
"value": "={{ $json.vendor_tier }}",
"type": "string"
},
{
"id": "a2",
"name": "company_name",
"value": "={{ $json.company_name }}",
"type": "string"
},
{
"id": "a3",
"name": "contact_email",
"value": "={{ $json.contact_email }}",
"type": "string"
},
{
"id": "a4",
"name": "fedramp_level",
"value": "={{ $json.fedramp_impact_level || 'MODERATE' }}",
"type": "string"
},
{
"id": "a5",
"name": "handles_cui",
"value": "={{ $json.handles_cui === true }}",
"type": "boolean"
},
{
"id": "a6",
"name": "cjis_required",
"value": "={{ $json.cjis_required === true }}",
"type": "boolean"
},
{
"id": "a7",
"name": "onboard_ts",
"value": "={{ new Date().toISOString() }}",
"type": "string"
}
]
},
"options": {}
},
"id": "set1",
"name": "Set Vendor Context",
"type": "n8n-nodes-base.set",
"typeVersion": 3,
"position": [
440,
300
]
},
{
"parameters": {
"mode": "rules",
"rules": {
"rules": [
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "FEDERAL_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "FEDERAL_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "STATE_MUNICIPAL_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "STATE_MUNICIPAL_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "PUBLIC_SAFETY_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "PUBLIC_SAFETY_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "COURT_CASE_MGMT_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "COURT_CASE_MGMT_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "ELECTION_TECH_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "ELECTION_TECH_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "EMERGENCY_MGMT_SAAS",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "EMERGENCY_MGMT_SAAS"
},
{
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.vendor_tier }}",
"rightValue": "GOVTECH_STARTUP",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"renameOutput": true,
"outputKey": "GOVTECH_STARTUP"
}
]
},
"options": {}
},
"id": "sw1",
"name": "Route by GovTech Tier",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
640,
300
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "FedRAMP ATO Boundary Notice \u2014 {{ $json.company_name }}",
"message": "Your account (FedRAMP {{ $json.fedramp_level }}) is active. Per FISMA 44 USC \u00a73553(a)(2), all data processing occurs within your agency's authorization boundary on self-hosted n8n. CUI handling follows NIST SP 800-171 Rev2. Your ATO renewal window is tracked automatically \u2014 you'll receive alerts at 90/60/30/14 days.",
"options": {}
},
"id": "em1a",
"name": "Email \u2013 FEDERAL_SAAS",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
120
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "StateRAMP + Public Records Compliance \u2014 {{ $json.company_name }}",
"message": "Your account (STATE_MUNICIPAL_SAAS) is active. StateRAMP continuous monitoring is enabled. Per your state's open records / FOIA statute, any data you process may be subject to public records requests. FOIA response clocks (20 business days federal, varies by state) are tracked in your compliance dashboard.",
"options": {}
},
"id": "em1b",
"name": "Email \u2013 STATE_MUNICIPAL",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
240
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "CJIS Security Policy 5.9.1 Compliance Notice \u2014 {{ $json.company_name }}",
"message": "Your account (PUBLIC_SAFETY_SAAS) is active. FBI CJIS Security Policy 5.9.1 requires multi-factor authentication, advanced encryption, and security incident reporting within 1 hour (\u00a75.4.1). All criminal justice information (CJI) is processed within your authorized CJIS boundary. NCIC access logs are retained per \u00a75.4.2.",
"options": {}
},
"id": "em1c",
"name": "Email \u2013 PUBLIC_SAFETY",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
360
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "CJIS + Court Records Confidentiality Notice \u2014 {{ $json.company_name }}",
"message": "Your account (COURT_CASE_MGMT_SAAS) is active. Court records confidentiality rules (sealed case data, juvenile records) are enforced at the workflow layer. CJIS Security Policy 5.9.1 applies for any criminal case data. SJI technology standards for court management systems are tracked in your compliance dashboard.",
"options": {}
},
"id": "em1d",
"name": "Email \u2013 COURT_CASE_MGMT",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
480
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "HAVA VVSG 2.0 + CISA Election Guidance \u2014 {{ $json.company_name }}",
"message": "Your account (ELECTION_TECH_SAAS) is active. HAVA VVSG 2.0 (EAC certification, 5-year validity) and CISA election security guidance apply. Your EAC certification expiry is tracked with 180/90/30 day alerts. All election data processing is air-gapped per CISA Protect 2024 guidelines.",
"options": {}
},
"id": "em1e",
"name": "Email \u2013 ELECTION_TECH",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
600
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "DHS NIMS + FEMA Continuity Compliance \u2014 {{ $json.company_name }}",
"message": "Your account (EMERGENCY_MGMT_SAAS) is active. DHS NIMS (National Incident Management System) and FEMA IS-700.b compliance frameworks apply. CISA directives and FCC Emergency Alert System (EAS) integration requirements are tracked in your dashboard. Continuity of Operations Plan (COOP) alignment is required per FEMA guidance.",
"options": {}
},
"id": "em1f",
"name": "Email \u2013 EMERGENCY_MGMT",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
720
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "FedRAMP Ready Pathway + NIST 800-171 Self-Attestation \u2014 {{ $json.company_name }}",
"message": "Your account (GOVTECH_STARTUP) is active. Your FedRAMP Ready pathway checklist is available in the dashboard. NIST SP 800-171 Rev2 self-attestation (110 controls) must be completed before bidding on DoD contracts. StateRAMP prep materials are included. Schedule your compliance kickoff call to begin the ATO process.",
"options": {}
},
"id": "em1g",
"name": "Email \u2013 GOVTECH_STARTUP",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
860,
840
]
}
],
"connections": {
"Webhook \u2013 New GovTech Account": {
"main": [
[
{
"node": "Set Vendor Context",
"type": "main",
"index": 0
}
]
]
},
"Set Vendor Context": {
"main": [
[
{
"node": "Route by GovTech Tier",
"type": "main",
"index": 0
}
]
]
},
"Route by GovTech Tier": {
"main": [
[
{
"node": "Email \u2013 FEDERAL_SAAS",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 STATE_MUNICIPAL",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 PUBLIC_SAFETY",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 COURT_CASE_MGMT",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 ELECTION_TECH",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 EMERGENCY_MGMT",
"type": "main",
"index": 0
}
],
[
{
"node": "Email \u2013 GOVTECH_STARTUP",
"type": "main",
"index": 0
}
]
]
}
}
}
What this covers: FISMA §3553 authorization boundary disclosure (FEDERAL_SAAS), StateRAMP + state open records notice (STATE_MUNICIPAL_SAAS), CJIS Security Policy 5.9.1 §5.4.1 incident reporting requirement (PUBLIC_SAFETY_SAAS + COURT_CASE_MGMT_SAAS), HAVA VVSG 2.0 EAC certification window (ELECTION_TECH_SAAS), DHS NIMS continuity requirements (EMERGENCY_MGMT_SAAS), FedRAMP Ready pathway guide (GOVTECH_STARTUP).
Workflow 2: FedRAMP/FISMA/CMMC/FOIA Deadline Tracker
The GovTech compliance calendar is unforgiving. FedRAMP POA&M items are due monthly. FISMA annual authorizations expire. CMMC 2.0 Level 2 C3PAO assessments recur every three years. FOIA 20-business-day clocks run regardless of your sprint schedule. This workflow checks every deadline daily, routes alerts to the right Slack channel by urgency tier, notifies the account contact, and logs everything to Google Sheets for your auditor.
{
"name": "GovTech Compliance Deadline Tracker (FISMA/FedRAMP/CMMC/FOIA)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"minutesInterval": 1440
}
]
}
},
"id": "sch2",
"name": "Schedule \u2013 Daily 08:00",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT account_id, company_name, contact_email, compliance_type, deadline_date, days_until_deadline FROM govtech_compliance_deadlines WHERE deadline_date >= CURRENT_DATE AND deadline_date <= CURRENT_DATE + INTERVAL '30 days' ORDER BY deadline_date ASC",
"options": {}
},
"id": "pg2",
"name": "Postgres \u2013 Fetch Deadlines",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
440,
300
]
},
{
"parameters": {
"jsCode": "\nconst items = $input.all();\nconst result = [];\nfor (const item of items) {\n const d = item.json;\n const days = d.days_until_deadline;\n let urgency = 'INFO';\n let slack_channel = '#compliance-tracking';\n if (days <= 1) { urgency = 'CRITICAL'; slack_channel = '#compliance-critical'; }\n else if (days <= 3) { urgency = 'HIGH'; slack_channel = '#compliance-critical'; }\n else if (days <= 7) { urgency = 'HIGH'; slack_channel = '#compliance-deadlines'; }\n else if (days <= 14) { urgency = 'MEDIUM'; slack_channel = '#compliance-deadlines'; }\n else if (days <= 30) { urgency = 'LOW'; slack_channel = '#compliance-deadlines'; }\n result.push({ json: { ...d, urgency, slack_channel,\n display_type: d.compliance_type.replace(/_/g,' ') } });\n}\nreturn result;\n"
},
"id": "code2",
"name": "Classify Urgency",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
640,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.urgency }}",
"rightValue": "INFO",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if2",
"name": "Filter \u2013 Actionable Only",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
840,
300
]
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "message",
"operation": "post",
"select": "channel",
"channelId": {
"__rl": true,
"value": "={{ $json.slack_channel }}",
"mode": "name"
},
"text": ":rotating_light: *{{ $json.urgency }}* | {{ $json.display_type }}\n*{{ $json.company_name }}* \u2014 deadline in *{{ $json.days_until_deadline }} days* ({{ $json.deadline_date }})",
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"id": "sl2",
"name": "Slack \u2013 Compliance Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1040,
200
]
},
{
"parameters": {
"fromEmail": "compliance@yourcompany.com",
"toEmail": "={{ $json.contact_email }}",
"subject": "[{{ $json.urgency }}] {{ $json.display_type }} \u2014 {{ $json.days_until_deadline }} days remaining",
"message": "Compliance deadline alert for {{ $json.company_name }}.\n\nType: {{ $json.display_type }}\nDeadline: {{ $json.deadline_date }}\nDays remaining: {{ $json.days_until_deadline }}\nUrgency: {{ $json.urgency }}\n\nLog into your compliance dashboard to review required actions.",
"options": {}
},
"id": "em2",
"name": "Gmail \u2013 Notify Contact",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1040,
400
]
},
{
"parameters": {
"operation": "appendOrUpdate",
"documentId": {
"__rl": true,
"value": "YOUR_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "id"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [
"account_id",
"compliance_type"
],
"schema": []
},
"options": {}
},
"id": "gs2",
"name": "Sheets \u2013 Audit Log",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
1040,
600
]
}
],
"connections": {
"Schedule \u2013 Daily 08:00": {
"main": [
[
{
"node": "Postgres \u2013 Fetch Deadlines",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2013 Fetch Deadlines": {
"main": [
[
{
"node": "Classify Urgency",
"type": "main",
"index": 0
}
]
]
},
"Classify Urgency": {
"main": [
[
{
"node": "Filter \u2013 Actionable Only",
"type": "main",
"index": 0
}
]
]
},
"Filter \u2013 Actionable Only": {
"main": [
[
{
"node": "Slack \u2013 Compliance Alert",
"type": "main",
"index": 0
}
],
[]
]
},
"Slack \u2013 Compliance Alert": {
"main": [
[
{
"node": "Gmail \u2013 Notify Contact",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2013 Notify Contact": {
"main": [
[
{
"node": "Sheets \u2013 Audit Log",
"type": "main",
"index": 0
}
]
]
}
}
}
Deadline types tracked: FISMA_ANNUAL_AUTHORIZATION (365d), FEDRAMP_CONTINUOUS_MONITORING_MONTHLY (30d), NIST_800_171_INCIDENT_72H, FOIA_20_BUSINESS_DAY, FOIA_UNUSUAL_CIRCUMSTANCES_10_DAY_EXTENSION, CJIS_SECURITY_INCIDENT_1H, CMMC_L2_ASSESSMENT_TRIENNIAL (3yr), SECTION_508_VPAT_UPDATE_ANNUAL, FEDRAMP_POA_M_SUBMISSION_MONTHLY, STATERAMP_ANNUAL_REVIEW, GSA_FAR_IT_CONTRACT_ANNUAL_SECURITY_REVIEW, ELECTION_TECH_EAC_CERTIFICATION_EXPIRY (5yr).
Workflow 3: GovTech API Health Monitor (10-min interval)
FedRAMP continuous monitoring requires documented evidence that your system is operating within its authorization boundary. This is not a once-a-day check. If your CJIS API is down, NCIC terminal access is unavailable — that is a reportable security incident per CJIS Security Policy 5.9.1 §5.4.1 within one hour. If your FOIA processing API is down, your 20-business-day response clock does not pause. Monitor every 10 minutes, alert Slack + PagerDuty + CTO on any DOWN state.
{
"name": "GovTech API Health Monitor (FISMA/FedRAMP/CJIS/FOIA \u2013 10 min)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 10
}
]
}
},
"id": "sch3",
"name": "Schedule \u2013 Every 10 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
400
]
},
{
"parameters": {
"jsCode": "\nreturn [\n { json: { endpoint: 'auth_gateway_api', url: 'https://api.yourcompany.com/health/auth', compliance: 'FISMA 44 USC \u00a73553 \u2014 authentication gateway', threshold_ms: 2000 }},\n { json: { endpoint: 'foia_processing_api', url: 'https://api.yourcompany.com/health/foia', compliance: 'FOIA 5 USC \u00a7552 \u2014 20-business-day request clock', threshold_ms: 3000 }},\n { json: { endpoint: 'fedramp_boundary_api', url: 'https://api.yourcompany.com/health/fedramp', compliance: 'FedRAMP ATO boundary \u2014 continuous monitoring', threshold_ms: 2000 }},\n { json: { endpoint: 'cjis_api', url: 'https://api.yourcompany.com/health/cjis', compliance: 'CJIS Security Policy 5.9.1 \u2014 CJI access control', threshold_ms: 1500 }},\n { json: { endpoint: 'cmmc_evidence_api', url: 'https://api.yourcompany.com/health/cmmc', compliance: 'NIST SP 800-171 Rev2 \u2014 CUI evidence repository', threshold_ms: 2500 }}\n];\n"
},
"id": "code3a",
"name": "Define Endpoints",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
400
]
},
{
"parameters": {
"url": "={{ $json.url }}",
"options": {
"timeout": 5000,
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "http3",
"name": "HTTP Health Check",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
640,
400
],
"continueOnFail": true
},
{
"parameters": {
"jsCode": "\nconst item = $input.item.json;\nconst status = item.$response?.statusCode || item.statusCode;\nconst ok = status >= 200 && status < 300;\nconst ts = new Date().toISOString();\nreturn [{ json: { ...item, http_status: status, health: ok ? 'UP' : 'DOWN', checked_at: ts,\n alert_msg: ok ? null : `GOVTECH API DOWN: ${item.endpoint} | ${item.compliance} | HTTP ${status} @ ${ts}` } }];\n"
},
"id": "code3b",
"name": "Evaluate Health",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
840,
400
]
},
{
"parameters": {
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.health }}",
"rightValue": "DOWN",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if3",
"name": "If DOWN",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1040,
400
]
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "message",
"operation": "post",
"select": "channel",
"channelId": {
"__rl": true,
"value": "#govtech-alerts",
"mode": "name"
},
"text": ":red_circle: GOVTECH API DOWN\n*{{ $json.endpoint }}*\n{{ $json.compliance }}\nHTTP {{ $json.http_status }} @ {{ $json.checked_at }}\n@cto @ciso",
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"id": "sl3",
"name": "Slack \u2013 GovTech Alert",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1240,
300
]
},
{
"parameters": {
"url": "https://events.pagerduty.com/v2/enqueue",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "routing_key",
"value": "YOUR_PAGERDUTY_ROUTING_KEY"
},
{
"name": "event_action",
"value": "trigger"
},
{
"name": "payload",
"value": "={{ JSON.stringify({summary: $json.alert_msg, severity: 'critical', source: $json.endpoint}) }}"
}
]
},
"options": {}
},
"id": "pd3",
"name": "PagerDuty \u2013 Trigger Incident",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1240,
500
]
},
{
"parameters": {
"fromEmail": "alerts@yourcompany.com",
"toEmail": "cto@yourcompany.com",
"subject": "[CRITICAL] GovTech API Down: {{ $json.endpoint }}",
"message": "{{ $json.alert_msg }}\n\nCompliance impact: {{ $json.compliance }}\n\nImmediate action required \u2014 FedRAMP continuous monitoring requires documented incident response within 1 hour.",
"options": {}
},
"id": "em3",
"name": "Gmail \u2013 CTO Alert",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1240,
700
]
}
],
"connections": {
"Schedule \u2013 Every 10 Minutes": {
"main": [
[
{
"node": "Define Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Define Endpoints": {
"main": [
[
{
"node": "HTTP Health Check",
"type": "main",
"index": 0
}
]
]
},
"HTTP Health Check": {
"main": [
[
{
"node": "Evaluate Health",
"type": "main",
"index": 0
}
]
]
},
"Evaluate Health": {
"main": [
[
{
"node": "If DOWN",
"type": "main",
"index": 0
}
]
]
},
"If DOWN": {
"main": [
[
{
"node": "Slack \u2013 GovTech Alert",
"type": "main",
"index": 0
}
],
[]
]
},
"Slack \u2013 GovTech Alert": {
"main": [
[
{
"node": "PagerDuty \u2013 Trigger Incident",
"type": "main",
"index": 0
}
]
]
},
"PagerDuty \u2013 Trigger Incident": {
"main": [
[
{
"node": "Gmail \u2013 CTO Alert",
"type": "main",
"index": 0
}
]
]
}
}
}
Endpoints monitored: auth_gateway_api (FISMA §3553 authentication), foia_processing_api (5 USC §552 response clock), fedramp_boundary_api (FedRAMP ATO boundary), cjis_api (CJIS Security Policy 5.9.1 CJI access), cmmc_evidence_api (NIST SP 800-171 Rev2 CUI evidence repository).
Workflow 4: FOIA Request Processing Pipeline
FOIA 5 USC §552(a)(6)(A)(i) gives agencies 20 business days to respond — roughly 28 calendar days. Miss it and the requester can file in federal district court under §552(a)(4)(B) without further exhaustion. Most GovTech platforms don't manage their customers' FOIA obligations — but if your platform processes government data and receives public records requests directed at that data, you need this. The pipeline acknowledges receipt, assigns the request, tracks the statutory clock, and escalates to your General Counsel at the 10-, 5-, and 2-day marks.
{
"name": "FOIA / Open Records Request Processing Pipeline",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "foia-request",
"responseMode": "lastNode",
"options": {}
},
"id": "wh4",
"name": "Webhook \u2013 New FOIA Request",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
240,
400
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "b1",
"name": "request_id",
"value": "={{ 'FOIA-' + Date.now() }}",
"type": "string"
},
{
"id": "b2",
"name": "requester_name",
"value": "={{ $json.requester_name }}",
"type": "string"
},
{
"id": "b3",
"name": "requester_email",
"value": "={{ $json.requester_email }}",
"type": "string"
},
{
"id": "b4",
"name": "request_description",
"value": "={{ $json.description }}",
"type": "string"
},
{
"id": "b5",
"name": "received_date",
"value": "={{ new Date().toISOString().split('T')[0] }}",
"type": "string"
},
{
"id": "b6",
"name": "statute",
"value": "={{ $json.statute || 'FOIA 5 USC \u00a7552' }}",
"type": "string"
},
{
"id": "b7",
"name": "agency",
"value": "={{ $json.agency }}",
"type": "string"
},
{
"id": "b8",
"name": "response_due_business_days",
"value": "=20",
"type": "number"
},
{
"id": "b9",
"name": "assigned_to",
"value": "foia-team@yourcompany.com",
"type": "string"
}
]
},
"options": {}
},
"id": "set4",
"name": "Set Request Metadata",
"type": "n8n-nodes-base.set",
"typeVersion": 3,
"position": [
440,
400
]
},
{
"parameters": {
"operation": "insert",
"schema": {
"__rl": true,
"value": "public",
"mode": "list"
},
"table": {
"__rl": true,
"value": "foia_requests",
"mode": "list"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": []
},
"options": {}
},
"id": "pg4a",
"name": "Postgres \u2013 Insert Request",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
640,
400
]
},
{
"parameters": {
"fromEmail": "foia@yourcompany.com",
"toEmail": "={{ $json.requester_email }}",
"subject": "FOIA Request Received \u2014 Reference {{ $json.request_id }}",
"message": "Your FOIA request ({{ $json.statute }}) has been received.\n\nReference: {{ $json.request_id }}\nReceived: {{ $json.received_date }}\nAgency: {{ $json.agency }}\n\nPer {{ $json.statute }}, we have 20 business days to respond. You will receive a determination letter by the statutory deadline. If unusual circumstances apply (5 USC \u00a7552(a)(6)(B)), we will notify you within the initial 20-day window.",
"options": {}
},
"id": "em4a",
"name": "Gmail \u2013 Acknowledge to Requester",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
840,
250
]
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "message",
"operation": "post",
"select": "channel",
"channelId": {
"__rl": true,
"value": "#foia-queue",
"mode": "name"
},
"text": ":mailbox_with_mail: *New FOIA Request*\nID: `{{ $json.request_id }}`\nRequester: {{ $json.requester_name }}\nAgency: {{ $json.agency }}\n20 biz-day clock started: {{ $json.received_date }}\nAssign at: https://yourcompany.com/foia/{{ $json.request_id }}",
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"id": "sl4",
"name": "Slack \u2013 FOIA Queue",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
840,
450
]
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "days",
"minutesInterval": 1440
}
]
}
},
"id": "sch4",
"name": "Schedule \u2013 Daily Escalation Check",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
700
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT request_id, requester_email, requester_name, agency, received_date, statute, (received_date + INTERVAL '28 days')::date AS calendar_deadline, (received_date + INTERVAL '28 days')::date - CURRENT_DATE AS days_remaining, status FROM foia_requests WHERE status NOT IN ('closed','denied','fulfilled') AND received_date + INTERVAL '28 days' >= CURRENT_DATE ORDER BY days_remaining ASC",
"options": {}
},
"id": "pg4b",
"name": "Postgres \u2013 Open Requests",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
440,
700
]
},
{
"parameters": {
"jsCode": "\nconst items = $input.all();\nconst alerts = [];\nfor (const item of items) {\n const d = item.json.days_remaining;\n if (d <= 2) {\n alerts.push({ json: { ...item.json, escalation_level: 'CRITICAL', message: `FOIA DEADLINE CRITICAL: ${item.json.request_id} expires in ${d} day(s). Immediate GC notification required per ${item.json.statute}.` }});\n } else if (d <= 5) {\n alerts.push({ json: { ...item.json, escalation_level: 'HIGH', message: `FOIA deadline HIGH: ${item.json.request_id} expires in ${d} days.` }});\n } else if (d <= 10) {\n alerts.push({ json: { ...item.json, escalation_level: 'MEDIUM', message: `FOIA deadline MEDIUM: ${item.json.request_id} expires in ${d} days.` }});\n }\n}\nreturn alerts.length ? alerts : [{ json: { skip: true } }];\n"
},
"id": "code4",
"name": "Escalation Logic",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
640,
700
]
},
{
"parameters": {
"conditions": {
"options": {},
"conditions": [
{
"leftValue": "={{ $json.skip }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "notEqual"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if4",
"name": "Skip if No Alerts",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
840,
700
]
},
{
"parameters": {
"fromEmail": "foia@yourcompany.com",
"toEmail": "gc@yourcompany.com",
"subject": "[{{ $json.escalation_level }}] FOIA Deadline: {{ $json.request_id }} \u2014 {{ $json.days_remaining }} days",
"message": "{{ $json.message }}\n\nRequester: {{ $json.requester_name }} ({{ $json.requester_email }})\nAgency: {{ $json.agency }}\nStatute: {{ $json.statute }}\nDeadline: {{ $json.calendar_deadline }}\n\nFailure to respond within the statutory period exposes the agency to judicial review under 5 USC \u00a7552(a)(4)(B).",
"options": {}
},
"id": "em4b",
"name": "Gmail \u2013 Escalate to GC",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
1040,
700
]
}
],
"connections": {
"Webhook \u2013 New FOIA Request": {
"main": [
[
{
"node": "Set Request Metadata",
"type": "main",
"index": 0
}
]
]
},
"Set Request Metadata": {
"main": [
[
{
"node": "Postgres \u2013 Insert Request",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2013 Insert Request": {
"main": [
[
{
"node": "Gmail \u2013 Acknowledge to Requester",
"type": "main",
"index": 0
}
]
]
},
"Gmail \u2013 Acknowledge to Requester": {
"main": [
[
{
"node": "Slack \u2013 FOIA Queue",
"type": "main",
"index": 0
}
]
]
},
"Schedule \u2013 Daily Escalation Check": {
"main": [
[
{
"node": "Postgres \u2013 Open Requests",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2013 Open Requests": {
"main": [
[
{
"node": "Escalation Logic",
"type": "main",
"index": 0
}
]
]
},
"Escalation Logic": {
"main": [
[
{
"node": "Skip if No Alerts",
"type": "main",
"index": 0
}
]
]
},
"Skip if No Alerts": {
"main": [
[
{
"node": "Gmail \u2013 Escalate to GC",
"type": "main",
"index": 0
}
],
[]
]
}
}
}
Escalation logic: CRITICAL (≤2 days) → Gmail GC + Slack #foia-escalation. HIGH (≤5 days) → Gmail GC + Slack #foia-deadlines. MEDIUM (≤10 days) → Slack #foia-deadlines. UNUSUAL_CIRCUMSTANCES extension (5 USC §552(a)(6)(B)) adds 10 business days — requires written notification to requester before the initial 20-day window closes.
Workflow 5: Weekly GovTech KPI Briefing
Every Monday at 08:00 ET, pull accounts by tier, MRR, new accounts, churn, and the full compliance snapshot — FedRAMP items due in 30 days, CMMC assessments in 60 days, CJIS deadlines in 14 days, FOIA requests with 5 or fewer business days remaining, open POA&M items, and VPAT updates due within 60 days. Render as HTML and send to CEO, BCC CISO, BCC GC. Built inside your FedRAMP authorization boundary — the only infrastructure that should ever see this data.
{
"name": "Weekly GovTech KPI Briefing (CEO + CISO + GC)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"minutesInterval": 10080
}
]
},
"options": {
"timezone": "America/New_York"
}
},
"id": "sch5",
"name": "Schedule \u2013 Monday 08:00 ET",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
240,
400
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "\nSELECT\n COUNT(*) FILTER (WHERE vendor_tier = 'FEDERAL_SAAS') AS federal_saas_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'STATE_MUNICIPAL_SAAS') AS state_municipal_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'PUBLIC_SAFETY_SAAS') AS public_safety_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'COURT_CASE_MGMT_SAAS') AS court_case_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'ELECTION_TECH_SAAS') AS election_tech_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'EMERGENCY_MGMT_SAAS') AS emergency_mgmt_count,\n COUNT(*) FILTER (WHERE vendor_tier = 'GOVTECH_STARTUP') AS startup_count,\n COUNT(*) AS total_accounts,\n SUM(monthly_recurring_revenue) AS total_mrr,\n COUNT(*) FILTER (WHERE churn_date IS NOT NULL AND churn_date >= CURRENT_DATE - INTERVAL '30 days') AS churned_30d,\n COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE - INTERVAL '7 days') AS new_this_week\nFROM govtech_accounts WHERE status = 'active'\n",
"options": {}
},
"id": "pg5a",
"name": "Postgres \u2013 Account Metrics",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
440,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "\nSELECT\n COUNT(*) FILTER (WHERE compliance_type LIKE 'FEDRAMP%' AND deadline_date <= CURRENT_DATE + INTERVAL '30 days') AS fedramp_due_30d,\n COUNT(*) FILTER (WHERE compliance_type LIKE 'CMMC%' AND deadline_date <= CURRENT_DATE + INTERVAL '60 days') AS cmmc_due_60d,\n COUNT(*) FILTER (WHERE compliance_type LIKE 'CJIS%' AND deadline_date <= CURRENT_DATE + INTERVAL '14 days') AS cjis_due_14d,\n COUNT(*) FILTER (WHERE compliance_type = 'FOIA_20_BUSINESS_DAY' AND deadline_date <= CURRENT_DATE + INTERVAL '5 days') AS foia_critical,\n COUNT(*) FILTER (WHERE status = 'POAM_OPEN') AS open_poam_items,\n COUNT(*) FILTER (WHERE compliance_type = 'SECTION_508_VPAT_UPDATE_ANNUAL' AND deadline_date <= CURRENT_DATE + INTERVAL '60 days') AS vpat_due_60d\nFROM govtech_compliance_deadlines\n",
"options": {}
},
"id": "pg5b",
"name": "Postgres \u2013 Compliance Snapshot",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
440,
500
]
},
{
"parameters": {
"jsCode": "\nconst acct = $('Postgres \u2013 Account Metrics').first().json;\nconst comp = $('Postgres \u2013 Compliance Snapshot').first().json;\nconst week = new Date().toISOString().split('T')[0];\nconst html = `\n<html><body style=\"font-family:sans-serif;max-width:640px;margin:0 auto\">\n<h2 style=\"color:#1a3a5c\">GovTech KPI Weekly Briefing \u2014 ${week}</h2>\n<h3>Account Summary</h3>\n<table border=\"1\" cellpadding=\"6\" cellspacing=\"0\" style=\"border-collapse:collapse;width:100%\">\n<tr style=\"background:#e8f0fe\"><th>Tier</th><th>Count</th></tr>\n<tr><td>FEDERAL_SAAS (FedRAMP ATO)</td><td>${acct.federal_saas_count}</td></tr>\n<tr><td>STATE_MUNICIPAL_SAAS (StateRAMP)</td><td>${acct.state_municipal_count}</td></tr>\n<tr><td>PUBLIC_SAFETY_SAAS (CJIS)</td><td>${acct.public_safety_count}</td></tr>\n<tr><td>COURT_CASE_MGMT_SAAS (CJIS + SJI)</td><td>${acct.court_case_count}</td></tr>\n<tr><td>ELECTION_TECH_SAAS (HAVA VVSG 2.0)</td><td>${acct.election_tech_count}</td></tr>\n<tr><td>EMERGENCY_MGMT_SAAS (DHS NIMS)</td><td>${acct.emergency_mgmt_count}</td></tr>\n<tr><td>GOVTECH_STARTUP (FedRAMP Ready)</td><td>${acct.startup_count}</td></tr>\n<tr style=\"font-weight:bold;background:#f0f4ff\"><td>TOTAL</td><td>${acct.total_accounts}</td></tr>\n</table>\n<p>MRR: <strong>$${Number(acct.total_mrr||0).toLocaleString()}</strong> | New this week: <strong>${acct.new_this_week}</strong> | Churned (30d): <strong>${acct.churned_30d}</strong></p>\n<h3>Compliance Alerts</h3>\n<table border=\"1\" cellpadding=\"6\" cellspacing=\"0\" style=\"border-collapse:collapse;width:100%\">\n<tr style=\"background:#fce8e6\"><th>Item</th><th>Count</th></tr>\n<tr><td>FedRAMP deadlines due \u226430 days</td><td>${comp.fedramp_due_30d}</td></tr>\n<tr><td>CMMC 2.0 assessments due \u226460 days</td><td>${comp.cmmc_due_60d}</td></tr>\n<tr><td>CJIS Security deadlines due \u226414 days</td><td>${comp.cjis_due_14d}</td></tr>\n<tr><td>FOIA requests CRITICAL (\u22645 biz days)</td><td style=\"color:red;font-weight:bold\">${comp.foia_critical}</td></tr>\n<tr><td>Open POA&M items</td><td>${comp.open_poam_items}</td></tr>\n<tr><td>VPAT/Section 508 updates due \u226460 days</td><td>${comp.vpat_due_60d}</td></tr>\n</table>\n<p style=\"font-size:12px;color:#666\">Generated by n8n on self-hosted infrastructure within FedRAMP authorization boundary.</p>\n</body></html>`;\nreturn [{ json: { html, week, ...acct, ...comp } }];\n"
},
"id": "code5",
"name": "Build HTML Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
640,
400
]
},
{
"parameters": {
"fromEmail": "reports@yourcompany.com",
"toEmail": "ceo@yourcompany.com",
"subject": "GovTech Weekly KPI \u2014 {{ $json.week }} | MRR ${{ $json.total_mrr }} | {{ $json.foia_critical }} FOIA Critical",
"message": "={{ $json.html }}",
"options": {
"appendAttribution": false
}
},
"id": "em5",
"name": "Gmail \u2013 CEO + CISO + GC",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [
840,
400
]
}
],
"connections": {
"Schedule \u2013 Monday 08:00 ET": {
"main": [
[
{
"node": "Postgres \u2013 Account Metrics",
"type": "main",
"index": 0
},
{
"node": "Postgres \u2013 Compliance Snapshot",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2013 Account Metrics": {
"main": [
[
{
"node": "Build HTML Report",
"type": "main",
"index": 0
}
]
]
},
"Postgres \u2013 Compliance Snapshot": {
"main": [
[
{
"node": "Build HTML Report",
"type": "main",
"index": 0
}
]
]
},
"Build HTML Report": {
"main": [
[
{
"node": "Gmail \u2013 CEO + CISO + GC",
"type": "main",
"index": 0
}
]
]
}
}
}
Self-Hosting Is the Architecture of FedRAMP Compliance
When a federal agency's Contracting Officer asks "is your automation platform within your FedRAMP ATO boundary?", the answer cannot be "we use a cloud iPaaS on a separate vendor's infrastructure." Three specific risk vectors:
1. CUI spillage through cloud workflow engines. NIST SP 800-171 Rev2 §3.6.2 requires you to report CUI spillage within 72 hours. If CUI flows through Zapier, Make, or any other cloud automation tool not listed in your System Security Plan (SSP), that is a spillage event every time the workflow runs. CMMC 2.0 Level 2 assessors are now specifically asking about iPaaS tools in scope.
2. FedRAMP subservice organizations. Under FedRAMP, every cloud service that processes federal data must be covered by an ATO — either your own or an inherited ATO from an authorized subservice. A cloud workflow vendor without a FedRAMP Moderate authorization is not a valid subservice. Your SSP's control inheritance doesn't cover them.
3. CJIS configuration management. FBI CJIS Security Policy 5.9.1 §4.3.2 requires configuration management controls for all systems that access CJI. A cloud workflow tool that executes against your CJIS-connected APIs is within your CJIS boundary. Your terminal agency agreement must cover it. Most cloud iPaaS vendors have not completed an FBI CJIS Security Addendum.
Self-hosted n8n on infrastructure already within your authorization boundary — your FedRAMP-authorized cloud, your on-premises data center — eliminates all three vectors. The automation tool is a node in your existing SSP, not a new subservice to assess.
Get the Full FlowKit Template Pack
These five workflows are part of the FlowKit n8n Automation Template Library — 15 import-ready templates for SaaS vendors operating in regulated industries.
Browse all templates at stripeai.gumroad.com
Each template includes:
- Complete n8n workflow JSON (import in 2 clicks)
- Setup guide with configuration checklist
- Compliance notes for each automation type
Free to import. If you build something useful, let me know — always looking to improve coverage for compliance-heavy verticals.
Top comments (0)