)]}'
{
  "commit": "face465a7301cf567ff172372756dd0b72832e2d",
  "tree": "88db03b3c9eb0985ffeefc7cad3748e3bed3b995",
  "parents": [
    "279ebc6c8b93a667f3078a0445ccc789bf063f60"
  ],
  "author": {
    "name": "Jarek Potiuk",
    "email": "jarek@potiuk.com",
    "time": "Sat Apr 25 17:26:15 2026 +0200"
  },
  "committer": {
    "name": "Jarek Potiuk",
    "email": "jarek@potiuk.com",
    "time": "Sun Apr 26 22:19:00 2026 +0200"
  },
  "message": "Add unit tests and CI for ponymail-mcp\n\nThe mcp/ponymail-mcp package shipped without tests or CI. This adds\nboth, using only built-in Node tooling so the dependency tree stays\nunchanged.\n\n- restrictions.test.js: 15 unit tests covering pattern grammar\n  (prefix@, @domain, prefix@domain), env-var parsing edge cases\n  (none, empty, mixed case, whitespace), case-insensitive input\n  matching, restrictionFor/restrictionForAddress/isRestricted/\n  restrictionError/listRestrictions, and falsy-input tolerance.\n  Each test that exercises a different env spawns a child node\n  process and re-imports restrictions.js, since RESTRICTED is\n  captured at module load.\n- auth.test.js: 8 unit tests for the session-persistence helpers\n  (loadSession, clearSession). Each test runs in a child process\n  with HOME pointed at a temporary directory so the on-disk\n  session.json is fully isolated. Covers: missing file, fresh\n  cookie, expired cookie, missing-timestamp behaviour, malformed\n  JSON, missing cookie field, and clearSession idempotency. The\n  interactive performLogin() flow (browser, local HTTP server,\n  network validation) is out of scope for unit tests.\n- package.json: adds `npm test` script using node:test with the\n  spec reporter, and declares engines.node: \u003e\u003d20 (uses node:test\n  built-in runner; no new deps).\n- .github/workflows/ponymail-mcp-tests.yml: runs the suite on\n  push/PR (path-filtered to mcp/ponymail-mcp/) on Node 20 and 22.\n  Hardened: top-level `permissions: {}` (deny-all) with per-job\n  contents: read, third-party actions pinned to commit SHAs with\n  version comments, actions/checkout sets persist-credentials:\n  false, 10-minute job timeout.\n\nGenerated-by: Claude Code (Claude Opus 4.7)\n",
  "tree_diff": [
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "dbac030d35f3164cef2474191a84cc2e955760bc",
      "new_mode": 33188,
      "new_path": ".github/workflows/ponymail-mcp-tests.yml"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "405b0d038538be8bf537d8cb819dd15c623e3e9e",
      "new_mode": 33188,
      "new_path": "mcp/ponymail-mcp/auth.test.js"
    },
    {
      "type": "modify",
      "old_id": "19a9ba3349244aa0f10c857a61ad0945404a022c",
      "old_mode": 33188,
      "old_path": "mcp/ponymail-mcp/package.json",
      "new_id": "76f34d619eaa50da6e6b10c3a3be2f1450ce233e",
      "new_mode": 33188,
      "new_path": "mcp/ponymail-mcp/package.json"
    },
    {
      "type": "modify",
      "old_id": "542be1c08bd7ae5d97a3a405172ca8b115c2eba9",
      "old_mode": 33188,
      "old_path": "mcp/ponymail-mcp/restrictions.test.js",
      "new_id": "a472de94194507e935fdf3728f0fda2be204108c",
      "new_mode": 33188,
      "new_path": "mcp/ponymail-mcp/restrictions.test.js"
    }
  ]
}
