If your ConstructionTech SaaS handles OSHA incident records, Davis-Bacon payroll data, or EPA stormwater monitoring, you already have a compliance boundary problem you may not know about.
The core issue: Every time your workflow automation routes OSHA §1904.39 injury investigation records, Davis-Bacon WH-347 certified payroll data, or EPA NPDES discharge monitoring through a cloud iPaaS like Zapier or Make, that data touches an external server outside your legal privilege boundary. DOL Wage and Hour Division subpoenas don't just go to your customer — they go to every vendor in the data chain.
Self-hosted n8n keeps your ConstructionTech data in one place. Here are 5 automations built for the regulations that govern construction SaaS vendors.
The compliance landscape for ConstructionTech SaaS vendors
Your customers operate under a dense stack of overlapping federal and state requirements:
| Regulation | Jurisdiction | Who it hits | Fastest clock |
|---|---|---|---|
| OSHA 29 CFR Part 1926 | Federal | All construction employers | §1904.39: 8h fatality report |
| Davis-Bacon Act 40 USC §3142 | Federal | Federal construction contracts | WH-347 weekly payroll |
| EPA NPDES §402 CGP | Federal | Sites >1 acre disturbed | SWPPP discharge monitoring |
| AIA A201-2017 | Contract | Commercial construction | §15.1.3: 21-day claim notice |
| OSHA Form 300 | Federal | All construction employers | Feb 1 annual posting |
| State prevailing wage | State | State-funded contracts | Varies by state (quarterly typical) |
Seven customer tiers shape how these requirements land in your platform:
- ENTERPRISE_CONSTRUCTION_MGMT_PLATFORM — OSHA §1926 incident record system of record + AIA A201 document retention
- PROJECT_MANAGEMENT_SAAS_VENDOR — AIA A201 §3.2 RFI/submittal/change order chain of custody
- SAFETY_COMPLIANCE_SAAS_VENDOR — OSHA §1904.39 8h/24h incident reporting clocks are your core product
- BIM_DESIGN_COLLABORATION_SAAS — AIA A201 design document retention + federal BIM mandate data sovereignty
- SUBCONTRACTOR_MANAGEMENT_SAAS — Davis-Bacon WH-347 weekly submission + craft classification records
- FIELD_WORKFORCE_MGMT_SAAS — OSHA Form 300 + Davis-Bacon field data = DOL audit boundary
- CONSTRUCTIONTECH_STARTUP — Start with OSHA Form 300 and Davis-Bacon basics for enterprise procurement
Workflow 1: Tier-segmented customer onboarding drip
Injects the right compliance context at Day 0 based on customer tier and compliance flags (DAVIS_BACON_FEDERAL_CONTRACTOR, EPA_NPDES_STORMWATER_PERMIT, OSHA_1926_CONSTRUCTION_SUBJECT). Day 3 reinforces the 8-hour OSHA fatality clock. Day 8 sends pre-built workflow links for Davis-Bacon, OSHA Form 300, and EPA NPDES.
{
"name": "ConstructionTech Customer Onboarding Drip",
"nodes": [
{
"id": "n1",
"name": "New Customer Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"parameters": {
"sheetId": "YOUR_SHEET_ID",
"range": "Customers!A:M",
"event": "rowAdded"
}
},
{
"id": "n2",
"name": "Extract & Segment Customer",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst row = $input.first().json;\nconst tier = row.customer_tier || 'CONSTRUCTIONTECH_STARTUP';\nconst flags = (row.compliance_flags || '').split(',').map(f => f.trim());\n\nconst tierNotes = {\n ENTERPRISE_CONSTRUCTION_MGMT_PLATFORM: 'OSHA 29 CFR Part 1926 incident investigation records in your system are DOL subpoena targets \u2014 architecture brief in Day 0 email.',\n PROJECT_MANAGEMENT_SAAS_VENDOR: 'AIA A201 \u00a73.2 RFI/submittal/change order retention: 10-year litigation hold window for project closeout claims.',\n SAFETY_COMPLIANCE_SAAS_VENDOR: 'OSHA \u00a71904.39 severe injury 24h / fatality 8h notification clocks \u2014 your incident pipeline is the compliance boundary.',\n BIM_DESIGN_COLLABORATION_SAAS: 'AIA A201 \u00a73.2 design document retention + NIST BIM IFC data sovereignty for federal BIM mandate projects.',\n SUBCONTRACTOR_MANAGEMENT_SAAS: 'Davis-Bacon 40 USC \u00a73142 certified payroll (WH-347 weekly) \u2014 prevailing wage data in cloud iPaaS = DOL WHD audit exposure.',\n FIELD_WORKFORCE_MGMT_SAAS: 'OSHA Form 300 injury log + Davis-Bacon craft classification records \u2014 field data sovereignty for DOL compliance boundary.',\n CONSTRUCTIONTECH_STARTUP: 'Start with OSHA Form 300 and Davis-Bacon basics \u2014 fastest path to enterprise procurement.'\n};\n\nconst flagNotes = [];\nif (flags.includes('DAVIS_BACON_FEDERAL_CONTRACTOR')) flagNotes.push('Davis-Bacon WH-347 certified payroll weekly submission active for this account.');\nif (flags.includes('EPA_NPDES_STORMWATER_PERMIT')) flagNotes.push('EPA NPDES \u00a7402 stormwater SWPPP discharge monitoring data must stay in environmental compliance perimeter.');\nif (flags.includes('OSHA_1926_CONSTRUCTION_SUBJECT')) flagNotes.push('OSHA 29 CFR Part 1926 construction safety standards apply \u2014 incident investigation records in scope.');\n\nreturn [{\n json: {\n customer_id: row.customer_id,\n company_name: row.company_name,\n contact_email: row.contact_email,\n tier,\n flags,\n tier_note: tierNotes[tier] || tierNotes.CONSTRUCTIONTECH_STARTUP,\n flag_notes: flagNotes.join(' '),\n onboarding_started: new Date().toISOString(),\n crm_url: `https://crm.example.com/accounts/${row.customer_id}`\n }\n}];\n"
}
},
{
"id": "n3",
"name": "Day 0 Welcome Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.contact_email }}",
"subject": "Welcome to FlowKit \u2014 your n8n automation is ready",
"message": "={{ 'Hi ' + $json.company_name + ',\\n\\nYour n8n automation environment is live.\\n\\n' + $json.tier_note + '\\n\\n' + ($json.flag_notes ? $json.flag_notes + '\\n\\n' : '') + 'Book your onboarding call: https://cal.example.com/onboarding\\n\\nThe FlowKit Team' }}"
}
},
{
"id": "n4",
"name": "Log to Sheets",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "append",
"sheetId": "YOUR_SHEET_ID",
"range": "OnboardingLog!A:G",
"values": [
[
"={{ $json.customer_id }}",
"={{ $json.company_name }}",
"={{ $json.tier }}",
"={{ $json.flags.join(',') }}",
"Day0",
"={{ new Date().toISOString() }}",
"sent"
]
]
}
},
{
"id": "n5",
"name": "Wait 3 Days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 3,
"unit": "days"
}
},
{
"id": "n6",
"name": "Day 3 Check-In Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.contact_email }}",
"subject": "Day 3: Your first workflow \u2014 any questions?",
"message": "={{ 'Hi ' + $json.company_name + ',\\n\\nChecking in \u2014 have you triggered your first automation?\\n\\nTop tip for ' + $json.tier + ': configure your OSHA incident pipeline early \u2014 the 8-hour fatality reporting clock starts at discovery.\\n\\nReply to this email or book a call.\\n\\nThe FlowKit Team' }}"
}
},
{
"id": "n7",
"name": "Wait 5 Days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 5,
"unit": "days"
}
},
{
"id": "n8",
"name": "Day 8 Feature Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.contact_email }}",
"subject": "Day 8: 3 workflows your competitors are already running",
"message": "={{ 'Hi ' + $json.company_name + ',\\n\\n3 workflows live customers run on Day 8:\\n\\n1. Davis-Bacon WH-347 certified payroll weekly deadline tracker (DOL WHD audit compliance)\\n2. OSHA Form 300 annual posting reminder (Feb 1 deadline \u2014 OSHA \u00a71904.32)\\n3. EPA NPDES stormwater SWPPP review scheduler (permit renewal compliance)\\n\\nAll 3 are pre-built in your template library.\\n\\nThe FlowKit Team' }}"
}
},
{
"id": "n9",
"name": "Wait 6 Days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 6,
"unit": "days"
}
},
{
"id": "n10",
"name": "Day 14 QBR / Upgrade Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.contact_email }}",
"subject": "Day 14: Book your 30-min QBR",
"message": "={{ 'Hi ' + $json.company_name + ',\\n\\nTwo weeks in \u2014 time for a quick review of your compliance automation coverage.\\n\\nBook your 30-min QBR: https://cal.example.com/qbr\\n\\nAgenda: OSHA/Davis-Bacon/EPA workflow gaps, upgrade path to Enterprise tier.\\n\\nThe FlowKit Team' }}"
}
}
],
"connections": {
"n1": {
"main": [
[
"n2"
]
]
},
"n2": {
"main": [
[
"n3"
]
]
},
"n3": {
"main": [
[
"n4"
]
]
},
"n4": {
"main": [
[
"n5"
]
]
},
"n5": {
"main": [
[
"n6"
]
]
},
"n6": {
"main": [
[
"n7"
]
]
},
"n7": {
"main": [
[
"n8"
]
]
},
"n8": {
"main": [
[
"n9"
]
]
},
"n9": {
"main": [
[
"n10"
]
]
}
}
}
Workflow 2: OSHA/Davis-Bacon/AIA/EPA deadline tracker
Runs daily at 7AM against a Google Sheet of compliance deadlines. 12 deadline types with regulation-specific urgency notes. Routes OVERDUE/IMMEDIATE/CRITICAL items to Slack #compliance-critical and emails the compliance owner directly.
Deadline types covered:
-
OSHA_FATALITY_REPORT— OSHA §1904.39: 8h oral report after fatality discovery (fastest clock) -
OSHA_SEVERE_INJURY_REPORT— §1904.39: 24h from employer learning of hospitalization/amputation/eye loss -
OSHA_FORM_300_ANNUAL_SUMMARY_POSTING— Form 300A posted Feb 1 through Apr 30 -
DAVIS_BACON_CERTIFIED_PAYROLL_WEEKLY— WH-347 weekly for federal construction contracts -
DAVIS_BACON_ANNUAL_WAGE_DETERMINATION_REVIEW— SAM.gov prevailing wage rate review by craft -
EPA_NPDES_STORMWATER_SWPPP_ANNUAL_REVIEW— CGP permit holder annual SWPPP update -
EPA_NPDES_CONSTRUCTION_PERMIT_RENEWAL— EPA §402 CGP permit renewal authorization -
AIA_A201_PROJECT_CLOSEOUT_RETENTION— 10-year record retention post-substantial completion -
OSHA_1926_SAFETY_TRAINING_ANNUAL— Part 1926 Subpart E training records 3-year minimum -
PREVAILING_WAGE_QUARTERLY_REPORT— State prevailing wage (CA DIR/NY DOL/IL IDOL varies) -
SOC2_TYPE2_RENEWAL— Annual audit cycle for enterprise ConstructionTech procurement -
ANNUAL_PENTEST— SOC 2 CC7.1 penetration testing requirement
{
"name": "ConstructionTech OSHA/Davis-Bacon/AIA/EPA Deadline Tracker",
"nodes": [
{
"id": "d1",
"name": "Daily 7AM Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 7 * * *"
}
]
}
}
},
{
"id": "d2",
"name": "Read Compliance Deadlines",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"sheetId": "YOUR_SHEET_ID",
"range": "ComplianceDeadlines!A:G"
}
},
{
"id": "d3",
"name": "Classify Urgency",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst today = new Date();\nconst deadlines = $input.all().map(item => {\n const d = item.json;\n const dueDate = new Date(d.due_date);\n const daysUntil = Math.ceil((dueDate - today) / (1000 * 60 * 60 * 24));\n\n const typeClocks = {\n OSHA_FATALITY_REPORT: { urgencyNote: 'OSHA \u00a71904.39 \u2014 8h oral report to OSHA Area Office after fatality discovery', fastest: true },\n OSHA_SEVERE_INJURY_REPORT: { urgencyNote: 'OSHA \u00a71904.39 \u2014 24h report for inpatient hospitalization, amputation, or eye loss', fastest: true },\n OSHA_FORM_300_ANNUAL_SUMMARY_POSTING: { urgencyNote: 'OSHA Form 300A must be posted Feb 1 through Apr 30 \u2014 \u00a71904.32', fastest: false },\n DAVIS_BACON_CERTIFIED_PAYROLL_WEEKLY: { urgencyNote: 'Davis-Bacon 40 USC \u00a73142 \u2014 WH-347 certified payroll due weekly for federal construction contracts', fastest: false },\n DAVIS_BACON_ANNUAL_WAGE_DETERMINATION_REVIEW: { urgencyNote: 'DOL wage determination review \u2014 check SAM.gov for current prevailing wage rates by craft classification', fastest: false },\n EPA_NPDES_STORMWATER_SWPPP_ANNUAL_REVIEW: { urgencyNote: 'EPA NPDES \u00a7402 \u2014 SWPPP annual review and update required for CGP permit holders', fastest: false },\n EPA_NPDES_CONSTRUCTION_PERMIT_RENEWAL: { urgencyNote: 'EPA Construction General Permit (CGP) renewal \u2014 EPA \u00a7402 stormwater discharge authorization', fastest: false },\n AIA_A201_PROJECT_CLOSEOUT_RETENTION: { urgencyNote: 'AIA A201 \u00a73.5 + \u00a715.1.2 \u2014 project record retention 10 years post-substantial completion', fastest: false },\n OSHA_1926_SAFETY_TRAINING_ANNUAL: { urgencyNote: 'OSHA 29 CFR Part 1926 Subpart E \u2014 safety training records maintained 3 years minimum', fastest: false },\n PREVAILING_WAGE_QUARTERLY_REPORT: { urgencyNote: 'State prevailing wage quarterly payroll report \u2014 varies by state (CA DIR/NY DOL/IL IDOL)', fastest: false },\n SOC2_TYPE2_RENEWAL: { urgencyNote: 'SOC 2 Type II audit renewal \u2014 CC9.2 vendor management scope includes n8n as infrastructure', fastest: false },\n ANNUAL_PENTEST: { urgencyNote: 'Annual penetration test \u2014 required for enterprise ConstructionTech procurement and SOC 2 CC7.1', fastest: false }\n };\n\n const info = typeClocks[d.deadline_type] || { urgencyNote: 'Compliance deadline', fastest: false };\n\n let urgency;\n if (daysUntil < 0) urgency = 'OVERDUE';\n else if (daysUntil <= 1 && info.fastest) urgency = 'IMMEDIATE';\n else if (daysUntil <= 7) urgency = 'CRITICAL';\n else if (daysUntil <= 21) urgency = 'URGENT';\n else if (daysUntil <= 45) urgency = 'WARNING';\n else urgency = 'NOTICE';\n\n return { ...d, daysUntil, urgency, urgencyNote: info.urgencyNote };\n}).filter(d => d.urgency !== 'NOTICE');\n\nreturn deadlines.map(d => ({ json: d }));\n"
}
},
{
"id": "d4",
"name": "Route by Urgency",
"type": "n8n-nodes-base.switch",
"parameters": {
"rules": {
"rules": [
{
"value1": "={{ $json.urgency }}",
"operation": "equals",
"value2": "OVERDUE"
},
{
"value1": "={{ $json.urgency }}",
"operation": "equals",
"value2": "IMMEDIATE"
},
{
"value1": "={{ $json.urgency }}",
"operation": "equals",
"value2": "CRITICAL"
}
]
}
}
},
{
"id": "d5",
"name": "Slack #compliance-critical",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#compliance-critical",
"text": "={{ '\ud83d\udea8 ' + $json.urgency + ': ' + $json.deadline_type + ' \u2014 ' + $json.daysUntil + 'd. ' + $json.urgencyNote + ' \u2014 Owner: ' + $json.owner }}"
}
},
{
"id": "d6",
"name": "Email Compliance Owner",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.owner_email }}",
"subject": "={{ '[' + $json.urgency + '] ' + $json.deadline_type + ' \u2014 ' + $json.daysUntil + ' days' }}",
"message": "={{ $json.deadline_type + ' deadline in ' + $json.daysUntil + ' days.\\n\\n' + $json.urgencyNote + '\\n\\nCustomer: ' + $json.customer_name + '\\nDue: ' + $json.due_date + '\\nOwner: ' + $json.owner }}"
}
}
],
"connections": {
"d1": {
"main": [
[
"d2"
]
]
},
"d2": {
"main": [
[
"d3"
]
]
},
"d3": {
"main": [
[
"d4"
]
]
},
"d4": {
"main": [
[
"d5"
],
[
"d5"
],
[
"d5"
]
]
},
"d5": {
"main": [
[
"d6"
]
]
}
}
}
Workflow 3: ConstructionTech API health monitor
Polls five critical endpoints every 15 minutes with compliance annotations. The 15-minute interval is tighter than the OSHA §1904.39 8h fatality clock, ensuring you detect a safety incident API failure before a reporting window slips.
Endpoints and compliance mapping:
-
project_mgmt_api— OSHA 29 CFR Part 1926 incident investigation record integrity -
bim_collaboration_api— AIA A201 §3.2 design document chain of custody -
payroll_api— Davis-Bacon 40 USC §3142 certified payroll weekly clock; downtime = WH-347 delay risk -
safety_incident_api— OSHA §1904.39 severe injury 24h / fatality 8h clock -
stormwater_api— EPA NPDES §402 SWPPP discharge monitoring
{
"name": "ConstructionTech BIM/Safety API Health Monitor",
"nodes": [
{
"id": "m1",
"name": "Every 15 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "*/15 * * * *"
}
]
}
}
},
{
"id": "m2",
"name": "Read API Endpoints",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"sheetId": "YOUR_SHEET_ID",
"range": "ApiEndpoints!A:D"
}
},
{
"id": "m3",
"name": "Ping Each Endpoint",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"url": "={{ $json.endpoint_url }}",
"method": "GET",
"timeout": 5000
}
},
{
"id": "m4",
"name": "Classify Health Status",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst endpoints = $input.all().map(item => {\n const d = item.json;\n const complianceAnnotations = {\n project_mgmt_api: 'OSHA 29 CFR Part 1926 \u2014 incident investigation records integrity; downtime = OSHA \u00a71904.39 reporting gap risk',\n bim_collaboration_api: 'AIA A201 \u00a73.2 design document retention \u2014 RFI/submittal/change order data chain of custody',\n payroll_api: 'Davis-Bacon 40 USC \u00a73142 \u2014 certified payroll weekly clock; downtime = WH-347 submission delay risk (DOL WHD)',\n safety_incident_api: 'OSHA \u00a71904.39 \u2014 severe injury 24h clock / fatality 8h clock; downtime = reporting window risk',\n stormwater_api: 'EPA NPDES \u00a7402 \u2014 SWPPP discharge monitoring data; downtime = CGP permit deviation'\n };\n\n const latency = d.responseTime || 9999;\n let status;\n if (d.statusCode >= 200 && d.statusCode < 300 && latency < 2000) status = 'HEALTHY';\n else if (d.statusCode >= 200 && d.statusCode < 300 && latency >= 2000) status = 'DEGRADED';\n else status = 'DOWN';\n\n return {\n endpoint_name: d.endpoint_name,\n status,\n statusCode: d.statusCode,\n latency,\n compliance_note: complianceAnnotations[d.endpoint_name] || 'ConstructionTech compliance boundary',\n checked_at: new Date().toISOString()\n };\n}).filter(e => e.status !== 'HEALTHY');\n\nreturn endpoints.length > 0 ? endpoints.map(e => ({ json: e })) : [{ json: { all_healthy: true } }];\n"
}
},
{
"id": "m5",
"name": "Alert Slack #construction-ops",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#construction-ops",
"text": "={{ '\u26a0\ufe0f API ' + $json.status + ': ' + $json.endpoint_name + ' (' + $json.latency + 'ms). ' + $json.compliance_note }}"
}
}
],
"connections": {
"m1": {
"main": [
[
"m2"
]
]
},
"m2": {
"main": [
[
"m3"
]
]
},
"m3": {
"main": [
[
"m4"
]
]
},
"m4": {
"main": [
[
"m5"
]
]
}
}
}
Workflow 4: OSHA/Davis-Bacon/EPA incident pipeline
Webhook endpoint that immediately ACKs with HTTP 200, then routes through a compliance matrix. Eight incident types with regulation-specific clocks, escalation lists, and authority contacts.
Incident types and clocks:
| Incident Type | Clock | Authority | Regulation |
|---|---|---|---|
OSHA_FATALITY_REPORT |
8 hours | OSHA Area Office (oral) | §1904.39 |
OSHA_SEVERE_INJURY_REPORT |
24 hours | OSHA Area Office | §1904.39 |
OSHA_CITATION_RECEIVED |
IMMEDIATE — 15 working days to contest | OSHA Area Office | §659 |
EPA_STORMWATER_DISCHARGE_VIOLATION |
14 days | EPA Region / State agency | NPDES §402 |
DAVIS_BACON_WAGE_VIOLATION_COMPLAINT |
IMMEDIATE — DOL WHD audit | DOL Wage and Hour Division | 40 USC §3142 |
AIA_A201_CLAIM_FILED |
21 days | Architect/Owner | AIA A201 §15.1.3 |
SITE_SAFETY_EMERGENCY |
IMMEDIATE | Emergency Services + OSHA | 29 CFR Part 1926 |
DATA_BREACH_CONSTRUCTION_PII |
72 hours | State AG / CCPA / GDPR | §1798.150 / Art.33 |
Fastest clocks: OSHA_FATALITY_REPORT (8h) and OSHA_SEVERE_INJURY_REPORT (24h)
{
"name": "ConstructionTech OSHA/Davis-Bacon/EPA Incident Pipeline",
"nodes": [
{
"id": "i1",
"name": "Incident Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "construction-incident",
"responseMode": "responseNode"
}
},
{
"id": "i2",
"name": "Immediate 200 ACK",
"type": "n8n-nodes-base.respondToWebhook",
"parameters": {
"responseCode": 200,
"responseBody": "{\"status\":\"received\"}"
}
},
{
"id": "i3",
"name": "Classify & Route Incident",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst p = $input.first().json.body || $input.first().json;\nconst type = p.incident_type;\n\nconst incidentMatrix = {\n OSHA_FATALITY_REPORT: {\n urgency: 'P0',\n clock: '8 hours',\n authority: 'OSHA Area Office (oral report required)',\n regulation: 'OSHA \u00a71904.39 \u2014 must report within 8 hours of learning of a work-related fatality',\n slackChannel: '#safety-critical',\n escalateTo: ['CEO', 'CCO', 'Legal', 'EHS Director'],\n note: 'FASTEST CLOCK \u2014 8h from discovery. Written follow-up within 8h. OSHA investigation may follow.'\n },\n OSHA_SEVERE_INJURY_REPORT: {\n urgency: 'P0',\n clock: '24 hours',\n authority: 'OSHA Area Office',\n regulation: 'OSHA \u00a71904.39 \u2014 inpatient hospitalization, amputation, or loss of an eye within 24h of employer learning',\n slackChannel: '#safety-critical',\n escalateTo: ['CCO', 'EHS Director', 'Legal'],\n note: '24h from employer learning of injury \u2014 not from date of injury'\n },\n OSHA_CITATION_RECEIVED: {\n urgency: 'P1',\n clock: 'IMMEDIATE \u2014 15 working days to contest',\n authority: 'OSHA Area Office',\n regulation: 'OSHA \u00a7659 \u2014 15 working-day contest window starts on receipt date',\n slackChannel: '#compliance-critical',\n escalateTo: ['Legal', 'EHS Director', 'COO'],\n note: 'Miss 15-day window = citation becomes final order; penalties not contestable'\n },\n EPA_STORMWATER_DISCHARGE_VIOLATION: {\n urgency: 'P1',\n clock: '14 days',\n authority: 'EPA Region / State environmental agency',\n regulation: 'EPA NPDES \u00a7402 CGP \u2014 discharge outside permit conditions must be reported',\n slackChannel: '#compliance-critical',\n escalateTo: ['Environmental Compliance', 'COO'],\n note: 'SWPPP best management practices failure \u2014 document corrective actions immediately'\n },\n DAVIS_BACON_WAGE_VIOLATION_COMPLAINT: {\n urgency: 'P1',\n clock: 'IMMEDIATE \u2014 DOL WHD investigation',\n authority: 'DOL Wage and Hour Division',\n regulation: 'Davis-Bacon 40 USC \u00a73142 \u2014 prevailing wage underpayment complaint triggers WHD audit',\n slackChannel: '#compliance-critical',\n escalateTo: ['Legal', 'Payroll Compliance', 'CFO'],\n note: 'Preserve all WH-347 certified payroll records \u2014 WHD subpoena typically covers 2-3 year lookback'\n },\n AIA_A201_CLAIM_FILED: {\n urgency: 'P2',\n clock: '21 days \u2014 AIA A201 \u00a715.1.3 notice requirement',\n authority: 'Architect/Owner per contract',\n regulation: 'AIA A201 \u00a715.1.3 \u2014 initial decision request must be filed within 21 days of claim notice',\n slackChannel: '#legal-compliance',\n escalateTo: ['Legal', 'Project Manager'],\n note: 'Preserve all RFI/submittal/change order records for dispute \u2014 AIA A201 \u00a73.2 document retention'\n },\n SITE_SAFETY_EMERGENCY: {\n urgency: 'P0',\n clock: 'IMMEDIATE',\n authority: 'Emergency Services + OSHA Area Office',\n regulation: 'OSHA 29 CFR Part 1926 Subpart C \u2014 safety emergency protocols',\n slackChannel: '#safety-critical',\n escalateTo: ['EHS Director', 'Site Superintendent', 'COO'],\n note: 'Follow emergency response plan \u2014 document all response actions for OSHA investigation'\n },\n DATA_BREACH_CONSTRUCTION_PII: {\n urgency: 'P2',\n clock: '72 hours',\n authority: 'State AG / CCPA / GDPR supervisory authority',\n regulation: 'CCPA \u00a71798.150 / GDPR Art.33 \u2014 notify within 72h of breach discovery',\n slackChannel: '#security-incident',\n escalateTo: ['CISO', 'Legal', 'DPO'],\n note: 'Worker PII (SSN, payroll data) in construction records \u2014 Davis-Bacon records subject to CCPA'\n }\n};\n\nconst info = incidentMatrix[type] || incidentMatrix.SITE_SAFETY_EMERGENCY;\n\nreturn [{\n json: {\n incident_id: p.incident_id || `INC-${Date.now()}`,\n incident_type: type,\n customer_id: p.customer_id,\n customer_name: p.customer_name,\n project_name: p.project_name,\n description: p.description,\n reported_by: p.reported_by,\n reported_at: new Date().toISOString(),\n ...info\n }\n}];\n"
}
},
{
"id": "i4",
"name": "Alert Slack",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "={{ $json.slackChannel }}",
"text": "={{ '\ud83d\udea8 ' + $json.urgency + ' | ' + $json.incident_type + ' | ' + $json.customer_name + ' | Project: ' + $json.project_name + '\\nClock: ' + $json.clock + ' \u2014 Authority: ' + $json.authority + '\\nReg: ' + $json.regulation + '\\nNote: ' + $json.note }}"
}
},
{
"id": "i5",
"name": "Log to Sheets",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "append",
"sheetId": "YOUR_SHEET_ID",
"range": "IncidentLog!A:K",
"values": [
[
"={{ $json.incident_id }}",
"={{ $json.incident_type }}",
"={{ $json.customer_id }}",
"={{ $json.project_name }}",
"={{ $json.urgency }}",
"={{ $json.clock }}",
"={{ $json.authority }}",
"={{ $json.regulation }}",
"={{ $json.reported_by }}",
"={{ $json.reported_at }}",
"OPEN"
]
]
}
}
],
"connections": {
"i1": {
"main": [
[
"i2",
"i3"
]
]
},
"i3": {
"main": [
[
"i4"
]
]
},
"i4": {
"main": [
[
"i5"
]
]
}
}
}
Workflow 5: Weekly ConstructionTech KPI dashboard
Monday 8AM executive briefing tracking MRR, active customers, and open compliance counts: OSHA incidents, Davis-Bacon violations, EPA NPDES pending, AIA A201 claims. Uses $getWorkflowStaticData for WoW MRR comparison. Emails CEO with BCC to CISO and CCO.
{
"name": "Weekly ConstructionTech KPI Dashboard",
"nodes": [
{
"id": "k1",
"name": "Monday 8AM Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "k2",
"name": "Read Platform Metrics",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"sheetId": "YOUR_SHEET_ID",
"range": "PlatformMetrics!A:Z"
}
},
{
"id": "k3",
"name": "Read Compliance Events",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"sheetId": "YOUR_SHEET_ID",
"range": "ComplianceEvents!A:J"
}
},
{
"id": "k4",
"name": "Build KPI Report",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "\nconst metrics = $input.all()[0]?.json || {};\nconst prevMetrics = $getWorkflowStaticData('global');\n\nconst mrr = parseFloat(metrics.mrr_usd || 0);\nconst prevMrr = parseFloat(prevMetrics.mrr_usd || 0);\nconst mrrWoW = prevMrr > 0 ? (((mrr - prevMrr) / prevMrr) * 100).toFixed(1) : 'N/A';\n\nconst active = parseInt(metrics.active_customers || 0);\nconst osha_open = parseInt(metrics.osha_incidents_open || 0);\nconst davis_bacon_open = parseInt(metrics.davis_bacon_violations_open || 0);\nconst epa_npdes_open = parseInt(metrics.epa_npdes_pending || 0);\nconst aia_claims_open = parseInt(metrics.aia_claims_open || 0);\nconst safety_trainings = parseInt(metrics.safety_training_completions_7d || 0);\nconst api_calls = parseInt(metrics.api_calls_7d || 0);\n\n$setWorkflowStaticData('global', { mrr_usd: mrr });\n\nconst html = `<h2>ConstructionTech Weekly KPI \u2014 ${new Date().toLocaleDateString()}</h2>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse\">\n<tr><th>Metric</th><th>Value</th><th>WoW</th></tr>\n<tr><td>MRR</td><td>$${mrr.toLocaleString()}</td><td>${mrrWoW}%</td></tr>\n<tr><td>Active Customers</td><td>${active}</td><td>\u2014</td></tr>\n<tr><td>API Calls (7d)</td><td>${api_calls.toLocaleString()}</td><td>\u2014</td></tr>\n<tr><td style=\"color:${osha_open>0?'red':'green'}\">OSHA Incidents Open</td><td>${osha_open}</td><td>\u2014</td></tr>\n<tr><td style=\"color:${davis_bacon_open>0?'red':'green'}\">Davis-Bacon Violations Open</td><td>${davis_bacon_open}</td><td>\u2014</td></tr>\n<tr><td style=\"color:${epa_npdes_open>0?'orange':'green'}\">EPA NPDES Pending</td><td>${epa_npdes_open}</td><td>\u2014</td></tr>\n<tr><td style=\"color:${aia_claims_open>0?'orange':'green'}\">AIA A201 Claims Open</td><td>${aia_claims_open}</td><td>\u2014</td></tr>\n<tr><td>Safety Trainings (7d)</td><td>${safety_trainings}</td><td>\u2014</td></tr>\n</table>`;\n\nreturn [{ json: { html, mrr, active, osha_open, davis_bacon_open, epa_npdes_open, aia_claims_open } }];\n"
}
},
{
"id": "k5",
"name": "Email CEO + BCC CISO",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "ceo@example.com",
"bcc": "ciso@example.com,cco@example.com",
"subject": "ConstructionTech Weekly KPI",
"message": "={{ $json.html }}",
"messageType": "html"
}
},
{
"id": "k6",
"name": "Slack #management One-Liner",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#management",
"text": "={{ 'Weekly KPI: MRR $' + $json.mrr.toLocaleString() + ' | Customers ' + $json.active + ' | OSHA Open ' + $json.osha_open + ' | Davis-Bacon Open ' + $json.davis_bacon_open + ' | EPA Pending ' + $json.epa_npdes_open + ' | AIA Claims ' + $json.aia_claims_open }}"
}
}
],
"connections": {
"k1": {
"main": [
[
"k2"
]
]
},
"k2": {
"main": [
[
"k3"
]
]
},
"k3": {
"main": [
[
"k4"
]
]
},
"k4": {
"main": [
[
"k5"
]
]
},
"k5": {
"main": [
[
"k6"
]
]
}
}
}
Why self-hosted n8n for ConstructionTech SaaS
| Compliance requirement | Cloud iPaaS risk | Self-hosted n8n solution |
|---|---|---|
| OSHA §1904.39 incident records | DOL subpoena outside privilege boundary — cloud vendor receives subpoena | Records stay in your VPC; legal privilege intact |
| Davis-Bacon WH-347 certified payroll | Prevailing wage data in Zapier = DOL WHD audit data outside perimeter | Payroll data in compliance boundary; WHD audit scope controlled |
| EPA NPDES SWPPP discharge monitoring | Environmental monitoring data in cloud = EPA audit chain gap | Discharge data in environmental compliance perimeter |
| AIA A201 project closeout records | RFI/change order history in cloud = litigation discovery risk | 10-year retention in your document management perimeter |
| OSHA Form 300 injury log | Worker injury data in cloud iPaaS = EEOC discovery exposure | Injury records in OSHA-compliant boundary |
Quick setup
- Import each workflow JSON into your n8n instance
- Set your Google Sheets IDs in all nodes
- Configure Slack webhook URLs for
#compliance-critical,#safety-critical,#construction-ops - Populate
ComplianceDeadlinessheet with your customers' deadline data - Set
POST /construction-incidentwebhook URL in your safety incident system
All 5 workflows are included in the FlowKit n8n Template Library at stripeai.gumroad.com. The complete bundle includes 15 production-ready templates for $97.
Compare: n8n vs Zapier/Make for ConstructionTech SaaS
| Capability | n8n (self-hosted) | Zapier / Make |
|---|---|---|
| OSHA record privacy | In your VPC | Data transits cloud |
| Davis-Bacon payroll data | In compliance boundary | Routes through cloud |
| EPA SWPPP monitoring data | In environmental perimeter | External server |
| AIA A201 retention control | Your document system | Cloud vendor data |
| 8h OSHA fatality clock | Sub-1-min trigger | Cloud latency |
| Cost at scale | Fixed hosting | Per-task pricing |
Questions? Drop them in the comments — I respond to all OSHA/Davis-Bacon/EPA questions.
Top comments (0)