Skill: joseshiru/watchdog (version 1.0.0)

--- name: watchdog description: > Monitors websites, APIs, and cron jobs (watchdogs) using Watch.dog. Use it when the user asks to "check the status of my monitors", "check uptime", "review watchdogs", or "create a website monitor". IMPORTANT: Deleting monitors and watchdogs requires explicit prior confirmation from the user. When the user provides their credentials (WATCHDOG_API_KEY, WATCHDOG_API_URL) or modifies them, you MUST automatically execute the `list_monitors` tool as a silent test to verify the connection, and then inform them if it was successful by showing a summary of what the skill can do. version: "1.0.0" author: Watch.dog Team clawhub: true metadata: openclaw: emoji: "🐕" requires: bins: ["node"] mcp: transport: stdio command: node args: ["{baseDir}/index.js"] env: WATCHDOG_API_KEY: "" WATCHDOG_API_URL: "https://api.watch.dog/api/mcp_server.php" --- # Watchdog – OpenClaw Skill ## What does this skill do? Connects your AI agent with the **Watch.dog** platform to: - 🔭 **Actively monitor** websites, APIs, IPs, and ports (HTTP, Keyword, Ping) - 🫀 **Watch scheduled tasks** (cron jobs, backups, scripts) through Passive Watchdogs (Heartbeats) - 📊 **Check the status** of your infrastructure in real-time - Monitor statuses are interpreted as follows: - `0`: Down (Offline) - `1`: Up (Online) - `2` or `null`: New (New/Pending) - 🗑️ **Manage resources** (Pause, Resume, Delete) - 🌐 **Public Status Pages** (Tracker Pages) ## When to activate this skill Use it when the user: - Wants to create a monitor for a URL, website, API, or server - Asks about the status, historical uptime, or availability of their services - Needs to configure a watchdog for a scheduled task or cron job - Asks for a summary of their monitored infrastructure - Wants to pause, resume, or delete monitors or watchdogs from their account - Requests to configure their public status page (Tracker Page) ## Required Configuration Create a `.env` file in this folder with: ```env WATCHDOG_API_KEY="sk_live_your_key_here" WATCHDOG_API_URL="api_url_here" | "https://api.watch.dog/api/mcp_server.php" ``` > If you don't have an API Key, create one in your dashboard at [watch.dog](https://watch.dog). ### Clarification about Intervals - When creating monitors (`create_monitor`) or watchdogs (`create_watchdog`), if the user specifies a time (e.g. "every 5 minutes"), **always pass the exact value in seconds** (e.g. 300). - Be aware the remote API may auto-correct the interval if the user's plan does not support such high frequencies, so report the returned interval accurately. ## Available Tools | Tool | Description | | ---------------------------- | --------------------------------------------------- | | `list_monitors` | Lists all active monitors | | `create_monitor` | Creates an Active Monitor (HTTP, Keyword, Ping) | | `get_monitor_status` | Status and recent events of a specific monitor | | `pause_monitor` | Temporarily pauses an Active Monitor | | `resume_monitor` | Resumes a previously paused Active Monitor | | `delete_monitor` | Deletes an Active Monitor (Requires Confirmation) | | `get_monitor_uptime_history` | Uptime/Availability matrix of a monitor | | `update_tracker_page` | Configures the Public Status Page (`/monitors/...`) | | `list_watchdogs` | Lists all Passive Watchdogs/Heartbeats | | `create_watchdog` | Creates a Passive Watchdog for a cron job | | `get_watchdog_status` | Health status of the last ping of a watchdog | | `delete_watchdog` | Deletes a Passive Watchdog (Requires Confirmation) | ## Installation ```bash cd watchdog npm install ```

path: index.js
content: #!/usr/bin/env node
/**
 * Watchdog – OpenClaw MCP Skill (Native stdio)
 * Version: 1.0.0
 *
 * Implements the Model Context Protocol (MCP) over stdin/stdout.
 * - Prompts: defined locally (behavioral instructions for the LLM)
 * - Tools:   proxied to the remote Watch.dog MCP PHP server via HTTP
 *
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { readFileSync, existsSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import { z } from "zod";

// ─── Load .env if present ────────────────────────────────────────────────────

const __dirname = dirname(fileURLToPath(import.meta.url));
const envPath = join(__dirname, ".env");

if (existsSync(envPath)) {
  const envContent = readFileSync(envPath, "utf-8");
  for (const line of envContent.split("\n")) {
    const match = line.match(/^([A-Z_]+)\s*=\s*"?([^"\n]+)"?/);
    if (match) process.env[match[1]] = match[2].trim();
  }
}

// ─── Configuration ───────────────────────────────────────────────────────────

const CONFIG = {
  apiUrl:
    process.env.WATCHDOG_API_URL || "https://api.watch.dog/api/mcp_server.php",
  [REDACTED_SECRET] || "",
};

// ─── Behavioral Prompt (Prompts layer – separate from Tools) ─────────────────

const WATCHDOG_SYSTEM_PROMPT = `
You are the expert assistant and site reliability engineer for the Watch.dog platform.
Your mission is to help users monitor the health status of their web infrastructure, APIs, and scheduled tasks using the tools available to you.

Your tone should always be enthusiastic, highly technical, professional, and empathetic.

## Initialization Flow (Onboarding)

If the user activates this skill for the first time and has no API Key configured:
1. Greet them enthusiastically and explain that you need to connect to their Watch.dog account.
2. Ask them only for their API Key and API URL (and remind them they can create a free account at https://watch.dog).
3. Once the user provides the data, use your native file writing tools to automatically create or overwrite the .env file in the root of this skill with the exact following format:
   WATCHDOG_API_KEY="[user_key]"
   WATCHDOG_API_URL="[user_url]"
   Never ask the user to create the file manually.
4. Immediately after, execute list_monitors to test the connection.
   - If successful: celebrate with the user and offer to create their first monitor or watchdog.
   - If it fails with Auth Error: kindly ask them to verify their key and URL.

## Heuristics and Triggers

### Active Monitors (Uptime of URLs/IPs/Ports)
- Create surveillance for URL/IP/port → use create_monitor.
- View all sites → use list_monitors.
- View details, uptime, and downtimes of a site → use get_monitor_status or get_monitor_uptime_history.
- Pause or resume monitors → use pause_monitor or resume_monitor.
- Publish a list of monitors on a Status Page → use update_tracker_page. The tool will return the full URL (https://watch.dog/monitors/...).

### Passive Watchdogs (Cron Jobs / Heartbeats)
- Create scheduled task/script → use create_watchdog.
- View all tasks → use list_watchdogs.
- View details or latest ping of a task → use get_watchdog_status.

### Deletions (CRITICAL CONFIRMATION RULE)
If the user asks to delete a monitor or watchdog:
STOP! YOU MUST ask for ABSOLUTE confirmation before invoking \`delete_monitor\` or \`delete_watchdog\`.
Example: "You are about to irreversibly delete the monitor [Name]. Are you 100% sure you want to proceed?"
Only if the response is affirmative, execute it.

### Mandatory Clarification
If the user says "Monitor my server" without specifying the type, ALWAYS ask:
"Do you want Watch.dog to actively check your server (Active Monitor) or do you prefer us to give you a URL so your server can ping us (Passive Watchdog)?"

## Post-Execution Behavior Rules

### When creating a Monitor (create_monitor):
Enthusiastically inform the user. The result will include the exact ID and URL of the created monitor.

### When creating a Watchdog (create_watchdog) — CRITICAL RULE:
The response will include an endpoint_url. YOU MUST communicate it verbatim to the user like this:
"Watchdog created! For Watch.dog to know your task has finished, configure your server or crontab to make an HTTP [type] request to:
  [endpoint_url]
If Watch.dog does not receive that ping every [interval_seconds] seconds, it will assume the task failed and trigger an alert."

### Lists and Statuses (list_monitors / get_monitor_status):
FORBIDDEN to show raw JSON. Always present the information in a friendly way using emojis.
The state values of a monitor in the tool response are strictly interpreted as follows:
- \`"1"\` or \`1\`: 🟢 UP / ONLINE
- \`"0"\` or \`0\`: 🔴 DOWN / OFFLINE
- \`"2"\`, \`2\` or \`null\`: 🔵 NEW / PENDING (New or Paused)
- If it's a Watchdog: 🟢 HEALTHY or 🔴 MISSING PING

### Uptime History (get_monitor_uptime_history):
Provide a clear summary using percentage bars or friendly explanations about which days had downtimes.

### Errors:
- Auth Error → Kindly tell the user to verify their API Key or generate a new one in the Watch.dog dashboard.
- Plan limit exceeded → With empathy, suggest they upgrade their subscription.
- Any technical error → Never show the raw error. Translate it into plain language.
`;

// ─── Remote Tool Proxy ───────────────────────────────────────────────────────

/**
 * Calls a tool on the remote Watch.dog PHP MCP server via HTTP.
 * The PHP server acts as the pure business logic layer.
 */
async function callRemoteTool(toolName, args = {}) {
  // Remove undefined args
  Object.keys(args).forEach((k) => args[k] === undefined && delete args[k]);

  if (!CONFIG.apiKey) {
    throw new Error(
      "WATCHDOG_API_KEY is not configured. " +
        "Please configure it in the .env file of the skill or as an environment variable.",
    );
  }

  const response = await fetch(CONFIG.apiUrl, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
      Authorization: `Bearer ${CONFIG.apiKey}`,
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: `req_${Date.now()}`,
      method: "tools/call",
      params: { name: toolName, arguments: args },
    }),
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  const data = await response.json();

  if (data.error) {
    throw new Error(`[${data.error.code}] ${data.error.message}`);
  }

  return data?.result?.content?.[0]?.text ?? "{}";
}

// ─── MCP Server Setup ────────────────────────────────────────────────────────

const server = new McpServer({
  name: "watchdog",
  version: "1.0.0",
});

// ── Prompts: Behavioral Instructions ─────────────────────────────────────────

server.registerPrompt(
  "watchdog",
  {
    description:
      "Activates the Watchdog expert mode. Provides behavioral context to monitor web infrastructure, APIs, and cron jobs.",
    argsSchema: {},
  },
  () => ({
    messages: [
      {
        role: "user",
        content: { type: "text", text: WATCHDOG_SYSTEM_PROMPT },
      },
    ],
  }),
);

// ── Tools: list_monitors ──────────────────────────────────────────────────────

server.registerTool(
  "list_monitors",
  {
    description: "Lists all active uptime monitors for the account.",
    inputSchema: {
      status: z
        .enum(["up", "down", "paused", "all"])
        .optional()
        .describe("Optional. Filter by status."),
    },
  },
  async ({ status }) => {
    const text = await callRemoteTool("list_monitors", { status });
    return {
      content: [
        {
          type: "text",
          text: `[Data retrieved. Present it as a friendly markdown table using emojis 🟢🔴⏸️]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: create_monitor ─────────────────────────────────────────────────────

server.registerTool(
  "create_monitor",
  {
    description:
      "Creates an Active Uptime Monitor that periodically checks a URL, IP, or port.",
    inputSchema: {
      name: z.string().describe("Friendly name of the monitor"),
      url: z.string().describe("URL or hostname to monitor"),
      type: z.enum(["http", "keyword", "ping"]).describe("Type of check"),
      interval: z
        .number()
        .int()
        .positive()
        .describe("Check interval in seconds (e.g. 300 for 5 minutes)"),
      keyword: z
        .string()
        .optional()
        .describe(
          "Only required if type=keyword. String to search for in the HTML.",
        ),
    },
  },
  async ({ name, url, type, interval, keyword }) => {
    const text = await callRemoteTool("create_monitor", {
      name,
      url,
      type,
      interval,
      keyword,
    });
    return {
      content: [
        {
          type: "text",
          text: `[Transmit this JSON result to the user enthusiastically and celebrate the success]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: get_monitor_status ─────────────────────────────────────────────────

server.registerTool(
  "get_monitor_status",
  {
    description:
      "Gets the health status and recent events of a specific monitor.",
    inputSchema: {
      monitor_id: z
        .number()
        .int()
        .positive()
        .optional()
        .describe("Numeric ID of the monitor"),
      name: z
        .string()
        .optional()
        .describe("Exact name (case-sensitive) in case the ID is unknown"),
    },
  },
  async ({ monitor_id, name }) => {
    if (!monitor_id && !name)
      throw new Error("You must provide a monitor_id or name.");
    const text = await callRemoteTool("get_monitor_status", {
      monitor_id,
      name,
    });
    return {
      content: [
        {
          type: "text",
          text: `[Generate a verbal summary of the current status using this JSON data]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: list_watchdogs ─────────────────────────────────────────────────────

server.registerTool(
  "list_watchdogs",
  {
    description:
      "Lists all Watchdogs (Passive Heartbeats / Cron Jobs) for the account.",
    inputSchema: {
      status: z
        .enum(["healthy", "missing", "all"])
        .optional()
        .describe("Optional. Filter by health status."),
    },
  },
  async ({ status }) => {
    const text = await callRemoteTool("list_watchdogs", { status });
    return {
      content: [
        {
          type: "text",
          text: `[Data retrieved. Present it to the user in a single Markdown table with health emojis]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: create_watchdog ────────────────────────────────────────────────────

server.registerTool(
  "create_watchdog",
  {
    description:
      "Creates a Passive Watchdog (Cron Job / Heartbeat). Watch.dog will wait to receive a periodic ping.",
    inputSchema: {
      name: z.string().describe("Name of the cron job or scheduled task"),
      type: z.enum(["email", "post", "get"]).describe("Ping reception method"),
      interval: z
        .number()
        .int()
        .positive()
        .describe(
          "Grace margin in seconds (e.g. 300 for 5 minutes) before marking it down.",
        ),
    },
  },
  async ({ name, type, interval }) => {
    const text = await callRemoteTool("create_watchdog", {
      name,
      type,
      interval,
    });
    return {
      content: [
        {
          type: "text",
          text: `[CRITICAL RULE: You must send the user the endpoint_url and give them exact instructions on how to ping using this data]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: get_watchdog_status ────────────────────────────────────────────────

server.registerTool(
  "get_watchdog_status",
  {
    description:
      "Gets the health status (healthy/missing_ping) of a Watchdog and the info of the last ping.",
    inputSchema: {
      watchdog_id: z
        .number()
        .int()
        .positive()
        .optional()
        .describe("Numeric ID of the watchdog"),
      name: z
        .string()
        .optional()
        .describe("Exact name (case-sensitive) in case the ID is unknown"),
    },
  },
  async ({ watchdog_id, name }) => {
    if (!watchdog_id && !name)
      throw new Error("You must provide a watchdog_id or name.");
    const text = await callRemoteTool("get_watchdog_status", {
      watchdog_id,
      name,
    });
    return {
      content: [
        {
          type: "text",
          text: `[Summary of the status of the provided watchdog in JSON]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: delete_monitor ─────────────────────────────────────────────────────
server.registerTool(
  "delete_monitor",
  {
    description:
      "Irreversibly deletes an Active Monitor. REQUIRES PRIOR EXPLICIT CONFIRMATION FROM THE USER.",
    inputSchema: {
      monitor_id: z.number().int().positive().optional(),
      name: z.string().optional(),
    },
  },
  async ({ monitor_id, name }) => {
    const text = await callRemoteTool("delete_monitor", { monitor_id, name });
    return {
      content: [
        {
          type: "text",
          text: `[Inform the user about the success of this deletion based on this JSON]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: delete_watchdog ────────────────────────────────────────────────────
server.registerTool(
  "delete_watchdog",
  {
    description:
      "Irreversibly deletes a Passive Watchdog. REQUIRES PRIOR EXPLICIT CONFIRMATION FROM THE USER.",
    inputSchema: {
      watchdog_id: z.number().int().positive().optional(),
      name: z.string().optional(),
    },
  },
  async ({ watchdog_id, name }) => {
    const text = await callRemoteTool("delete_watchdog", { watchdog_id, name });
    return {
      content: [
        {
          type: "text",
          text: `[Inform the user about the success of this deletion based on this JSON]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: pause_monitor ──────────────────────────────────────────────────────
server.registerTool(
  "pause_monitor",
  {
    description: "Temporarily pauses an Active Monitor.",
    inputSchema: {
      monitor_id: z.number().int().positive().optional(),
      name: z.string().optional(),
    },
  },
  async ({ monitor_id, name }) => {
    const text = await callRemoteTool("pause_monitor", { monitor_id, name });
    return {
      content: [
        {
          type: "text",
          text: `[Monitor paused successfully. Confirm it to the user]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: resume_monitor ─────────────────────────────────────────────────────
server.registerTool(
  "resume_monitor",
  {
    description: "Resumes a previously paused Active Monitor.",
    inputSchema: {
      monitor_id: z.number().int().positive().optional(),
      name: z.string().optional(),
    },
  },
  async ({ monitor_id, name }) => {
    const text = await callRemoteTool("resume_monitor", { monitor_id, name });
    return {
      content: [
        {
          type: "text",
          text: `[Monitor resumed successfully. Confirm it to the user]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: get_monitor_uptime_history ─────────────────────────────────────────
server.registerTool(
  "get_monitor_uptime_history",
  {
    description:
      "Gets the Uptime/Availability matrix of a monitor for the last X days.",
    inputSchema: {
      monitor_id: z.number().int().positive().optional(),
      name: z.string().optional(),
      days: z
        .number()
        .int()
        .positive()
        .optional()
        .describe("Number of days to retrieve (default 30)"),
    },
  },
  async ({ monitor_id, name, days }) => {
    const text = await callRemoteTool("get_monitor_uptime_history", {
      monitor_id,
      name,
      days,
    });
    return {
      content: [
        {
          type: "text",
          text: `[Analyze this JSON matrix and present a clear and friendly verbal summary to the user]:\n${text}`,
        },
      ],
    };
  },
);

// ── Tools: update_tracker_page ────────────────────────────────────────────────
server.registerTool(
  "update_tracker_page",
  {
    description:
      "Configures the Public Status Page (Tracker Page) to display monitors to the public.",
    inputSchema: {
      page_url: z
        .string()
        .optional()
        .describe("Public alias or slug for the company (e.g. mycompany)."),
      monitors: z
        .array(z.string())
        .optional()
        .describe(
          "Array with names or IDs of the monitors you want to make public.",
        ),
    },
  },
  async ({ page_url, monitors }) => {
    const text = await callRemoteTool("update_tracker_page", {
      page_url,
      monitors,
    });
    return {
      content: [
        {
          type: "text",
          text: `[Status page configured successfully according to this JSON. Inform the user and tell them they can visit the public link of their Tracker Page]:\n${text}`,
        },
      ],
    };
  },
);

// ─── Start Server ────────────────────────────────────────────────────────────

const transport = new StdioServerTransport();
await server.connect(transport);


path: package-lock.json
content: {
  "name": "watchdog",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "watchdog",
      "version": "1.0.0",
      "license": "MIT",
      "dependencies": {
        "@modelcontextprotocol/sdk": "^1.0.0",
        "zod": "^3.22.0"
      },
      "bin": {
        "watchdog": "index.js"
      }
    },
    "node_modules/@hono/node-server": {
      "version": "1.19.9",
      "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18.14.1"
      },
      "peerDependencies": {
        "hono": "^4"
      }
    },
    "node_modules/@modelcontextprotocol/sdk": {
      "version": "1.27.1",
      "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@hono/node-server": "^1.19.9",
        "ajv": "^8.17.1",
        "ajv-formats": "^3.0.1",
        "content-type": "^1.0.5",
        "cors": "^2.8.5",
        "cross-spawn": "^7.0.5",
        "eventsource": "^3.0.2",
        "eventsource-parser": "^3.0.0",
        "express": "^5.2.1",
        "express-rate-limit": "^8.2.1",
        "hono": "^4.11.4",
        "jose": "^6.1.3",
        "json-schema-typed": "^8.0.2",
        "pkce-challenge": "^5.0.0",
        "raw-body": "^3.0.0",
        "zod": "^3.25 || ^4.0",
        "zod-to-json-schema": "^3.25.1"
      },
      "engines": {
        "node": ">=18"
      },
      "peerDependencies": {
        "@cfworker/json-schema": "^4.1.1",
        "zod": "^3.25 || ^4.0"
      },
      "peerDependenciesMeta": {
        "@cfworker/json-schema": {
          "optional": true
        },
        "zod": {
          "optional": false
        }
      }
    },
    "node_modules/accepts": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-types": "^3.0.0",
        "negotiator": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/ajv": {
      "version": "8.18.0",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "fast-deep-equal": "^3.1.3",
        "fast-uri": "^3.0.1",
        "json-schema-traverse": "^1.0.0",
        "require-from-string": "^2.0.2"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/epoberezkin"
      }
    },
    "node_modules/ajv-formats": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependenciesMeta": {
        "ajv": {
          "optional": true
        }
      }
    },
    "node_modules/body-parser": {
      "version": "2.2.2",
      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "^3.1.2",
        "content-type": "^1.0.5",
        "debug": "^4.4.3",
        "http-errors": "^2.0.0",
        "iconv-lite": "^0.7.0",
        "on-finished": "^2.4.1",
        "qs": "^6.14.1",
        "raw-body": "^3.0.1",
        "type-is": "^2.0.1"
      },
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/bytes": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/call-bound": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "get-intrinsic": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/content-disposition": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/content-type": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie-signature": {
      "version": "1.2.2",
      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=6.6.0"
      }
    },
    "node_modules/cors": {
      "version": "2.8.6",
      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "object-assign": "^4",
        "vary": "^1"
      },
      "engines": {
        "node": ">= 0.10"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/cross-spawn": {
      "version": "7.0.6",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "path-key": "^3.1.0",
        "shebang-command": "^2.0.0",
        "which": "^2.0.1"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/debug": {
      "version": "4.4.3",
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ms": "^2.1.3"
      },
      "engines": {
        "node": ">=6.0"
      },
      "peerDependenciesMeta": {
        "supports-color": {
          "optional": true
        }
      }
    },
    "node_modules/depd": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/ee-first": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/encodeurl": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/escape-html": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/etag": {
      "version": "1.8.1",
      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/eventsource": {
      "version": "3.0.7",
      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "eventsource-parser": "^3.0.1"
      },
      "engines": {
        "node": ">=18.0.0"
      }
    },
    "node_modules/eventsource-parser": {
      "version": "3.0.6",
      "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18.0.0"
      }
    },
    "node_modules/express": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "accepts": "^2.0.0",
        "body-parser": "^2.2.1",
        "content-disposition": "^1.0.0",
        "content-type": "^1.0.5",
        "cookie": "^0.7.1",
        "cookie-signature": "^1.2.1",
        "debug": "^4.4.0",
        "depd": "^2.0.0",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "etag": "^1.8.1",
        "finalhandler": "^2.1.0",
        "fresh": "^2.0.0",
        "http-errors": "^2.0.0",
        "merge-descriptors": "^2.0.0",
        "mime-types": "^3.0.0",
        "on-finished": "^2.4.1",
        "once": "^1.4.0",
        "parseurl": "^1.3.3",
        "proxy-addr": "^2.0.7",
        "qs": "^6.14.0",
        "range-parser": "^1.2.1",
        "router": "^2.2.0",
        "send": "^1.1.0",
        "serve-static": "^2.2.0",
        "statuses": "^2.0.1",
        "type-is": "^2.0.1",
        "vary": "^1.1.2"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/express-rate-limit": {
      "version": "8.2.1",
      "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ip-address": "10.0.1"
      },
      "engines": {
        "node": ">= 16"
      },
      "funding": {
        "url": "https://github.com/sponsors/express-rate-limit"
      },
      "peerDependencies": {
        "express": ">= 4.11"
      }
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/fast-uri": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/fastify"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/fastify"
        }
      ],
      "license": "BSD-3-Clause"
    },
    "node_modules/finalhandler": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.0",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "on-finished": "^2.4.1",
        "parseurl": "^1.3.3",
        "statuses": "^2.0.1"
      },
      "engines": {
        "node": ">= 18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/forwarded": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/fresh": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/hono": {
      "version": "4.12.3",
      "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=16.9.0"
      }
    },
    "node_modules/http-errors": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "depd": "~2.0.0",
        "inherits": "~2.0.4",
        "setprototypeof": "~1.2.0",
        "statuses": "~2.0.2",
        "toidentifier": "~1.0.1"
      },
      "engines": {
        "node": ">= 0.8"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/iconv-lite": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safer-buffer": ">= 2.1.2 < 3.0.0"
      },
      "engines": {
        "node": ">=0.10.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/ip-address": {
      "version": "10.0.1",
      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 12"
      }
    },
    "node_modules/ipaddr.js": {
      "version": "1.9.1",
      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/is-promise": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/isexe": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/jose": {
      "version": "6.1.3",
      "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/panva"
      }
    },
    "node_modules/json-schema-traverse": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/json-schema-typed": {
      "version": "8.0.2",
      "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause"
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/media-typer": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/merge-descriptors": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/mime-db": {
      "version": "1.54.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-db": "^1.54.0"
      },
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/negotiator": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/object-assign": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/object-inspect": {
      "version": "1.13.4",
      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/on-finished": {
      "version": "2.4.1",
      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ee-first": "1.1.1"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/once": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "wrappy": "1"
      }
    },
    "node_modules/parseurl": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/path-key": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/path-to-regexp": {
      "version": "8.3.0",
      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/pkce-challenge": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=16.20.0"
      }
    },
    "node_modules/proxy-addr": {
      "version": "2.0.7",
      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "forwarded": "0.2.0",
        "ipaddr.js": "1.9.1"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/qs": {
      "version": "6.15.0",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "side-channel": "^1.1.0"
      },
      "engines": {
        "node": ">=0.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/range-parser": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/raw-body": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.7.0",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/router": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.0",
        "depd": "^2.0.0",
        "is-promise": "^4.0.0",
        "parseurl": "^1.3.3",
        "path-to-regexp": "^8.0.0"
      },
      "engines": {
        "node": ">= 18"
      }
    },
    "node_modules/safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/send": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.3",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "etag": "^1.8.1",
        "fresh": "^2.0.0",
        "http-errors": "^2.0.1",
        "mime-types": "^3.0.2",
        "ms": "^2.1.3",
        "on-finished": "^2.4.1",
        "range-parser": "^1.2.1",
        "statuses": "^2.0.2"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/serve-static": {
      "version": "2.2.1",
      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "parseurl": "^1.3.3",
        "send": "^1.2.0"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/setprototypeof": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/shebang-command": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "shebang-regex": "^3.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/shebang-regex": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/side-channel": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3",
        "side-channel-list": "^1.0.0",
        "side-channel-map": "^1.0.1",
        "side-channel-weakmap": "^1.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-list": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-map": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-weakmap": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3",
        "side-channel-map": "^1.0.1"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/statuses": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/toidentifier": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.6"
      }
    },
    "node_modules/type-is": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "content-type": "^1.0.5",
        "media-typer": "^1.1.0",
        "mime-types": "^3.0.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/unpipe": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/vary": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/which": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "isexe": "^2.0.0"
      },
      "bin": {
        "node-which": "bin/node-which"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/wrappy": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/zod": {
      "version": "3.25.76",
      "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/colinhacks"
      }
    },
    "node_modules/zod-to-json-schema": {
      "version": "3.25.1",
      "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "peerDependencies": {
        "zod": "^3.25 || ^4"
      }
    }
  }
}


path: package.json
content: {
  "name": "watchdog",
  "version": "1.0.0",
  "description": "Official Watch.dog skill for OpenClaw. Monitors the health of websites, APIs, and scheduled tasks (cron jobs) using the Watch.dog platform.",
  "type": "module",
  "main": "index.js",
  "bin": {
    "watchdog": "./index.js"
  },
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [
    "watchdog",
    "monitoring",
    "uptime",
    "cron",
    "mcp",
    "openclaw",
    "skill",
    "clawhub"
  ],
  "author": "Watch.dog Team",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.22.0"
  }
}

Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)