n8n-pto-pipeline — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited n8n-pto-pipeline (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Daily work planning in construction involves:
Automated n8n pipeline connecting Google Sheets task lists with Telegram bots for real-time task distribution and status collection.
┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐
│ Google Sheets │───>│ n8n │───>│ Telegram Bot │
│ (Task List) │ │ Pipeline │ │ (To Foreman) │
└─────────────────┘ └─────────────┘ └─────────────────┘
▲ │ │
│ │ ▼
│ ┌──────┴──────┐ ┌───────────┐
└──────────────│ Status │<─────│ Foreman │
│ Update │ │ Response │
└─────────────┘ └───────────┘#### 1. Morning Trigger (8:00 AM)
{
"nodes": [
{
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{"field": "hours", "hoursInterval": 24}
]
},
"triggerTimes": {"item": [{"hour": 8, "minute": 0}]}
}
}
]
}#### 2. Get Tasks from Google Sheets
{
"name": "Get Today Tasks",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "read",
"sheetId": "YOUR_SHEET_ID",
"range": "Tasks!A:F",
"options": {}
}
}#### 3. Filter Tasks by Foreman
// Filter tasks for specific foreman based on chat_id
const chatId = $node["Telegram Trigger"].json["message"]["chat"]["id"];
const tasks = $input.all();
return tasks.filter(task =>
task.json.foreman_chat_id === chatId.toString()
);#### 4. Format and Send via Telegram
// Format task message
const tasks = $input.all();
let message = "📋 *Задачи на сегодня:*\n\n";
tasks.forEach((task, index) => {
message += `*${index + 1}. ${task.json.task_name}*\n`;
message += ` 📍 Участок: ${task.json.location}\n`;
message += ` ⏰ Срок: ${task.json.deadline}\n`;
message += ` 📝 ${task.json.description}\n\n`;
});
message += "\n_Ответьте на это сообщение статусом:_\n";
message += "✅ выполнил\n❌ не выполнил + причина";
return [{json: {message}}];#### 5. Status Update Handler
// Parse foreman response and update status
const message = $node["Telegram Trigger"].json["message"]["text"];
const replyTo = $node["Telegram Trigger"].json["message"]["reply_to_message"];
let status = "в работе";
let comment = "";
if (message.toLowerCase().includes("выполнил")) {
status = "выполнено";
} else if (message.toLowerCase().includes("не выполнил")) {
status = "не выполнено";
comment = message.replace(/не выполнил/i, "").trim();
}
return [{
json: {
task_id: replyTo.message_id,
status: status,
comment: comment,
updated_at: new Date().toISOString()
}
}];Tasks Sheet:
| Column | Description |
|---|---|
| task_id | Unique task identifier |
| task_name | Task title |
| description | Detailed description |
| location | Work location |
| deadline | Due date/time |
| foreman_chat_id | Telegram chat ID of assigned foreman |
| status | Current status |
| comment | Foreman comment |
Foremen Sheet:
| Column | Description |
|---|---|
| name | Foreman name |
| chat_id | Telegram chat ID |
| registered_at | Registration timestamp |
npx n8n --tunnelnpx n8n --tunnel~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.