This workflow corresponds to n8n.io template #secrets-registry-verify-v1 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Secrets Registry Verify",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "secrets-registry-verify",
"options": {
"rawBody": false
},
"authentication": "headerAuth",
"responseMode": "lastNode"
},
"id": "webhook-trigger",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
200,
300
],
"typeVersion": 2
},
{
"parameters": {},
"id": "manual-trigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
200,
500
],
"typeVersion": 1
},
{
"parameters": {
"jsCode": "// Load manifest (inline; sync with n8n/secrets.manifest.yml). Validate schema.\nconst manifest = {\n version: '1.0',\n secrets: [\n { name: 'N8N_API_KEY', source: 'ENV', required: true },\n { name: 'N8N_ENCRYPTION_KEY', source: 'ENV', required: true },\n { name: 'SUPABASE_SERVICE_ROLE_KEY', source: 'ENV', required: true },\n { name: 'ANTHROPIC_API_KEY', source: 'ENV', required: true },\n { name: 'OPENAI_API_KEY', source: 'ENV', required: true },\n { name: 'MONDAY_API_TOKEN', source: 'ENV', required: false },\n { name: 'CLOUDFLARE_API_TOKEN', source: 'ENV', required: false },\n { name: 'COMMANDER_WEBHOOK_TOKEN', source: 'ENV', required: true },\n { name: 'VAULT_MASTER_KEY', source: 'ENV', required: false },\n { name: 'FIRECRAWL_API_KEY', source: 'ENV', required: false },\n { name: 'GRAFANA_PASSWORD', source: 'ENV', required: false }\n ],\n n8n_credentials: [\n { type: 'supabaseApi', name: 'Prod - Supabase Service Role' },\n { type: 'anthropicApi', name: 'Prod - Anthropic Claude' },\n { type: 'anthropicApi', name: 'AnthropicApi' },\n { type: 'openAiApi', name: 'Prod - OpenAI' },\n { type: 'gmailOAuth2', name: 'Prod - Gmail' },\n { type: 'googleSheetsOAuth2Api', name: 'Prod - Google Sheets' },\n { type: 'mondayComApi', name: 'Prod - Monday.com' }\n ]\n};\nconst schemaOk = manifest.version && Array.isArray(manifest.secrets) && manifest.secrets.every(s => s.name && s.source && s.required !== undefined);\nif (!schemaOk) throw new Error('Manifest schema invalid');\nreturn [{ json: manifest }];"
},
"id": "load-manifest",
"name": "Load Manifest",
"type": "n8n-nodes-base.code",
"position": [
480,
400
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Check ENV secrets by inspecting process.env.\n// NEVER output actual values \u2014 only presence.\nconst manifest = $input.first().json;\nconst results = { ok: true, missing: [], present: [], warnings: [] };\n\nfor (const secret of manifest.secrets) {\n if (secret.source === 'ENV') {\n const val = process.env[secret.name];\n if (!val || val.startsWith('paste-your-')) {\n if (secret.required) {\n results.missing.push(secret.name);\n results.ok = false;\n } else {\n results.warnings.push(`${secret.name} (optional) not set`);\n }\n } else {\n results.present.push(secret.name);\n }\n }\n}\n\nresults.env_checked = manifest.secrets.filter(s => s.source === 'ENV').length;\nreturn [{ json: results }];"
},
"id": "check-env-secrets",
"name": "Check ENV Secrets",
"type": "n8n-nodes-base.code",
"position": [
720,
300
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Check VAULT_REF secrets via vault adapter (existence only).\nconst vaultBase = process.env.VAULT_BASE_URL || 'http://localhost:4000';\nconst envResults = $input.first().json;\nconst manifest = $('Load Manifest').first().json;\nconst vaultNames = (manifest.secrets || []).filter(s => s.source === 'VAULT_REF').map(s => s.name);\nif (vaultNames.length === 0) vaultNames.push('VAULT_MASTER_KEY');\nconst vaultResults = { vault_checked: 0, vault_present: [], vault_missing: [] };\nfor (const name of vaultNames) {\n if (envResults.present && envResults.present.includes(name)) continue;\n try {\n const resp = await fetch(`${vaultBase}/secret/${name}`);\n vaultResults.vault_checked++;\n if (resp.ok) vaultResults.vault_present.push(name);\n else vaultResults.vault_missing.push(name);\n } catch (e) {\n vaultResults.vault_missing.push(name);\n envResults.warnings = envResults.warnings || [];\n envResults.warnings.push(`Vault unreachable for ${name}: ${e.message}`);\n }\n}\nreturn [{ json: { ...envResults, ...vaultResults } }];"
},
"id": "check-vault-secrets",
"name": "Check Vault Secrets",
"type": "n8n-nodes-base.code",
"position": [
960,
300
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Check n8n credentials via the n8n API (existence only, names only).\nconst report = $input.first().json;\nconst manifest = $('Load Manifest').first().json;\nconst n8nBase = (process.env.N8N_BASE_URL || process.env.N8N_URL || '').replace(/\\/$/, '');\nconst n8nApiKey = process.env.N8N_API_KEY;\nconst credResults = { creds_checked: 0, creds_present: [], creds_missing: [] };\nconst credList = manifest.n8n_credentials || [];\n\nif (n8nBase && n8nApiKey) {\n try {\n const resp = await fetch(`${n8nBase}/api/v1/credentials`, {\n headers: { 'X-N8N-API-KEY': n8nApiKey, 'Accept': 'application/json' }\n });\n if (resp.ok) {\n const data = await resp.json();\n const existingNames = (data.data || []).map(c => c.name);\n for (const cred of credList) {\n credResults.creds_checked++;\n if (existingNames.includes(cred.name)) {\n credResults.creds_present.push(cred.name);\n } else {\n credResults.creds_missing.push(cred.name);\n }\n }\n } else {\n report.warnings.push(`n8n API returned ${resp.status}`);\n }\n } catch (e) {\n report.warnings.push(`n8n API unreachable: ${e.message}`);\n }\n} else {\n report.warnings.push('N8N_BASE_URL or N8N_API_KEY not set \u2014 skipping credential check');\n}\n\nif (credResults.creds_missing.length > 0) report.ok = false;\n\nreturn [{ json: { ...report, ...credResults } }];"
},
"id": "check-n8n-creds",
"name": "Check n8n Credentials",
"type": "n8n-nodes-base.code",
"position": [
1200,
300
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Build final report. Never include secret values. Gate 4: ok, missing[], warnings[], checked_at, version_sha.\nconst r = $input.first().json;\nconst manifest = $('Load Manifest').first().json;\nconst allMissing = [...(r.missing || []), ...(r.vault_missing || []), ...(r.creds_missing || [])];\nconst report = {\n ok: r.ok,\n missing: allMissing,\n warnings: r.warnings || [],\n checked_at: new Date().toISOString(),\n version_sha: manifest.version || '1.0',\n summary: r.ok ? 'All required secrets and credentials are present.' : 'Missing secrets or credentials detected.',\n env: { checked: r.env_checked || 0, present: r.present || [], missing: r.missing || [] },\n vault: { checked: r.vault_checked || 0, present: r.vault_present || [], missing: r.vault_missing || [] },\n n8n_credentials: { checked: r.creds_checked || 0, present: r.creds_present || [], missing: r.creds_missing || [] },\n all_missing: allMissing\n};\nreturn [{ json: report }];"
},
"id": "build-report",
"name": "Build Report",
"type": "n8n-nodes-base.code",
"position": [
1440,
300
],
"typeVersion": 2
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Load Manifest",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Load Manifest",
"type": "main",
"index": 0
}
]
]
},
"Load Manifest": {
"main": [
[
{
"node": "Check ENV Secrets",
"type": "main",
"index": 0
}
]
]
},
"Check ENV Secrets": {
"main": [
[
{
"node": "Check Vault Secrets",
"type": "main",
"index": 0
}
]
]
},
"Check Vault Secrets": {
"main": [
[
{
"node": "Check n8n Credentials",
"type": "main",
"index": 0
}
]
]
},
"Check n8n Credentials": {
"main": [
[
{
"node": "Build Report",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateId": "secrets-registry-verify-v1",
"description": "Validates all secrets from the manifest against ENV, Vault adapter, and n8n Credentials API. Returns a report with missing/present status. Never outputs secret values."
},
"tags": [
"secrets",
"self-healing",
"infrastructure"
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Secrets Registry Verify. Webhook trigger; 7 nodes.
Source: https://github.com/jowikroon/hans-crafted-stories/blob/main/apps/personal/n8n/workflows/secrets_registry_verify.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A production-ready authentication workflow implementing secure user registration, login, token verification, and refresh token mechanisms. Perfect for adding authentication to any application without
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
This n8n template demonstrates how a simple Multi-Layer Perceptron (MLP) neural network can predict housing prices. The prediction is based on four key features, processed through a three-layer model.
github code Try yourself
This workflow receives new consult bookings via webhook (Calendly v2 or a generic scheduling tool), generates timed confirmation and reminder messages, runs each SMS through a separate compliance work