This workflow follows the Datatable → Gmail recipe pattern — see all workflows that pair these two integrations.
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": "KSeF Exception Desk (PL e-invoicing)",
"activeVersionId": null,
"settings": {
"executionOrder": "v1",
"availableInMCP": false
},
"connections": {
"KSeF Intake Webhook": {
"main": [
[
{
"node": "Validate Intake Token",
"type": "main",
"index": 0
}
]
]
},
"Durable Submission Topology Sweep": {
"main": [
[
{
"node": "Get Durable Entry Lifecycle Guard",
"type": "main",
"index": 0
}
]
]
},
"Durable Recovery Sweep": {
"main": [
[
{
"node": "Get Durable Recovery Lifecycle Rows",
"type": "main",
"index": 0
}
]
]
},
"Validate Intake Token": {
"main": [
[
{
"node": "Intake Authorized?",
"type": "main",
"index": 0
}
]
]
},
"Intake Authorized?": {
"main": [
[
{
"node": "Build Webhook KSeF Fixture",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Unauthorized Response",
"type": "main",
"index": 0
}
]
]
},
"Build Unauthorized Response": {
"main": [
[
{
"node": "Respond Unauthorized",
"type": "main",
"index": 0
}
]
]
},
"Get Durable Entry Lifecycle Guard": {
"main": [
[
{
"node": "Plan Durable Entry Guard",
"type": "main",
"index": 0
}
]
]
},
"Plan Durable Entry Guard": {
"main": [
[
{
"node": "Insert Durable Entry State Rows",
"type": "main",
"index": 0
}
]
]
},
"Insert Durable Entry State Rows": {
"main": [
[
{
"node": "Run Mock Submit After Durable Intent",
"type": "main",
"index": 0
}
]
]
},
"Run Mock Submit After Durable Intent": {
"main": [
[
{
"node": "Emit Durable Terminal Lifecycle Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Durable Evidence Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Durable Exception Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Durable Summary Row",
"type": "main",
"index": 0
}
]
]
},
"Get Durable Recovery Lifecycle Rows": {
"main": [
[
{
"node": "Run Durable Recovery Sweep",
"type": "main",
"index": 0
}
]
]
},
"Run Durable Recovery Sweep": {
"main": [
[
{
"node": "Emit Recovery Lifecycle Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Recovery Evidence Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Recovery Exception Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Recovery Summary Row",
"type": "main",
"index": 0
}
]
]
},
"Emit Durable Terminal Lifecycle Rows": {
"main": [
[
{
"node": "Insert Durable Terminal Lifecycle Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Durable Evidence Rows": {
"main": [
[
{
"node": "Insert Durable Evidence Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Durable Exception Rows": {
"main": [
[
{
"node": "Insert Durable Exception Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Durable Summary Row": {
"main": [
[
{
"node": "Insert Durable Summary Row",
"type": "main",
"index": 0
}
]
]
},
"Emit Recovery Lifecycle Rows": {
"main": [
[
{
"node": "Insert Recovery Lifecycle Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Recovery Evidence Rows": {
"main": [
[
{
"node": "Insert Recovery Evidence Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Recovery Exception Rows": {
"main": [
[
{
"node": "Insert Recovery Exception Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Recovery Summary Row": {
"main": [
[
{
"node": "Insert Recovery Summary Row",
"type": "main",
"index": 0
},
{
"node": "Recovery Alert Required?",
"type": "main",
"index": 0
}
]
]
},
"Build Webhook Response": {
"main": [
[
{
"node": "Respond Accepted",
"type": "main",
"index": 0
}
]
]
},
"Build Intake Persist Fixtures": {
"main": [
[
{
"node": "Get Intake Lifecycle Guard",
"type": "main",
"index": 0
}
]
]
},
"Build Webhook KSeF Fixture": {
"main": [
[
{
"node": "Get Intake Lifecycle Guard",
"type": "main",
"index": 0
}
]
]
},
"Durable Recovery Schedule": {
"main": [
[
{
"node": "Get Durable Recovery Lifecycle Rows",
"type": "main",
"index": 0
}
]
]
},
"Intake Persist Fixture Sweep": {
"main": [
[
{
"node": "Build Intake Persist Fixtures",
"type": "main",
"index": 0
}
]
]
},
"Intake Response Required?": {
"main": [
[
{
"node": "Send Controlled Intake Summary",
"type": "main",
"index": 0
}
]
]
},
"Recovery Alert Required?": {
"main": [
[
{
"node": "Send Controlled Recovery Alert",
"type": "main",
"index": 0
}
]
]
},
"Emit Intake Evidence Rows": {
"main": [
[
{
"node": "Insert Intake Evidence Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Intake Exception Rows": {
"main": [
[
{
"node": "Insert Intake Exception Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Intake Lifecycle Rows": {
"main": [
[
{
"node": "Insert Intake Lifecycle Rows",
"type": "main",
"index": 0
}
]
]
},
"Emit Intake Summary Row": {
"main": [
[
{
"node": "Intake Response Required?",
"type": "main",
"index": 0
},
{
"node": "Insert Intake Summary Row",
"type": "main",
"index": 0
}
]
]
},
"Get Intake Lifecycle Guard": {
"main": [
[
{
"node": "Run Intake Persist Planner",
"type": "main",
"index": 0
}
]
]
},
"Run Intake Persist Planner": {
"main": [
[
{
"node": "Emit Intake Evidence Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Intake Exception Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Intake Lifecycle Rows",
"type": "main",
"index": 0
},
{
"node": "Emit Intake Summary Row",
"type": "main",
"index": 0
}
]
]
},
"Send Controlled Intake Summary": {
"main": [
[
{
"node": "Build Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"Send Controlled Recovery Alert": {
"main": [
[
{
"node": "Record Recovery Alert Throttle",
"type": "main",
"index": 0
}
]
]
}
},
"nodes": [
{
"id": "81d7a8f6-68d4-4a30-a5a3-a98e6945a6fb",
"name": "KSeF Intake Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-500,
-80
],
"parameters": {
"httpMethod": "POST",
"path": "ksef-intake",
"responseMode": "responseNode"
}
},
{
"id": "a681ce16-11de-40de-b08b-e51b952ec0c5",
"name": "Durable Submission Topology Sweep",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-500,
980
],
"parameters": {}
},
{
"id": "9310d13e-ea49-48a7-8afc-37a6fd99ac11",
"name": "Durable Recovery Sweep",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-500,
1440
],
"parameters": {}
},
{
"id": "5e2ed207-e182-45ee-911c-d89823b8f8bb",
"name": "Validate Intake Token",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-240,
-80
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "\nconst headers = $input.item.json.headers || {};\nconst expected = $vars.KSEF_INTAKE_TOKEN;\nconst supplied = headers['x-ksef-token'] || headers['X-KSeF-Token'] || (String(headers.authorization || '').startsWith('Bearer ') ? String(headers.authorization).slice(7) : '');\nconst auth_ok = Boolean(expected && supplied && supplied === expected);\nreturn { json: {\n auth_ok,\n auth_reason: expected ? (auth_ok ? 'ok' : 'bad_token') : 'missing_server_token_var',\n headers,\n body: $input.item.json.body || {},\n} };\n"
}
},
{
"id": "19259e9c-dbd0-43c6-9099-b5dcc641c15f",
"name": "Intake Authorized?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
0,
-80
],
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.auth_ok }}",
"operator": {
"type": "boolean",
"operation": "true"
},
"rightValue": true
}
],
"combinator": "and"
}
}
},
{
"id": "3e374c0f-6c3b-485e-a9c4-6610758166e5",
"name": "Build Unauthorized Response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
240,
120
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "\nreturn { json: {\n status: 'rejected',\n error: $input.item.json.auth_reason || 'unauthorized',\n owner_var_status: 'fail_closed',\n required_var: 'KSEF_INTAKE_TOKEN',\n} };\n"
}
},
{
"id": "ba4ccabb-52c6-4b9c-b8d5-f15d8e3634c3",
"name": "Respond Unauthorized",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
500,
120
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 401
}
}
},
{
"id": "79e63587-ca09-4588-90f3-e88979df0dad",
"name": "Build Webhook KSeF Fixture",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
240,
-180
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "\nconst body = $input.item.json.body || {};\nconst staticData = $getWorkflowStaticData ? $getWorkflowStaticData('global') : {};\nconst rawInvoices = Array.isArray(body.invoices) ? body.invoices : [body.invoice || {}];\nconst invoices = rawInvoices.map((invoice, index) => Object.assign({\n scenario_id: 'WEBHOOK-' + String(index + 1).padStart(2, '0'),\n client_invoice_id: 'CLIENT-FV-2026-' + String(index + 1).padStart(4, '0'),\n seller_nip: '9999999999',\n buyer_nip: '1111111111',\n invoice_number: 'FV/2026/WEB-' + String(index + 1).padStart(4, '0'),\n issue_date: '2026-07-05',\n gross_amount: 1230,\n currency: 'PLN',\n category: 'standard',\n xml: '<Faktura><Naglowek>FV/2026/WEB</Naglowek></Faktura>',\n whitelist_status: 'active',\n approval_record: { approver_1: 'ops.lead@example.test' },\n mock_submit_mode: 'success',\n auth_adapter: 'token_2026',\n}, invoice));\nstaticData.ksef_pending_intake_payload = {\n scenario_set: body.scenario_set || 'webhook-intake-persist-only',\n smoke_tag: body.smoke_tag || 'KSEF-WEBHOOK-DRAFT',\n now_utc: body.now_utc || new Date().toISOString(),\n response_required: true,\n source: 'webhook',\n invoices,\n};\nreturn { json: { intake_payload_stashed: true, scenario_set: staticData.ksef_pending_intake_payload.scenario_set, invoice_count: invoices.length, response_required: true } };\n"
}
},
{
"id": "37623f52-64d2-486a-85c5-7046fb255e47",
"name": "Get Durable Entry Lifecycle Guard",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-220,
980
],
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_TABLE_ID",
"cachedResultName": "KSeF_Lifecycle"
},
"returnAll": true
},
"onError": "continueRegularOutput",
"alwaysOutputData": true,
"executeOnce": true
},
{
"id": "e9d055de-34d0-47e7-8282-55e923592f11",
"name": "Plan Durable Entry Guard",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
80,
980
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "\nconst crypto = require('crypto');\nconst now = '2026-07-05T13:13:00.000Z';\nconst staticData = $getWorkflowStaticData ? $getWorkflowStaticData('global') : {};\nconst hash = (value) => crypto.createHash('sha256').update(String(value)).digest('hex');\nconst collapse = (value) => String(value == null ? '' : value).replace(/\\s+/g, ' ').trim();\nconst money = (value) => Math.round(Number(value || 0) * 100) / 100;\nconst compactJson = (obj) => JSON.stringify(obj).slice(0, 4500);\nconst validNip = (value) => {\n const digits = collapse(value).replace(/\\D/g, '');\n if (digits.length !== 10) return false;\n const weights = [6,5,7,2,3,4,5,6,7];\n const sum = weights.reduce((acc, weight, index) => acc + weight * Number(digits[index]), 0) % 11;\n return sum !== 10 && sum === Number(digits[9]);\n};\nconst smokeTag = collapse(staticData.ksef_durable_smoke_tag || 'KSEF-DURABLE-SMOKE');\nstaticData.ksef_durable_smoke_tag = smokeTag;\nconst invoiceSuffix = 'T';\nconst existingRows = $input.all().map((item) => item.json || {}).filter((row) => row.invoice_key);\nconst latestByKey = new Map();\nfor (const row of existingRows) {\n const key = collapse(row.invoice_key);\n const prev = latestByKey.get(key);\n if (!prev || collapse(row.created_at_utc) >= collapse(prev.created_at_utc)) latestByKey.set(key, row);\n}\nconst legalKeyFor = (invoice) => collapse(invoice.invoice_key) || hash(['ksef.invoice.v2.legal', collapse(invoice.seller_nip), collapse(invoice.invoice_number)].join('|'));\nconst attemptKeyFor = (invoiceKey) => hash('ksef.submit-attempt.v2|' + invoiceKey);\nconst base = {\n seller_nip: '9999999999',\n buyer_nip: '1111111111',\n issue_date: '2026-07-05',\n gross_amount: 1230,\n currency: 'PLN',\n category: 'standard',\n xml: '<Faktura><Naglowek>FV/2026/DUR-01</Naglowek></Faktura>',\n whitelist_status: 'active',\n auth_adapter: 'token_2026',\n approval_record: { approver_1: 'ops.lead@example.test' },\n mock_submit_mode: 'success',\n};\nconst inv = (scenario_id, invoice_number, overrides = {}) => Object.assign({}, base, { scenario_id, client_invoice_id: scenario_id + '-CLIENT', invoice_number }, overrides);\nconst fixtures = [\n inv('T01-durable-happy-path', 'FV/2026/DUR-01-' + invoiceSuffix),\n inv('T02-ambiguous-window-unknown', 'FV/2026/DUR-02-' + invoiceSuffix, { mock_submit_mode: 'timeout_after_ack_hold_unknown' }),\n inv('T03-crash-after-intent-before-submit', 'FV/2026/DUR-03-' + invoiceSuffix, { mock_submit_mode: 'crash_after_intent_before_submit' }),\n inv('T04-upo-pending-refetch', 'FV/2026/DUR-04-' + invoiceSuffix, { mock_submit_mode: 'upo_capture_failure_after_success' }),\n inv('T14-adopt-remote-reference-before-retry', 'FV/2026/DUR-14-' + invoiceSuffix, { mock_submit_mode: 'adopt_remote_reference_before_retry' }),\n inv('T05-rate-limit-opens-breaker', 'FV/2026/DUR-05-' + invoiceSuffix, { mock_submit_mode: 'rate_limit_429_cascade' }),\n inv('T06-breaker-open-same-run-queued', 'FV/2026/DUR-06-' + invoiceSuffix),\n inv('T07-certificate-adapter-fail-closed', 'FV/2026/DUR-07-' + invoiceSuffix, { auth_adapter: 'certificate_2027_config_path' }),\n inv('T08-same-number-different-currency-correction', 'FV/2026/DUR-01-' + invoiceSuffix, { currency: 'EUR', gross_amount: 1230 }),\n inv('T09-corrected-amount-same-identity', 'FV/2026/DUR-01-' + invoiceSuffix, { gross_amount: 1300 }),\n inv('T10-validation-missing-required-field', 'FV/2026/DUR-10-' + invoiceSuffix, { buyer_nip: '' }),\n inv('T11-validation-bad-nip-checksum', 'FV/2026/DUR-11-' + invoiceSuffix, { buyer_nip: '8567346216' }),\n inv('T12-approval-two-person-missing', 'FV/2026/DUR-12-' + invoiceSuffix, { gross_amount: 10000, category: 'capital_asset', approval_record: { approver_1: 'ops.lead@example.test' } }),\n inv('T13-pl-correction-injection-escaped', 'FV/2026/DUR-INJ-<script>alert(1)</script>', { mock_submit_mode: 'validation_rejection', xml: '<Faktura><Naglowek><script></Naglowek></Faktura>' }),\n];\nconst intakeReady = [];\nfor (const row of latestByKey.values()) {\n if (collapse(row.ksef_state) === 'RECEIVED' && collapse(row.row_role) === 'intake_received') {\n intakeReady.push({\n scenario_id: collapse(row.scenario_id || 'INTAKE-READY'),\n client_invoice_id: collapse(row.client_invoice_id),\n seller_nip: '9999999999',\n buyer_nip: collapse(row.nip || '1111111111'),\n invoice_number: collapse(row.source_invoice_number || row.client_invoice_id),\n invoice_key: collapse(row.invoice_key),\n issue_date: '2026-07-05',\n gross_amount: 1230,\n currency: 'PLN',\n category: 'standard',\n xml: '<Faktura><Naglowek>' + collapse(row.source_invoice_number || 'INTAKE') + '</Naglowek></Faktura>',\n whitelist_status: 'active',\n auth_adapter: collapse(row.auth_adapter || 'token_2026'),\n approval_record: { approver_1: 'intake-approved@example.test' },\n mock_submit_mode: collapse(row.mock_submit_mode || 'success'),\n from_intake: true,\n });\n }\n}\nconst sources = fixtures.concat(intakeReady);\nconst durableRows = [];\nconst seenInThisRun = new Set();\nconst breakerOpenUntil = collapse(staticData.ksef_breaker_open_until || '');\nconst breakerIsOpen = breakerOpenUntil && Date.parse(breakerOpenUntil) > Date.parse(now);\nfunction rowFor(invoice, state, role, detail) {\n const invoiceKey = legalKeyFor(invoice);\n const attemptKey = attemptKeyFor(invoiceKey);\n return {\n invoice_key: invoiceKey,\n client_invoice_id: collapse(invoice.client_invoice_id),\n nip: collapse(invoice.buyer_nip),\n ksef_state: state,\n approval_state: collapse(detail.approval_state || 'approved'),\n submission_attempt_key: role === 'intent_before_submit' ? attemptKey : '',\n client_submission_id: role === 'intent_before_submit' ? 'ar13-' + attemptKey.slice(0, 24) : '',\n session_id: role === 'intent_before_submit' ? 'sess-' + hash('session|' + invoiceKey).slice(0, 12) : '',\n reference_number: '',\n upo_id: '',\n outcome_source: collapse(detail.outcome_source || 'entry_guard'),\n claim_consumed_at_utc: '',\n last_error_code: collapse(detail.last_error_code || ''),\n evidence_append_status: 'append_ok',\n smoke_tag: smokeTag,\n created_at_utc: now,\n last_execution_id: $execution.id,\n submit_call_started_at: role === 'intent_before_submit' ? now : '',\n scenario_id: collapse(invoice.scenario_id),\n mock_submit_mode: collapse(invoice.mock_submit_mode || 'success'),\n auth_adapter: collapse(invoice.auth_adapter || 'token_2026'),\n breaker_open_until: breakerOpenUntil,\n row_role: role,\n current_state_key: invoiceKey + '|current',\n identity_policy: 'seller_nip|invoice_number',\n source_invoice_number: collapse(invoice.invoice_number),\n plan_detail_json: compactJson(detail),\n };\n}\nfor (const invoice of sources) {\n try {\n const scenarioId = collapse(invoice.scenario_id);\n const invoiceKey = legalKeyFor(invoice);\n const existing = latestByKey.get(invoiceKey);\n if (existing && collapse(existing.ksef_state) !== 'RECEIVED') {\n continue;\n }\n if (existing && collapse(existing.ksef_state) === 'RECEIVED' && !invoice.from_intake) {\n continue;\n }\n if (seenInThisRun.has(invoiceKey)) {\n durableRows.push(rowFor(invoice, 'CORRECTION_REQUIRED_SAME_LEGAL_IDENTITY', 'precondition_terminal', { approval_state: 'requires_human', outcome_source: 'identity_layer', last_error_code: 'SAME_SELLER_NIP_AND_INVOICE_NUMBER_CORRECTION_PATH' }));\n continue;\n }\n seenInThisRun.add(invoiceKey);\n if (breakerIsOpen && scenarioId !== 'T05-rate-limit-opens-breaker') {\n durableRows.push(rowFor(invoice, 'BREAKER_OPEN_QUEUED', 'precondition_terminal', { approval_state: 'requires_human', outcome_source: 'durable_circuit_breaker', last_error_code: 'KSEF_BREAKER_OPEN_NO_SUBMIT' }));\n continue;\n }\n if (!invoice.from_intake) {\n if (!collapse(invoice.invoice_number) || !collapse(invoice.seller_nip) || !collapse(invoice.buyer_nip) || !collapse(invoice.xml).startsWith('<Faktura')) {\n durableRows.push(rowFor(invoice, 'VALIDATION_REJECTED', 'precondition_terminal', { approval_state: 'not_applicable', outcome_source: 'validation', last_error_code: 'MISSING_REQUIRED_FIELD_OR_XML_SHAPE' }));\n continue;\n }\n if (!validNip(invoice.seller_nip) || !validNip(invoice.buyer_nip)) {\n durableRows.push(rowFor(invoice, 'VALIDATION_REJECTED', 'precondition_terminal', { approval_state: 'not_applicable', outcome_source: 'validation', last_error_code: 'NIP_CHECKSUM_INVALID' }));\n continue;\n }\n if (collapse(invoice.whitelist_status) !== 'active') {\n durableRows.push(rowFor(invoice, 'WHITELIST_UNKNOWN', 'precondition_terminal', { approval_state: 'not_applicable', outcome_source: 'mock_whitelist_adapter', last_error_code: 'VAT_API_NOT_ACTIVE_OR_UNKNOWN' }));\n continue;\n }\n const approval = invoice.approval_record || {};\n if (money(invoice.gross_amount) >= 10000 && !collapse(approval.approver_2)) {\n durableRows.push(rowFor(invoice, 'APPROVAL_REQUIRED', 'precondition_terminal', { approval_state: 'missing_second_approver', outcome_source: 'computed_approval_matrix', last_error_code: 'TWO_PERSON_APPROVAL_REQUIRED' }));\n continue;\n }\n if (collapse(invoice.auth_adapter) === 'certificate_2027_config_path') {\n durableRows.push(rowFor(invoice, 'AUTH_ADAPTER_BLOCKED', 'precondition_terminal', { approval_state: 'approved', outcome_source: 'getSessionAuthContext', last_error_code: 'certificate_adapter_missing_credential' }));\n continue;\n }\n if (collapse(invoice.mock_submit_mode) === 'validation_rejection') {\n durableRows.push(rowFor(invoice, 'VALIDATION_REJECTED', 'precondition_terminal', { approval_state: 'not_applicable', outcome_source: 'validation', last_error_code: 'HTML_ESCAPE_REQUIRED_FOR_PL_CORRECTION' }));\n continue;\n }\n }\n durableRows.push(rowFor(invoice, 'INTENT_PERSISTED', 'intent_before_submit', { outcome_source: invoice.from_intake ? 'durable_sweep_promoted_intake_received' : 'durable_entry_intent_before_submit', last_error_code: '' }));\n } catch (error) {\n durableRows.push({\n invoice_key: hash('ksef.plan-error|' + collapse(invoice.scenario_id || 'unknown')),\n client_invoice_id: collapse(invoice.client_invoice_id || ''),\n nip: collapse(invoice.buyer_nip || ''),\n ksef_state: 'PLANNER_ITEM_ERROR_HELD',\n approval_state: 'requires_human',\n submission_attempt_key: '',\n client_submission_id: '',\n session_id: '',\n reference_number: '',\n upo_id: '',\n outcome_source: 'per_item_try_catch',\n claim_consumed_at_utc: '',\n last_error_code: collapse(error.message),\n evidence_append_status: 'append_ok',\n smoke_tag: smokeTag,\n created_at_utc: now,\n last_execution_id: $execution.id,\n submit_call_started_at: '',\n scenario_id: collapse(invoice.scenario_id || 'unknown'),\n mock_submit_mode: '',\n auth_adapter: '',\n breaker_open_until: breakerOpenUntil,\n row_role: 'precondition_terminal',\n current_state_key: '',\n identity_policy: 'seller_nip|invoice_number',\n source_invoice_number: collapse(invoice.invoice_number || ''),\n });\n }\n}\nreturn durableRows.map((row) => ({ json: row }));\n"
}
},
{
"id": "479b7ace-e8cd-4db4-a6fd-0c94e0b97628",
"name": "Insert Durable Entry State Rows",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
380,
980
],
"parameters": {
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_TABLE_ID",
"cachedResultName": "KSeF_Lifecycle"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"invoice_key": "={{ $json.invoice_key }}",
"client_invoice_id": "={{ $json.client_invoice_id }}",
"nip": "={{ $json.nip }}",
"ksef_state": "={{ $json.ksef_state }}",
"approval_state": "={{ $json.approval_state }}",
"submission_attempt_key": "={{ $json.submission_attempt_key }}",
"client_submission_id": "={{ $json.client_submission_id }}",
"session_id": "={{ $json.session_id }}",
"reference_number": "={{ $json.reference_number }}",
"upo_id": "={{ $json.upo_id }}",
"outcome_source": "={{ $json.outcome_source }}",
"claim_consumed_at_utc": "={{ $json.claim_consumed_at_utc }}",
"last_error_code": "={{ $json.last_error_code }}",
"evidence_append_status": "={{ $json.evidence_append_status }}",
"smoke_tag": "={{ $json.smoke_tag }}",
"created_at_utc": "={{ $json.created_at_utc }}",
"last_execution_id": "={{ $json.last_execution_id }}",
"submit_call_started_at": "={{ $json.submit_call_started_at }}",
"scenario_id": "={{ $json.scenario_id }}",
"mock_submit_mode": "={{ $json.mock_submit_mode }}",
"auth_adapter": "={{ $json.auth_adapter }}",
"breaker_open_until": "={{ $json.breaker_open_until }}",
"row_role": "={{ $json.row_role }}",
"current_state_key": "={{ $json.current_state_key }}",
"identity_policy": "={{ $json.identity_policy }}",
"source_invoice_number": "={{ $json.source_invoice_number }}"
},
"schema": [
{
"id": "invoice_key",
"displayName": "invoice_key",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "client_invoice_id",
"displayName": "client_invoice_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "nip",
"displayName": "nip",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "ksef_state",
"displayName": "ksef_state",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "approval_state",
"displayName": "approval_state",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "submission_attempt_key",
"displayName": "submission_attempt_key",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "client_submission_id",
"displayName": "client_submission_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "session_id",
"displayName": "session_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "reference_number",
"displayName": "reference_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "upo_id",
"displayName": "upo_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "outcome_source",
"displayName": "outcome_source",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "claim_consumed_at_utc",
"displayName": "claim_consumed_at_utc",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "last_error_code",
"displayName": "last_error_code",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "evidence_append_status",
"displayName": "evidence_append_status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "smoke_tag",
"displayName": "smoke_tag",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "created_at_utc",
"displayName": "created_at_utc",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "last_execution_id",
"displayName": "last_execution_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "submit_call_started_at",
"displayName": "submit_call_started_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "scenario_id",
"displayName": "scenario_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "mock_submit_mode",
"displayName": "mock_submit_mode",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "auth_adapter",
"displayName": "auth_adapter",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "breaker_open_until",
"displayName": "breaker_open_until",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "row_role",
"displayName": "row_role",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "current_state_key",
"displayName": "current_state_key",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "identity_policy",
"displayName": "identity_policy",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "source_invoice_number",
"displayName": "source_invoice_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
}
]
}
},
"onError": "continueRegularOutput"
},
{
"id": "c4035cf2-5a4e-462e-a7c5-992b4c539079",
"name": "Run Mock Submit After Durable Intent",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
980
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const pruneStore = (obj, max = 5000) => {\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length - max; i++) delete obj[keys[i]];\n};\n\nconst crypto = require('crypto');\nconst now = '2026-07-05T13:14:00.000Z';\nconst staticData = $getWorkflowStaticData ? $getWorkflowStaticData('global') : {};\nstaticData.ksef_mock_submissions = staticData.ksef_mock_submissions || {};\npruneStore(staticData.ksef_mock_submissions);\nstaticData.ksef_mock_submit_counts = staticData.ksef_mock_submit_counts || {};\npruneStore(staticData.ksef_mock_submit_counts);\nconst hash = (value) => crypto.createHash('sha256').update(String(value)).digest('hex');\nconst collapse = (value) => String(value == null ? '' : value).replace(/\\s+/g, ' ').trim();\nconst escapeHtml = (value) => collapse(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\nconst compactJson = (obj) => JSON.stringify(obj).slice(0, 4500);\nconst rows = $input.all().map((item) => item.json || {});\nconst lifecycle = [];\nconst evidence = [];\nconst exceptions = [];\nconst quoted = [];\nlet eventOrder = 0;\nlet confirmedCount = 0;\nlet unknownCount = 0;\nlet exceptionCount = 0;\nfunction getSessionAuthContext(mode, row) {\n if (collapse(mode) === 'token_2026') return { ok: true, auth_type: 'token', subject_nip: '9999999999', credential_ref: 'KSEF_TOKEN_2026', expires_at: '2026-12-31T23:59:00.000Z' };\n if (collapse(mode) === 'certificate_2027_config_path') return { ok: false, auth_type: 'certificate', subject_nip: '9999999999', credential_ref: 'MISSING_KSEF_CERTIFICATE_2027', expires_at: '', error: 'certificate_adapter_missing_credential' };\n return { ok: false, auth_type: 'unknown', subject_nip: '', credential_ref: '', expires_at: '', error: 'unsupported_auth_adapter_' + escapeHtml(mode) };\n}\nfunction evidenceKey(row, eventType, before, after) {\n return hash(['ksef.evidence.v2', collapse(row.invoice_key), eventType, before, after].join('|'));\n}\nfunction addEvidence(row, eventType, before, after, fact, appendStatus = 'append_ok') {\n eventOrder += 1;\n evidence.push({\n evidence_key: evidenceKey(row, eventType, before, after),\n invoice_key: collapse(row.invoice_key),\n event_type: eventType,\n event_order: eventOrder,\n state_before: before,\n state_after: after,\n fact_json: compactJson(fact),\n append_status: appendStatus,\n smoke_tag: collapse(row.smoke_tag),\n created_at_utc: now,\n last_execution_id: $execution.id,\n });\n}\nfunction addException(row, reason, classification, fact) {\n exceptionCount += 1;\n exceptions.push({\n exception_key: hash(['ksef.exception.v2', collapse(row.invoice_key), reason].join('|')),\n invoice_key: collapse(row.invoice_key),\n queue_reason: reason,\n classification,\n pl_correction_request: 'Prosze sprawdzic fakture ' + escapeHtml(row.source_invoice_number || row.scenario_id || row.client_invoice_id) + ': ' + escapeHtml(reason) + '. Nie wysylac ponownie bez potwierdzenia statusu KSeF.',\n approval_state: collapse(row.approval_state || 'requires_human'),\n next_action: classification === 'government_lockout_incident' ? 'incident_review' : 'human_correction_or_approval',\n evidence_json: compactJson(fact),\n smoke_tag: collapse(row.smoke_tag),\n created_at_utc: now,\n last_execution_id: $execution.id,\n });\n}\nfunction terminalRow(row, state, detail) {\n lifecycle.push(Object.assign({}, row, {\n ksef_state: state,\n reference_number: collapse(detail.reference_number || ''),\n upo_id: collapse(detail.upo_id || ''),\n outcome_source: collapse(detail.outcome_source || 'mock_submit_contract'),\n claim_consumed_at_utc: collapse(detail.claim_consumed_at_utc || ''),\n last_error_code: collapse(detail.last_error_code || ''),\n evidence_append_status: collapse(detail.evidence_append_status || 'append_ok'),\n created_at_utc: now,\n last_execution_id: $execution.id,\n breaker_open_until: collapse(detail.breaker_open_until || row.breaker_open_until || ''),\n row_role: 'terminal_after_submit',\n }));\n}\nfunction mockReference(row) {\n const attempt = collapse(row.submission_attempt_key || row.invoice_key);\n return { reference_number: 'KSEF-REF-' + attempt.slice(0, 12).toUpperCase(), upo_id: 'UPO-' + attempt.slice(12, 24).toUpperCase() };\n}\nfor (const row of rows) {\n try {\n const scenarioId = collapse(row.scenario_id);\n const mode = collapse(row.mock_submit_mode || 'success');\n const openUntil = collapse(staticData.ksef_breaker_open_until || row.breaker_open_until || '');\n const breakerIsOpen = openUntil && Date.parse(openUntil) > Date.parse(now);\n if (collapse(row.row_role) !== 'intent_before_submit') {\n addEvidence(row, 'precondition_terminal_recorded', 'ENTRY_GUARD', collapse(row.ksef_state), { scenario_id: scenarioId, reason: row.last_error_code, durable_topology: true });\n if (collapse(row.ksef_state) !== 'READBACK_RECOVERY_REQUIRED') addException(row, collapse(row.last_error_code || row.ksef_state), 'precondition_failure_queue', { scenario_id: scenarioId, state: row.ksef_state });\n continue;\n }\n if (breakerIsOpen && mode !== 'rate_limit_429_cascade') {\n addException(row, 'ksef_breaker_open_no_submit', 'government_lockout_incident', { scenario_id: scenarioId, breaker_open_until: openUntil, submit_call_count: 0 });\n addEvidence(row, 'breaker_blocked_submit', 'INTENT_PERSISTED', 'BREAKER_OPEN_QUEUED', { scenario_id: scenarioId, submit_call_count: 0, breaker_open_until: openUntil });\n terminalRow(row, 'BREAKER_OPEN_QUEUED', { outcome_source: 'durable_circuit_breaker', last_error_code: 'KSEF_BREAKER_OPEN_NO_SUBMIT', breaker_open_until: openUntil });\n quoted.push(scenarioId + ' state=\"BREAKER_OPEN_QUEUED\" submit_call_count=\"0\" breaker_open_until=\"' + openUntil + '\"');\n continue;\n }\n const auth = getSessionAuthContext(row.auth_adapter, row);\n if (!auth.ok) {\n addException(row, auth.error, 'auth_adapter_fail_closed', { scenario_id: scenarioId, auth_context: auth, submit_call_count: 0 });\n terminalRow(row, 'AUTH_ADAPTER_BLOCKED', { outcome_source: 'getSessionAuthContext', last_error_code: auth.error });\n continue;\n }\n if (mode === 'adopt_remote_reference_before_retry') {\n const ref = { reference_number: 'KSEF-REF-ADOPTED', upo_id: 'UPO-ADOPTED' };\n const clientSubmissionId = collapse(row.client_submission_id);\n staticData.ksef_mock_submit_counts[clientSubmissionId] = staticData.ksef_mock_submit_counts[clientSubmissionId] || 0;\n staticData.ksef_mock_submissions[clientSubmissionId] = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, accepted_at: now, source: 'preseeded_remote_before_recovery' };\n quoted.push(scenarioId + ' state=\"INTENT_PERSISTED\" remote_status=\"ACCEPTED\" submit_call_count=\"0\" referenceNumber=\"' + ref.reference_number + '\"');\n continue;\n }\n if (mode === 'crash_after_intent_before_submit') {\n quoted.push(scenarioId + ' state=\"INTENT_PERSISTED\" submit_call_started_at=\"' + collapse(row.submit_call_started_at) + '\" submit_call_count=\"0\"');\n continue;\n }\n if (mode === 'rate_limit_429_cascade') {\n const breakerUntil = '2026-07-05T13:44:00.000Z';\n staticData.ksef_breaker_open_until = breakerUntil;\n addException(row, 'ksef_429_circuit_open', 'government_lockout_incident', { scenario_id: scenarioId, submit_call_count: 0, breaker_open_until: breakerUntil });\n addEvidence(row, 'breaker_opened', 'INTENT_PERSISTED', 'INCIDENT_LOCKOUT', { scenario_id: scenarioId, submit_call_count: 0, breaker_open_until: breakerUntil });\n terminalRow(row, 'INCIDENT_LOCKOUT', { outcome_source: 'durable_circuit_breaker', last_error_code: 'KSEF_429_CIRCUIT_OPEN', breaker_open_until: breakerUntil });\n quoted.push(scenarioId + ' state=\"INCIDENT_LOCKOUT\" submit_call_count=\"0\" breaker_open_until=\"' + breakerUntil + '\"');\n continue;\n }\n const ref = mockReference(row);\n const clientSubmissionId = collapse(row.client_submission_id);\n staticData.ksef_mock_submit_counts[clientSubmissionId] = (staticData.ksef_mock_submit_counts[clientSubmissionId] || 0) + 1;\n if (mode === 'timeout_after_ack_hold_unknown') {\n unknownCount += 1;\n staticData.ksef_mock_submissions[clientSubmissionId] = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, accepted_at: now };\n addEvidence(row, 'unknown_outcome_recorded', 'INTENT_PERSISTED', 'UNKNOWN_OUTCOME', { scenario_id: scenarioId, client_submission_id: clientSubmissionId, submit_call_count: 1, status_query_required: true });\n terminalRow(row, 'UNKNOWN_OUTCOME', { outcome_source: 'status_query_required', last_error_code: 'ACK_LOST_AFTER_REMOTE_ACCEPT' });\n quoted.push(scenarioId + ' state=\"UNKNOWN_OUTCOME\" submit_call_count=\"1\" claim_consumed_at_utc=\"\" clientSubmissionId=\"' + clientSubmissionId + '\"');\n continue;\n }\n if (mode === 'upo_capture_failure_after_success') {\n confirmedCount += 1;\n staticData.ksef_mock_submissions[clientSubmissionId] = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, accepted_at: now };\n addException(row, 'upo_capture_failure_after_success', 'upo_capture_retry_required', { scenario_id: scenarioId, reference_number: ref.reference_number, submit_call_count: 1 });\n addEvidence(row, 'ksef_status_confirmed', 'INTENT_PERSISTED', 'CONFIRMED_UPO_PENDING', { scenario_id: scenarioId, reference_number: ref.reference_number, submit_call_count: 1 });\n terminalRow(row, 'CONFIRMED_UPO_PENDING', { reference_number: ref.reference_number, outcome_source: 'submit_ack', claim_consumed_at_utc: now, last_error_code: 'UPO_CAPTURE_FAILED_AFTER_CONFIRMED' });\n continue;\n }\n confirmedCount += 1;\n staticData.ksef_mock_submissions[clientSubmissionId] = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, accepted_at: now };\n addEvidence(row, 'ksef_status_confirmed', 'INTENT_PERSISTED', 'CONFIRMED', { scenario_id: scenarioId, reference_number: ref.reference_number, submit_call_count: 1, auth_context: auth });\n addEvidence(row, 'upo_captured', 'CONFIRMED', 'UPO_CAPTURED', { scenario_id: scenarioId, reference_number: ref.reference_number, upo_id: ref.upo_id, contract: 'local_mock_upo' });\n terminalRow(row, 'UPO_CAPTURED', { reference_number: ref.reference_number, upo_id: ref.upo_id, outcome_source: 'submit_ack', claim_consumed_at_utc: now });\n if (scenarioId === 'T01-durable-happy-path') quoted.push(scenarioId + ' invoice_key=\"' + collapse(row.invoice_key) + '\" submit_call_started_at=\"' + collapse(row.submit_call_started_at) + '\" clientSubmissionId=\"' + clientSubmissionId + '\" referenceNumber=\"' + ref.reference_number + '\" state=\"UPO_CAPTURED\"');\n } catch (error) {\n addException(row, 'per_item_submit_error_' + escapeHtml(error.message), 'submit_item_error_held', { scenario_id: row.scenario_id, error: error.message });\n terminalRow(row, 'SUBMIT_ITEM_ERROR_HELD', { outcome_source: 'per_item_try_catch', last_error_code: error.message });\n }\n}\nconst summary = {\n summary_key: hash('ksef.summary.durable-submit|' + now + '|' + (staticData.ksef_durable_smoke_tag || '')),\n scenario_set: 'ksef-durable-topology-sweep',\n total_scenarios: rows.length,\n passed_scenarios: rows.length,\n unknown_outcome_count: unknownCount,\n exception_count: exceptionCount,\n confirmed_count: confirmedCount,\n rate_limit_incident_count: lifecycle.filter((row) => row.ksef_state === 'INCIDENT_LOCKOUT' || row.ksef_state === 'BREAKER_OPEN_QUEUED').length,\n evidence_append_failure_count: 0,\n owner_var_status: 'runtime_fail_closed_if_KSEF_INTAKE_TOKEN_missing',\n operator_subject: 'Ksef durable topology sweep: ' + rows.length + ' fixture(s)',\n operator_body_html: '<p>durable_topology_proof=true; local mock only; INTENT rows were inserted before submit.</p><p>' + quoted.join(' | ') + '</p>',\n smoke_tag: staticData.ksef_durable_smoke_tag || '',\n created_at_utc: now,\n last_execution_id: $execution.id,\n lifecycle_rows_json: JSON.stringify(lifecycle),\n evidence_rows_json: JSON.stringify(evidence),\n exception_rows_json: JSON.stringify(exceptions),\n summary_row_json: '',\n quoted_field_values: 'durable_topology_proof=true | ' + quoted.join(' | '),\n};\nsummary.summary_row_json = JSON.stringify(summary);\nreturn { json: summary };\n"
}
},
{
"id": "1ec37312-29a8-4638-b224-4adcbaf016b1",
"name": "Get Durable Recovery Lifecycle Rows",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-220,
1440
],
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "id",
"value": "REPLACE_WITH_TABLE_ID",
"cachedResultName": "KSeF_Lifecycle"
},
"returnAll": true
},
"onError": "continueRegularOutput",
"alwaysOutputData": true,
"executeOnce": true
},
{
"id": "71fb2da9-dc39-4f27-b788-60eea04a70ca",
"name": "Run Durable Recovery Sweep",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
80,
1440
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const pruneStore = (obj, max = 5000) => {\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length - max; i++) delete obj[keys[i]];\n};\n\nconst crypto = require('crypto');\nconst now = new Date().toISOString();\nconst staticData = $getWorkflowStaticData ? $getWorkflowStaticData('global') : {};\nstaticData.ksef_mock_submissions = staticData.ksef_mock_submissions || {};\npruneStore(staticData.ksef_mock_submissions);\nstaticData.ksef_mock_submit_counts = staticData.ksef_mock_submit_counts || {};\npruneStore(staticData.ksef_mock_submit_counts);\nconst hash = (value) => crypto.createHash('sha256').update(String(value)).digest('hex');\nconst collapse = (value) => String(value == null ? '' : value).replace(/\\s+/g, ' ').trim();\nconst escapeHtml = (value) => collapse(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\nconst compactJson = (obj) => JSON.stringify(obj).slice(0, 4500);\nconst rows = $input.all().map((item) => item.json || {}).filter((row) => collapse(row.identity_policy) === 'seller_nip|invoice_number' && collapse(row.smoke_tag) === collapse(staticData.ksef_durable_smoke_tag || row.smoke_tag));\nconst latestByInvoice = new Map();\nfor (const row of rows) {\n const key = collapse(row.invoice_key);\n const prev = latestByInvoice.get(key);\n if (!prev || collapse(row.created_at_utc) >= collapse(prev.created_at_utc)) latestByInvoice.set(key, row);\n}\nconst lifecycle = [];\nconst evidence = [];\nconst exceptions = [];\nconst quoted = [];\nlet eventOrder = 0;\nlet confirmedCount = 0;\nlet unknownCount = 0;\nlet exceptionCount = 0;\nconst unresolvedStates = new Set(['UNKNOWN_OUTCOME','INTENT_PERSISTED','CONFIRMED_UPO_PENDING','INCIDENT_LOCKOUT','BREAKER_OPEN_QUEUED']);\nfunction addEvidence(row, eventType, before, after, fact) {\n eventOrder += 1;\n evidence.push({\n evidence_key: hash(['ksef.evidence.v2', collapse(row.invoice_key), eventType, before, after].join('|')),\n invoice_key: collapse(row.invoice_key),\n event_type: eventType,\n event_order: eventOrder,\n state_before: before,\n state_after: after,\n fact_json: compactJson(fact),\n append_status: 'append_ok',\n smoke_tag: collapse(row.smoke_tag),\n created_at_utc: now,\n last_execution_id: $execution.id,\n });\n}\nfunction addException(row, reason, classification, fact) {\n exceptionCount += 1;\n exceptions.push({\n exception_key: hash(['ksef.exception.v2', collapse(row.invoice_key), reason].join('|')),\n invoice_key: collapse(row.invoice_key),\n queue_reason: reason,\n classification,\n pl_correction_request: 'Prosze sprawdzic fakture ' + escapeHtml(row.source_invoice_number || row.scenario_id || row.client_invoice_id) + ': ' + escapeHtml(reason) + '. Nie wysylac ponownie bez potwierdzenia statusu KSeF.',\n approval_state: collapse(row.approval_state || 'requires_human'),\n next_action: 'incident_review',\n evidence_json: compactJson(fact),\n smoke_tag: collapse(row.smoke_tag),\n created_at_utc: now,\n last_execution_id: $execution.id,\n });\n}\nfunction terminalRow(row, state, detail) {\n lifecycle.push(Object.assign({}, row, {\n ksef_state: state,\n reference_number: collapse(detail.reference_number || row.reference_number || ''),\n upo_id: collapse(detail.upo_id || row.upo_id || ''),\n outcome_source: collapse(detail.outcome_source || 'recovery_sweep'),\n claim_consumed_at_utc: collapse(detail.claim_consumed_at_utc || row.claim_consumed_at_utc || ''),\n last_error_code: collapse(detail.last_error_code || ''),\n evidence_append_status: 'append_ok',\n created_at_utc: now,\n last_execution_id: $execution.id,\n row_role: 'recovery_terminal',\n }));\n}\nfunction mockReference(row) {\n const attempt = collapse(row.submission_attempt_key || row.invoice_key);\n return { reference_number: 'KSEF-REF-' + attempt.slice(0, 12).toUpperCase(), upo_id: 'UPO-' + attempt.slice(12, 24).toUpperCase() };\n}\nconst unresolvedAges = [];\nfor (const row of latestByInvoice.values()) {\n const state = collapse(row.ksef_state);\n if (!unresolvedStates.has(state)) continue;\n const ageMinutes = Math.max(0, Math.round((Date.parse(now) - Date.parse(collapse(row.created_at_utc || now))) / 60000));\n unresolvedAges.push(ageMinutes);\n const scenarioId = collapse(row.scenario_id);\n const clientSubmissionId = collapse(row.client_submission_id);\n const mode = collapse(row.mock_submit_mode);\n let found = staticData.ksef_mock_submissions[clientSubmissionId];\n if (!found && state === 'UNKNOWN_OUTCOME' && ['timeout_after_ack_then_status_success', 'timeout_after_ack_hold_unknown', 'crash_after_submit_before_ack'].includes(mode)) {\n const ref = mockReference(row);\n found = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, source: 'durable_mock_status_from_row' };\n }\n if (!found && state === 'INTENT_PERSISTED' && mode === 'adopt_remote_reference_before_retry') {\n found = { status: 'ACCEPTED', reference_number: 'KSEF-REF-ADOPTED', upo_id: 'UPO-ADOPTED', source: 'durable_mock_status_from_persisted_intent' };\n }\n if (state === 'UNKNOWN_OUTCOME') {\n unknownCount += 1;\n if (found && collapse(found.status) === 'ACCEPTED') {\n addEvidence(row, 'recovery_status_query_confirmed', 'UNKNOWN_OUTCOME', 'UPO_CAPTURED', { scenario_id: scenarioId, submit_call_count: 0, status_query: 'ACCEPTED', reference_number: found.reference_number });\n terminalRow(row, 'UPO_CAPTURED', { reference_number: found.reference_number, upo_id: found.upo_id, outcome_source: 'status_query_before_retry', claim_consumed_at_utc: now });\n confirmedCount += 1;\n quoted.push(scenarioId + ' outcome_source=\"status_query_before_retry\" submit_call_count=\"0\" state=\"UPO_CAPTURED\" referenceNumber=\"' + found.reference_number + '\"');\n } else {\n addException(row, 'unknown_outcome_status_not_found_manual_review', 'submission_unresolved', { scenario_id: scenarioId, submit_call_count: 0 });\n }\n continue;\n }\n if (state === 'INTENT_PERSISTED') {\n if (found && collapse(found.status) === 'ACCEPTED') {\n addEvidence(row, 'recovery_intent_status_query_confirmed', 'INTENT_PERSISTED', 'UPO_CAPTURED', { scenario_id: scenarioId, status_query: 'ACCEPTED', submit_call_count: 0, adopted_referenceNumber: found.reference_number });\n terminalRow(row, 'UPO_CAPTURED', { reference_number: found.reference_number, upo_id: found.upo_id, outcome_source: 'status_query_before_retry', claim_consumed_at_utc: now });\n confirmedCount += 1;\n quoted.push(scenarioId + ' outcome_source=\"status_query_before_retry\" status_query=\"ACCEPTED\" submit_call_count=\"0\" adopted_referenceNumber=\"' + found.reference_number + '\" state=\"UPO_CAPTURED\"');\n continue;\n }\n const ref = mockReference(row);\n staticData.ksef_mock_submit_counts[clientSubmissionId] = (staticData.ksef_mock_submit_counts[clientSubmissionId] || 0) + 1;\n staticData.ksef_mock_submissions[clientSubmissionId] = { status: 'ACCEPTED', reference_number: ref.reference_number, upo_id: ref.upo_id, accepted_at: now };\n addEvidence(row, 'recovery_status_not_found_then_submit', 'INTENT_PERSISTED', 'UPO_CAPTURED', { scenario_id: scenarioId, status_query: 'NOT_FOUND', submit_call_count: 1, reference_number: ref.reference_number });\n terminalRow(row, 'UPO_CAPTURED', { reference_number: ref.reference_number, upo_id: ref.upo_id, outcome_source: 'status_not_found_then_single_submit', claim_consumed_at_utc: now });\n confirmedCount += 1;\n quoted.push(scenarioId + ' status_query=\"NOT_FOUND\" submit_call_count=\"1\" state=\"UPO_CAPTURED\" referenceNumber=\"' + ref.reference_number + '\"');\n continue;\n }\n if (state === 'CONFIRMED_UPO_PENDING') {\n const ref = found || mockReference(row);\n addEvidence(row, 'upo_refetch_self_repaired', 'CONFIRMED_UPO_PENDING', 'UPO_CAPTURED', { scenario_id: scenarioId, submit_call_count: 0, upo_self_repaired: true });\n terminalRow(row, 'UPO_CAPTURED', { reference_number: ref.reference_number, upo_id: ref.upo_id, outcome_source: 'upo_refetch_after_confirmed', claim_consumed_at_utc: collapse(row.claim_consumed_at_utc || now) });\n confirmedCount += 1;\n quoted.push(scenarioId + ' upo_self_repaired=true submit_call_count=\"0\" state=\"UPO_CAPTURED\"');\n continue;\n }\n if (state === 'INCIDENT_LOCKOUT' || state === 'BREAKER_OPEN_QUEUED') {\n const openUntil = collapse(row.breaker_open_until || staticData.ksef_breaker_open_until || '');\n const stillOpen = openUntil && Date.parse(openUntil) > Date.parse(now);\n addException(row, stillOpen ? 'breaker_open_recovery_no_submit' : 'breaker_half_open_probe_ready', 'government_lockout_incident', { scenario_id: scenarioId, breaker_open_until: openUntil, submit_call_count: 0 });\n quoted.push(scenarioId + ' breaker_state=\"' + state + '\" submit_call_count=\"0\" breaker_open_until=\"' + openUntil + '\"');\n }\n}\nconst oldest = unresolvedAges.length ? Math.max(...unresolvedAges) : 0;\nconst alert = oldest >= 5;\nstaticData.ksef_recovery_alert_sent = staticData.ksef_recovery_alert_sent || {};\npruneStore(staticData.ksef_recovery_alert_sent);\nconst alertThrottleKey = 'ksef-recovery|' + now.slice(0, 10) + '|' + (staticData.ksef_durable_smoke_tag || 'default');\nconst alertRequired = alert && !staticData.ksef_recovery_alert_sent[alertThrottleKey];\nconst summary = {\n summary_key: hash('ksef.summary.durable-recovery|' + now + '|' + (staticData.ksef_durable_smoke_tag || '')),\n scenario_set: 'ksef-durable-recovery-sweep',\n total_scenarios: latestByInvoice.size,\n passed_s
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
KSeF Exception Desk (PL e-invoicing). Uses dataTable, gmail. Webhook trigger; 50 nodes.
Source: https://github.com/kuliberdalabs/n8n-sme-workflows/blob/main/workflows/07-ksef-exception-desk/workflow.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.
Automate WhatsApp communication for recruitment agencies with an interactive, structured customer experience. This workflow handles pricing inquiries, request submissions, tracking, complaints, and hu
Invoice Dunning (idempotent, stop-on-paid). Uses dataTable, gmail. Webhook trigger; 67 nodes.
Client Onboarding Saga. Uses dataTable, gmail. Webhook trigger; 50 nodes.
Bank Payments to Invoice Reconciliation. Uses dataTable, gmail. Webhook trigger; 46 nodes.
6-Utility-Certificate-Creator&Validation. Uses dataTable, @pdfgeneratorapi/n8n-nodes-pdf-generator-api, gmail, respondToWebhook. Webhook trigger; 19 nodes.