SIRT Triage Agent Workshop
~15 min

Wire up D1 to surface the incident queue

Create a D1 database, run the seed migration, add the binding, and watch the incident queue populate with ten sample incidents.

Steps0 / 5
~15 min
  1. Navigate to the lesson-06-d1 directory

    Run `cd ..\lesson-06-d1` from your current lesson-05-empty directory.

  2. Create a D1 database

    Run `npx wrangler d1 create sirt-incidents`. Note the database_id from the output.

  3. Replace REPLACE_WITH_YOUR_DATABASE_ID in wrangler.jsonc

    Open `wrangler.jsonc` in the lesson-06-d1 folder. Find `REPLACE_WITH_YOUR_DATABASE_ID` and replace it with your actual database_id.

  4. Run the seed migration

    Run `npx wrangler d1 execute sirt-incidents --remote --file=migrations\001-seed.sql`.

  5. Install, deploy, and verify the queue

    Run `npm install` then `npm run deploy`, reload your app. You should see 10 incidents in the queue.

OpenCode shortcut

Paste this prompt into the OpenCode TUI to let your AI agent walk you through this lesson:

 

What is D1?

D1 is Cloudflare’s serverless SQL database. Under the hood, it’s SQLite — you get full SQL support, but it runs at the edge alongside your Worker. There’s no connection string, no VPN, no cold start penalty. Your Worker accesses D1 through a binding, which means it’s available as env.INCIDENTS_DB in your code with zero network hops.

Why D1 here? The incident queue needs structured data: incident IDs, titles, severity levels, timestamps, alert types, and raw telemetry payloads. D1 gives you a real SQL database for this without any infrastructure management.

D1 data flow: Worker to incident queue

flowchart LR
W[Worker] -->|env.INCIDENTS_DB| D1[(D1 Database)]
D1 --> T[incidents table]
T --> id[incident_id]
T --> src[source]
T --> title[title]
T --> sev[severity]
T --> ts[received_at]
T --> tel[raw_payload]
D1 -->|SQL query| W
W -->|JSON response| UI[UI Incident Queue]

Step 0: Navigate to the lesson-06-d1 directory

From your current lesson-05-empty directory, move to the lesson 06 directory:

cd ..\lesson-06-d1

Step 1: Create the D1 database

Run the following command to create a new D1 database:

npx wrangler d1 create sirt-incidents

The output will include a database_idcopy that value. It looks like this:

database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Step 2: Replace the database ID in wrangler.jsonc

Open lesson-06-d1\wrangler.jsonc in your editor. The D1 binding is already configured — you just need to replace the placeholder with your actual database ID.

Find this line:

"database_id": "REPLACE_WITH_YOUR_DATABASE_ID"

Replace REPLACE_WITH_YOUR_DATABASE_ID with the database_id you copied in Step 1:

"database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Step 3: Run the seed migration

The workshop app includes a pre-written migration file at migrations\001-seed.sql. This file creates an incidents table and inserts ten sample incidents.

Run the migration against your remote D1 database:

npx wrangler d1 execute sirt-incidents --remote --file=migrations\001-seed.sql

The --remote flag is important — it runs the migration on your deployed D1 database, not a local copy.

You should see output confirming the SQL was executed successfully.

The ten seeded incidents span a range of security scenarios:

  1. Malware + C2 Beacon — Encoded PowerShell, C2 IP communication
  2. Phishing + BEC — Credential harvesting, mailbox forwarding rule
  3. Anomalous Authentication — Impossible travel, MFA bypass via legacy protocol
  4. Data Exfiltration — Off-hours upload to personal cloud storage
  5. AI Prompt Injection — Attempt to extract system prompt from internal AI assistant
  6. CSPM Cloud Misconfiguration — S3 bucket changed to public access
  7. Credential Stuffing — Rotating-IP brute force against login endpoint
  8. User-Reported Phishing — Suspicious invoice email with .zip attachment
  9. Compromised CI Pipeline — Unauthorized npm package from CI runner
  10. Ransomware Encryption — Mass file encryption on file server

Step 4: Install dependencies and deploy

Install the lesson dependencies and deploy:

npm install
npm run deploy

Now reload your app in the browser. Instead of the “Incident Queue” placeholder, you should see ten incident cards in the queue, each showing:

  • The incident title
  • The severity level (P0, P1, P2)
  • The alert source
  • The timestamp

Click on an incident to see its detail view. At this stage, the detail view shows raw telemetry data but no analysis — that comes in later lessons when you add Workers AI and the agent harness.

Key takeaways

Before moving on, make sure these ideas land. They are the reason this lesson matters in the larger triage system.

  1. 1

    D1 is serverless SQLite beside your Worker

    D1 gives the incident queue a real SQL database without connection strings, VPNs, or database servers. The Worker reads structured incident data through a local binding.

  2. 2

    Bindings are the Cloudflare resource access pattern

    The D1 database is declared in wrangler.jsonc and appears as env.INCIDENTS_DB in code. The platform handles authentication, routing, and lifecycle behind that binding.

  3. 3

    Migrations make sample data reproducible

    The seed migration creates the same incident table and records for every participant. That keeps later AI and agent lessons working against known, realistic data.

Knowledge checkRequired to continue