# @doubleagent-so/node

```sh
npm install @doubleagent-so/node   # Node 20+, no dependencies
```

```ts
import { createDoubleAgent } from '@doubleagent-so/node';
const da = createDoubleAgent({ secretKey: process.env.DOUBLEAGENT_SECRET_KEY }); // secret only for getSession

const claims = await da.verifyToken(token, { site: 'st_…' });
// { sid, cls, p, agent?, rec, act, prof, site, iat, exp, v }. Throws DoubleAgentError.

app.post('/signup', da.requireHuman({ actions: ['signup'] }), handler);           // 401 / 403
app.post('/checkout', da.requireHuman({ allow: ['human', 'verified_agent'] }), h);

const d = await da.requireHuman({ actions: ['login'] }).check(request);          // fetch-style
const event = await da.verifyWebhook(rawBody, req.get('DoubleAgent-Signature'), secret);
const s = await da.getSession(sid);                                               // null if unknown or expired
```

`site` accepts your site id (`st_…`), a public key (`pk_…`) or an array of either. `da.stats({ from, to })` reads `/v1/stats` with your secret key; it throws `site_not_verified` until a domain is verified. The token is read from the `da_token` body field or the `x-doubleagent-token` header. Keys are cached for 24 h and tokens live 10 min.

Error codes: `malformed unsupported_alg unknown_kid bad_signature expired not_yet_valid wrong_site jwks_unavailable`.
