{"_id":"@bobfromarcher/domainward","name":"@bobfromarcher/domainward","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@bobfromarcher/domainward","publishConfig":{"access":"public"},"version":"1.0.0","description":"A single HTTP API over the mailward and dnsward audit engines: one request returns a domain's email-authentication and DNS-health report with an overall grade. Built on Node's http, no third-party runtime code, no AI.","bin":{"domainward":"bin/domainward.js"},"main":"lib/server.js","scripts":{"test":"node test/test.js","start":"node bin/domainward.js"},"keywords":["domain","dns","email","deliverability","spf","dkim","dmarc","dnssec","api","http","audit","self-hosted","zero-dependency"],"author":{"name":"bobfromarcher"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bobfromarcher/domainward.git"},"bugs":{"url":"https://github.com/bobfromarcher/domainward/issues"},"homepage":"https://github.com/bobfromarcher/domainward#readme","engines":{"node":">=16"},"gitHead":"9caffdc7e6cb675bca1f14edd7966969af1e1865","_id":"@bobfromarcher/domainward@1.0.0","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-zymqNHXt9BwrLnNZFB1fjhmXO/s5q7thd024AJAq+oeWIsiEv9N3SMvZZPklxRxRsdehDnO5z3kvIDqDwoISvA==","shasum":"ec1f427b49543eab305a64831e1b8bc5ac5fc1fe","tarball":"https://registry.npmjs.org/@bobfromarcher/domainward/-/domainward-1.0.0.tgz","fileCount":7,"unpackedSize":38248,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICjq33Iq+77DufgTcnCdA0JGO5PWBEoZnrG2Tj6GIFBkAiAUxzglaTbPeN5S5PEcyXoV2/RBHgQRfUuRrFc87Gj1BQ=="}]},"_npmUser":{"name":"bobfromarcher","email":"chrisbellth@gmail.com"},"directories":{},"maintainers":[{"name":"bobfromarcher","email":"chrisbellth@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/domainward_1.0.0_1781952210773_0.9860381431343359"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-20T10:43:30.638Z","1.0.0":"2026-06-20T10:43:30.929Z","modified":"2026-06-20T10:43:31.295Z"},"maintainers":[{"name":"bobfromarcher","email":"chrisbellth@gmail.com"}],"description":"A single HTTP API over the mailward and dnsward audit engines: one request returns a domain's email-authentication and DNS-health report with an overall grade. Built on Node's http, no third-party runtime code, no AI.","homepage":"https://github.com/bobfromarcher/domainward#readme","keywords":["domain","dns","email","deliverability","spf","dkim","dmarc","dnssec","api","http","audit","self-hosted","zero-dependency"],"repository":{"type":"git","url":"git+https://github.com/bobfromarcher/domainward.git"},"author":{"name":"bobfromarcher"},"bugs":{"url":"https://github.com/bobfromarcher/domainward/issues"},"license":"MIT","readme":"# domainward\n\n[![npm](https://img.shields.io/npm/v/@bobfromarcher/domainward?color=cb3837&logo=npm)](https://www.npmjs.com/package/@bobfromarcher/domainward)\n[![CI](https://github.com/bobfromarcher/domainward/actions/workflows/ci.yml/badge.svg)](https://github.com/bobfromarcher/domainward/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/@bobfromarcher/domainward?color=blue)](LICENSE)\n\nOne HTTP API over the [mailward](https://github.com/bobfromarcher/mailward) and [dnsward](https://github.com/bobfromarcher/dnsward) audit engines. A single request returns a domain's email-authentication report, its DNS-health report, and a combined overall grade. Built on Node's built-in `http`, with no third-party runtime code and no AI. Results are deterministic because everything is read from live DNS.\n\n<p align=\"center\"><img src=\"demo.svg\" alt=\"a domainward API response\" width=\"520\"></p>\n\n## Run it\n\n```bash\nnpx @bobfromarcher/domainward\n# domainward listening on http://localhost:8080\n```\n\nOr with Docker:\n\n```bash\ndocker build -t domainward .\ndocker run -p 8080:8080 domainward\n```\n\n## Endpoints\n\n| Method | Path | Returns |\n| --- | --- | --- |\n| GET | `/v1/audit/{domain}` | Combined mail and dns report with an overall grade |\n| GET | `/v1/audit/mail/{domain}` | Email authentication (MX, SPF, DKIM, DMARC, MTA-STS, BIMI) |\n| GET | `/v1/audit/dns/{domain}` | DNS health (A/AAAA, NS, SOA, CAA, TTL, DNSSEC) |\n| GET | `/health` | Liveness |\n| GET | `/` | A small HTML index of the endpoints |\n\nYou can also pass the domain as a query string: `GET /v1/audit?domain=example.com`.\n\n### Example\n\n```bash\ncurl https://your-host/v1/audit/stripe.com\n```\n\n```json\n{\n  \"domain\": \"stripe.com\",\n  \"overall\": { \"score\": 81, \"grade\": \"B\" },\n  \"mail\": { \"score\": 87, \"grade\": \"B\", \"checks\": [ ... ] },\n  \"dns\":  { \"score\": 75, \"grade\": \"C\", \"checks\": [ ... ] }\n}\n```\n\nEach entry in `checks` has an `id`, `title`, `status` (`pass`, `warn`, `fail`, `info`), a `detail`, and a `fix` when the check is not passing.\n\n## Built in\n\n- **Response cache.** Identical requests inside the TTL are served from memory and return `x-cache: HIT`. Default 5 minutes.\n- **Rate limiting.** Per-IP, default 60 requests per minute. Over the limit returns `429` with `retry-after`.\n- **Input validation.** Bare IPs, `localhost` and malformed names are rejected with `400`.\n- **Hard timeout.** A slow audit returns `504` rather than hanging the connection.\n- **CORS.** `access-control-allow-origin: *`, so it can be called from a browser.\n\n## Configuration\n\n| Variable | Default | Meaning |\n| --- | --- | --- |\n| `PORT` | `8080` | Listen port |\n| `CACHE_TTL_MS` | `300000` | Response cache TTL |\n| `RATE_LIMIT` | `60` | Requests per IP per minute |\n| `AUDIT_TIMEOUT` | `6000` | Per-audit DNS timeout in ms |\n\n## Deploy\n\nThe image is a plain Node server with no third-party dependencies, so it runs anywhere that runs a container or a Node process:\n\n- **Docker / any VM:** `docker run -p 8080:8080 domainward`.\n- **Render or Railway:** point at this repo, they detect the Dockerfile, set the port to `8080`.\n- **Fly.io:** `fly launch` picks up the Dockerfile.\n\nDNSSEC checking uses a direct UDP DNS query. Most container hosts allow outbound UDP on port 53, but some serverless platforms block raw UDP, in which case the DNSSEC check degrades to \"not checked\" and the rest of the audit still works. For that reason a container or VM is the most reliable host.\n\n## A note on the vendored engines\n\n`lib/mailward.js` and `lib/dnsward.js` are copies of the published [@bobfromarcher/mailward](https://www.npmjs.com/package/@bobfromarcher/mailward) and [@bobfromarcher/dnsward](https://www.npmjs.com/package/@bobfromarcher/dnsward) packages. Vendoring keeps this service fully self-contained with no install step and no version surprises at deploy time.\n\n## Development\n\n```bash\ngit clone https://github.com/bobfromarcher/domainward\ncd domainward\nnode test/test.js\nnpm start\n```\n\nThe server is created by `createApp(deps)` in `lib/server.js`, which accepts injected audit functions, a clock, and limits, so the whole API is tested without touching the network.\n\n## License\n\nMIT, bobfromarcher.\n","readmeFilename":"README.md","_rev":"1-5fe2678598768c49d4a6db4dbb6fdf1a"}