> ## Documentation Index
> Fetch the complete documentation index at: https://docs.onefirewall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Release: v2026-05-18

> Tasks — Scheduled Intelligence Automation & Alerting

# Tasks — Scheduled Intelligence Automation & Alerting

## Overview

OneFirewall now includes a **Tasks** engine: a built-in automation system that lets users schedule periodic queries against OneFirewall's threat intelligence APIs, evaluate conditions on the responses, and deliver notifications through in-app or email channels.

Tasks replace the need for external cron scripts or third-party alerting integrations for common OneFirewall workflows. Everything is configured through a guided, multi-step wizard directly inside the portal.

***

## What Tasks Do

A Task is a scheduled unit of work with three parts:

1. **One or more API queries** — the Task calls internal OneFirewall API endpoints on a schedule.
2. **Conditions** — the Task evaluates the API response against user-defined rules (e.g. `score > 500`). Notification is only sent when conditions pass. Conditions can be omitted to notify on every run.
3. **Notification delivery** — the Task sends a message to the in-app notification bell, to email, or both.

***

## Task Types

| Type            | Behaviour                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------- |
| `api_condition` | Calls one or more APIs, checks conditions, sends a templated notification when conditions are met. |
| `api_fetch`     | Calls an API and sends the raw or templated response as a notification unconditionally.            |
| `hello_world`   | Sends a static message (useful for testing notification delivery).                                 |

***

## Guided Wizard

Creating a task uses a **6-step wizard**:

### Step 1 — Task Name

Give the task a short descriptive name (e.g. `Alert on High-Risk IP`).

### Step 2 — API Calls

Add one or more OneFirewall API endpoints to query. A searchable preset picker covers common endpoints:

* IP / Domain / URL / File Hash intelligence
* Files, Domains, URLs, IPs above a score threshold
* Defence rules, overview statistics, and more

Each API call has a **Test** button that fires the request live and shows the JSON response inline — useful for discovering which field names to use in conditions and templates.

Multiple API calls are executed in sequence. Responses are merged into a single template data object for use in Step 3.

**Timestamp tokens** in API paths are automatically resolved at execution time:

| Token         | Resolves to                          |
| ------------- | ------------------------------------ |
| `__now__`     | Current Unix timestamp (ms)          |
| `__24h_ago__` | Unix timestamp 24 hours earlier (ms) |

This allows recurring tasks to always query a rolling time window without manual updates.

### Step 3 — Conditions & Template

**Conditions** define when a notification is sent. Each condition targets a field from an API response and evaluates it against a value.

| Operator   | Description                      |
| ---------- | -------------------------------- |
| `>`        | Greater than                     |
| `<`        | Less than                        |
| `>=`       | Greater than or equal            |
| `<=`       | Less than or equal               |
| `==`       | Exact string match               |
| `!=`       | Not equal                        |
| `contains` | Case-insensitive substring match |

Multiple conditions are combined with **AND** (all must pass) or **OR** (any must pass) logic, selectable per task.

When a task has multiple API calls, each condition can target a specific call's response using `api_index`.

**Notification Template** defines the message content using `{{fieldName}}` placeholders:

```
Alert: {{score}} score detected for {{ip}} — reported by {{members}} members
```

For the second API call onwards, use prefixed references:

```
Top actor: {{api2_1_actor}} with score {{api2_1_score}} in {{api2_1_country}}
```

Array responses are automatically flattened up to 10 items with numbered prefixes (`api2_1_*`, `api2_2_*`, …), making it straightforward to reference ranked list data in templates.

**HTML templates** are supported — if the template begins with `<!DOCTYPE html>` or `<html`, it is treated as an HTML document. In-app notifications receive the stripped plain-text version; emails receive the full HTML.

### Step 4 — Notification Channel

| Channel              | Behaviour                                                                          |
| -------------------- | ---------------------------------------------------------------------------------- |
| **App Notification** | Appears in the bell icon in the top navigation bar. Unread count shown as a badge. |
| **Email only**       | Sent to the task owner's registered email address.                                 |
| **Email + App**      | Delivered to both channels simultaneously.                                         |

For email-capable channels, **additional recipients** can be added — up to 20 extra addresses beyond the task owner's account email.

SMTP delivery uses `config.json` settings (`smtp.server`, `smtp.port`, `smtp.username`, `smtp.password`). Environment variables take precedence if set: `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`.

### Step 5 — Schedule

| Option            | Behaviour                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------- |
| **Now**           | Executes immediately on creation (one-shot).                                                |
| **One time**      | Runs once at a specified date and time.                                                     |
| **Every X hours** | Recurs on an hourly interval (1, 2, 3, 4, 6, 8, or 12 hours).                               |
| **Recurring**     | Daily, Weekly (specific day of week), or Monthly (specific day of month), at a chosen time. |

Recurring tasks automatically reschedule themselves after each execution. One-time and "now" tasks are marked `done` after a single run.

### Step 6 — Review & Activate

A summary of the full task configuration is presented before submission. Navigate back to any step to make changes. Click **Activate Task** to create and start scheduling the task.

***

## Upcoming Tasks Table

The **Upcoming Tasks** card shows all active and pending tasks for the organisation with:

* **Task name** (click to open the detail view)
* Notification channel
* Next scheduled run time (relative, e.g. "In 3 hours and 42 min")
* Recurrence pattern
* Last sent time
* Execution status: `pending`, `running`, `done`, `failed`

Clicking a task name opens a detail modal showing the full configuration: API calls, conditions with logic, notification template, last message sent, and any error from the most recent run.

***

## Task Log

The **Task Log** card provides a paginated audit trail of all task executions:

* Timestamp (relative)
* Event name (task name)
* Message preview (click to view full content, including rendered HTML in a sandboxed iframe)
* Delivery channel
* Status

Individual entries can be deleted, or the entire log can be cleared with a single action.

***

## Global Enable / Disable

A toggle in the **Configurations** card enables or disables the Tasks engine organisation-wide. When disabled, no scheduled tasks execute and no notifications are delivered. The state is persisted per user account.

***

## In-App Notification Bell

Tasks that target the `app` or `email_app` channel surface notifications in the **bell icon** in the top navigation bar. The bell shows an unread badge count. Clicking opens a notification panel where messages can be read, dismissed, or navigated to the full task log.

***

## Deep-Link Pre-Population

Other pages in the portal can link directly to the task wizard with fields pre-filled using URL query parameters. This allows one-click task creation from intelligence views with the correct API path, conditions, and template already configured.

Supported parameters include: `name`, `api`, `cond_0_field`, `cond_0_op`, `cond_0_val`, `logic`, `template`, `channel`, `sched_type`, and recurrence options.

***

## Backend & Reliability

The Task Runner executes on a **distributed, atomic-claim model**:

* An hourly sweep claims and runs all tasks with `scheduled_at ≤ now`.
* Tasks scheduled for immediate execution (`now`) are triggered directly from the creation API without waiting for the next sweep.
* Only one replica can claim a task at a time — `findOneAndUpdate` with a status guard prevents double-execution in multi-instance deployments.
* Tasks left `in_progress` for more than **5 minutes** (e.g. after a container crash) are automatically recovered and returned to `pending` on the next sweep.

***

## API Endpoints

| Method   | Path                                    | Description                         |
| -------- | --------------------------------------- | ----------------------------------- |
| `GET`    | `/api/v1/tasks/config`                  | Get global Tasks enabled state      |
| `PUT`    | `/api/v1/tasks/config`                  | Set global Tasks enabled state      |
| `POST`   | `/api/v1/tasks`                         | Create a new task                   |
| `GET`    | `/api/v1/tasks/upcoming`                | List all tasks for the organisation |
| `DELETE` | `/api/v1/tasks/:tid`                    | Delete a task                       |
| `GET`    | `/api/v1/tasks/log`                     | Paginated task execution log        |
| `DELETE` | `/api/v1/tasks/log/:lid`                | Delete a single log entry           |
| `DELETE` | `/api/v1/tasks/log`                     | Clear the entire task log           |
| `GET`    | `/api/v1/tasks/notifications/unread`    | Fetch unread in-app notifications   |
| `PUT`    | `/api/v1/tasks/notifications/:nid/read` | Mark a notification as read         |
| `DELETE` | `/api/v1/tasks/notifications/:nid`      | Delete a notification               |

***

## Weekly Email Reports

Tasks are the built-in way to send recurring security digest emails — no external tooling required. The sections below show how to build a weekly report that consolidates Live Traffic, the Defence Center, and the Threat Intelligence overview into a single formatted email.

### Which Endpoints to Query

These endpoints return JSON and work without manual timestamp parameters — they use their own internal windows or current-state snapshots:

| Endpoint                                        | Data                                                                          | Internal window                               |
| ----------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------- |
| `GET /api/v1/graphs/overview`                   | Total counts of Live IPv4 rules, File Signatures, Domains, URLs, IPv6 entries | 15-day trend + all-time totals                |
| `GET /api/v1/defense`                           | Active agent count, total blocked attacks, unique threat actors               | Last 24 hours                                 |
| `GET /api/v1/graphs/traffic/malicious/top`      | Top malicious IPs seen in live firewall traffic, with scores and geolocation  | Last hour (default when no timestamps passed) |
| `GET /api/v1/graphs/traffic/malicious/detailed` | Detailed traffic breakdown by risk category (low/medium/high/critical)        | Last hour (default)                           |

> **Timestamp note for Live Traffic:** `/malicious/top` and `/malicious/detailed` accept optional `from_ts` and `to_ts` query parameters in **Unix seconds**. When omitted, both default to the last hour automatically, which is the right behaviour for a recurring task — every run always reflects the most recent hour.

### Building the Weekly Report Task

Follow the wizard with these settings:

**Step 1 — Name**

```
Weekly Security Digest
```

**Step 2 — API Calls**

Add three calls in sequence:

| Call | Path                                   |
| ---- | -------------------------------------- |
| 1    | `/api/v1/graphs/overview`              |
| 2    | `/api/v1/defense`                      |
| 3    | `/api/v1/graphs/traffic/malicious/top` |

Use the **Test** button on each to verify the live JSON response and confirm field names before proceeding.

**Step 3 — Conditions & Template**

Leave conditions **empty** — the task will notify on every scheduled run regardless of values.

Paste an HTML template in the Notification Template field. Because the template starts with `<!DOCTYPE html>`, the Task Runner automatically treats it as HTML: the email receives the full rendered document, and the in-app notification receives the stripped plain-text version.

Example template:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  body { font-family: Arial, sans-serif; background: #f4f6f9; margin: 0; padding: 20px; }
  .container { max-width: 640px; margin: auto; background: #fff; border-radius: 8px; padding: 30px; }
  h1 { color: #2c3e50; font-size: 22px; margin-bottom: 4px; }
  .subtitle { color: #7f8c8d; font-size: 13px; margin-bottom: 24px; }
  .section { margin-bottom: 24px; }
  .section-title { font-size: 12px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: #7f8c8d; margin-bottom: 10px; border-bottom: 1px solid #ecf0f1; padding-bottom: 6px; }
  .stat-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
  .stat { background: #f8fafc; border: 1px solid #e8ecef; border-radius: 6px;
    padding: 12px 16px; flex: 1; min-width: 120px; }
  .stat-value { font-size: 24px; font-weight: 700; color: #2c3e50; }
  .stat-label { font-size: 11px; color: #95a5a6; margin-top: 2px; }
  .actor-row { background: #f8fafc; border-left: 3px solid #e74c3c;
    padding: 8px 12px; margin-bottom: 6px; border-radius: 0 4px 4px 0; font-size: 13px; }
  .actor-ip { font-weight: 600; color: #c0392b; }
  .actor-meta { color: #7f8c8d; font-size: 11px; }
  .footer { font-size: 11px; color: #bdc3c7; margin-top: 24px; border-top: 1px solid #ecf0f1; padding-top: 12px; }
</style>
</head>
<body>
<div class="container">
  <h1>Weekly Security Digest</h1>
  <div class="subtitle">OneFirewall — automated report</div>

  <div class="section">
    <div class="section-title">Threat Intelligence Database</div>
    <div class="stat-row">
      <div class="stat">
        <div class="stat-value">{{graph1.value}}</div>
        <div class="stat-label">Live IPv4 Rules</div>
      </div>
      <div class="stat">
        <div class="stat-value">{{graph2.value}}</div>
        <div class="stat-label">File Signatures</div>
      </div>
      <div class="stat">
        <div class="stat-value">{{graph3.value}}</div>
        <div class="stat-label">Domains</div>
      </div>
      <div class="stat">
        <div class="stat-value">{{graph4.value}}</div>
        <div class="stat-label">URLs</div>
      </div>
    </div>
  </div>

  <div class="section">
    <div class="section-title">Defence Center — Last 24 Hours</div>
    <div class="stat-row">
      <div class="stat">
        <div class="stat-value">{{api2.attacks}}</div>
        <div class="stat-label">Blocked Attacks</div>
      </div>
      <div class="stat">
        <div class="stat-value">{{api2.actors}}</div>
        <div class="stat-label">Unique Threat Actors</div>
      </div>
    </div>
  </div>

  <div class="section">
    <div class="section-title">Top Malicious Actors — Last Hour of Live Traffic</div>
    <div class="actor-row">
      <span class="actor-ip">{{api3_1_actor}}</span>
      <span class="actor-meta"> &nbsp;·&nbsp; Score {{api3_1_live_score}} &nbsp;·&nbsp; {{api3_1_ip_info_country}}</span>
    </div>
    <div class="actor-row">
      <span class="actor-ip">{{api3_2_actor}}</span>
      <span class="actor-meta"> &nbsp;·&nbsp; Score {{api3_2_live_score}} &nbsp;·&nbsp; {{api3_2_ip_info_country}}</span>
    </div>
    <div class="actor-row">
      <span class="actor-ip">{{api3_3_actor}}</span>
      <span class="actor-meta"> &nbsp;·&nbsp; Score {{api3_3_live_score}} &nbsp;·&nbsp; {{api3_3_ip_info_country}}</span>
    </div>
    <div class="actor-row">
      <span class="actor-ip">{{api3_4_actor}}</span>
      <span class="actor-meta"> &nbsp;·&nbsp; Score {{api3_4_live_score}} &nbsp;·&nbsp; {{api3_4_ip_info_country}}</span>
    </div>
    <div class="actor-row">
      <span class="actor-ip">{{api3_5_actor}}</span>
      <span class="actor-meta"> &nbsp;·&nbsp; Score {{api3_5_live_score}} &nbsp;·&nbsp; {{api3_5_ip_info_country}}</span>
    </div>
  </div>

  <div class="footer">Generated automatically by OneFirewall Tasks</div>
</div>
</body>
</html>
```

**Template field reference:**

| Placeholder                  | Source                           | Field                              |
| ---------------------------- | -------------------------------- | ---------------------------------- |
| `{{graph1.value}}`           | API 1 (`/graphs/overview`)       | Total Live IPv4 rule count         |
| `{{graph2.value}}`           | API 1                            | Total File Signature count         |
| `{{graph3.value}}`           | API 1                            | Total Domain count                 |
| `{{graph4.value}}`           | API 1                            | Total URL count                    |
| `{{api2.attacks}}`           | API 2 (`/defense`)               | Blocked attack events (last 24h)   |
| `{{api2.actors}}`            | API 2                            | Unique threat actor IPs (last 24h) |
| `{{api3_1_actor}}`           | API 3 (`/malicious/top`), item 1 | Top threat actor IP                |
| `{{api3_1_live_score}}`      | API 3, item 1                    | OFA threat score                   |
| `{{api3_1_ip_info_country}}` | API 3, item 1                    | Geolocation country                |
| `{{api3_2_actor}}` …         | API 3, item 2–5                  | Second through fifth actors        |

The array-flattening logic in the Task Runner automatically expands the `malicious/top` response array into `api3_1_*`, `api3_2_*`, … prefixed keys — up to 10 items — so no custom scripting is needed.

**Step 4 — Notification Channel**

Select **Email + App Notification**.

For an organisation-wide report, add the team's shared security mailbox under **Additional Recipients**.

**Step 5 — Schedule**

Select **Recurring → Weekly → Monday → 09:00** (or whichever day and time fits your team's review cadence).

**Step 6 — Review & Activate**

Confirm all three API calls, the HTML template, and the weekly schedule, then click **Activate Task**.

***

### Extending the Report

To add more data to the same report, add additional API calls in Step 2 and reference them in the template using `{{api4_…}}`, `{{api5_…}}`, etc.

Common additions:

| Call | Path                                        | Adds to report                                                                     |
| ---- | ------------------------------------------- | ---------------------------------------------------------------------------------- |
| 4th  | `/api/v1/graphs/traffic/malicious/detailed` | Traffic risk category breakdown (low/medium/high/critical counts)                  |
| 4th  | `/api/v1/feeds/500/5/10`                    | Current intelligence feed (IPs with score ≥ 500, seen by ≥ 5 members, ≥ 10 events) |
| 4th  | `/api/v1/domains/score/500`                 | Domains above a threat score threshold                                             |
| 4th  | `/api/v1/files/score/500`                   | Malicious file hashes above threshold                                              |

### Sending to Multiple Teams

Create one task per audience and adjust the **Additional Recipients** list in Step 4:

* `SOC Weekly Digest` → SOC team mailing list
* `Executive Weekly Summary` → same API calls, simplified template without raw IPs
* `CISO Board Report` → monthly schedule, higher-level stats only

Each task is independent and can have its own schedule, template, and recipient list.

***

## Summary

* **Scheduled API queries** against any OneFirewall endpoint — run now, one-time, hourly, or on a daily/weekly/monthly recurring schedule.
* **Condition engine** with 7 operators, AND/OR logic, and multi-API-call support.
* **Mustache-style templates** with automatic array flattening and full HTML email support.
* **Three notification channels**: in-app bell, email, or both — with configurable additional recipients.
* **Live API test** in the wizard so you can inspect the JSON response before setting up conditions.
* **Task log** with paginated history and inline HTML message preview.
* **Distributed, crash-safe execution** with atomic locking and stale-task recovery.
* **Deep-link URL support** for pre-populating the wizard from other pages in the portal.

> Tasks bring proactive alerting directly into OneFirewall — no external cron jobs, no third-party webhooks, no scripting required.
