{"_id":"@atoapayments/agentic-payment-approvals-js","_rev":"4-9460e40de896b1f669177d9cc051734c","name":"@atoapayments/agentic-payment-approvals-js","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.1":{"name":"@atoapayments/agentic-payment-approvals-js","version":"0.0.1","keywords":["atoa","approvals","agentic-payments","payments","webauthn","sdk","browser"],"author":{"name":"Atoa and contributors"},"license":"UNLICENSED","_id":"@atoapayments/agentic-payment-approvals-js@0.0.1","maintainers":[{"name":"shariqueatoa","email":"sharique@paywithatoa.co.uk"},{"name":"rvkrish","email":"vamsi@paywithatoa.co.uk"},{"name":"tushargupta224","email":"tushar@paywithatoa.co.uk"},{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},{"name":"anandtanu","email":"tanushree@paywithatoa.co.uk"}],"homepage":"https://github.com/ATOAPaymentsLimited/AtoaAgenticFramework/tree/main/packages/agentic-payment-approvals-js#readme","bugs":{"url":"https://github.com/ATOAPaymentsLimited/AtoaAgenticFramework/issues"},"dist":{"shasum":"ac751bc6728220ed86ffddfa82a9032b8d993fc0","tarball":"https://registry.npmjs.org/@atoapayments/agentic-payment-approvals-js/-/agentic-payment-approvals-js-0.0.1.tgz","fileCount":7,"integrity":"sha512-xEQKt54QqKR7YBxKiM8FZAkUJjJI69HDjWzPFLIyjjKYWFZX51ykihssxa4XVZJDj/o2Fd0f+1beQRoGh3/zGQ==","signatures":[{"sig":"MEYCIQDqxTPWRqB6FzYSYAk/SlsZTlo+9DfcouDCSQxPYISWpAIhAIEWLR2GC47PxNPfWExG0lxbKGsL6hNFGokKO903mAWm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45866},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","unpkg":"./dist/index.global.js","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"ce0e27b75a7564f2f37842bfc9612623e7bebf0d","private":false,"scripts":{"test":"node --test test/*.test.ts","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},"repository":{"url":"git+https://github.com/ATOAPaymentsLimited/AtoaAgenticFramework.git","type":"git","directory":"packages/agentic-payment-approvals-js"},"_npmVersion":"11.16.0","description":"Zero-dependency browser SDK to surface an Atoa payment-approval — open the hosted approval page (popup, modal, or redirect) and resolve the human decision. The decision credential (OTP, passkey) is only ever collected on the Atoa origin; host apps forward","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.5.0","@types/node":"^22.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/agentic-payment-approvals-js_0.0.1_1785245798607_0.11830972214146573","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@atoapayments/agentic-payment-approvals-js","version":"0.0.2","keywords":["atoa","approvals","agentic-payments","payments","webauthn","sdk","browser"],"author":{"name":"Atoa Payments Limited"},"license":"MIT","_id":"@atoapayments/agentic-payment-approvals-js@0.0.2","maintainers":[{"name":"shariqueatoa","email":"sharique@paywithatoa.co.uk"},{"name":"rvkrish","email":"vamsi@paywithatoa.co.uk"},{"name":"tushargupta224","email":"tushar@paywithatoa.co.uk"},{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},{"name":"anandtanu","email":"tanushree@paywithatoa.co.uk"}],"homepage":"https://docs.paywithatoa.co.uk/agent-pay/approvals","dist":{"shasum":"51c68e40f9cb22fe19d1ed7e0e8a1050be36b243","tarball":"https://registry.npmjs.org/@atoapayments/agentic-payment-approvals-js/-/agentic-payment-approvals-js-0.0.2.tgz","fileCount":9,"integrity":"sha512-nNSX0+rRyZZiGxG5w0j6IpsbBDIzqXjrCF+2OLr1nnRlY4Tg9Bb0RwAI8gtPTP6V/9awuc+Z013tz6WxddqHXQ==","signatures":[{"sig":"MEQCIAqOhMegOURu2Y7vPiGQY8DraO8kxFeV9xxje84yo2ZrAiB9IiIZKsVDcCITKKMBXk1IpphR4nt2DfccC8olo0oaOg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48399},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","unpkg":"./dist/index.global.js","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"6d992b974e4c6903cbe5258028f75c5236d9ef47","private":false,"scripts":{"test":"node --test test/*.test.ts","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},"_npmVersion":"11.16.0","description":"Zero-dependency browser SDK to surface an Atoa payment-approval — open the hosted approval page (popup, modal, or redirect) and resolve the human decision. The decision credential (OTP, passkey) is only ever collected on the Atoa origin; host apps forward","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.5.0","@types/node":"^22.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/agentic-payment-approvals-js_0.0.2_1785902624826_0.28535706096424196","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@atoapayments/agentic-payment-approvals-js","version":"0.0.3","keywords":["atoa","approvals","agentic-payments","payments","webauthn","sdk","browser"],"author":{"name":"Atoa Payments Limited"},"license":"MIT","_id":"@atoapayments/agentic-payment-approvals-js@0.0.3","maintainers":[{"name":"shariqueatoa","email":"sharique@paywithatoa.co.uk"},{"name":"rvkrish","email":"vamsi@paywithatoa.co.uk"},{"name":"tushargupta224","email":"tushar@paywithatoa.co.uk"},{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},{"name":"anandtanu","email":"tanushree@paywithatoa.co.uk"}],"homepage":"https://docs.paywithatoa.co.uk/agent-pay/approvals","dist":{"shasum":"482ac10be1917f5779b7e0a99fa14e0fe0c69cf4","tarball":"https://registry.npmjs.org/@atoapayments/agentic-payment-approvals-js/-/agentic-payment-approvals-js-0.0.3.tgz","fileCount":9,"integrity":"sha512-PiZvB+sHdJvyAnkjkC4dP+T8zaQOXA5FH6Sm51LdHjPYcPPr87UCICMfVIB/PKW+AXhtIr/odv1mLCB91A3R7A==","signatures":[{"sig":"MEQCIB4Kx5YXUgXQ0vcbg6xZ73qZrLxMZUr5H0PoEur1nOj7AiBuV4N8ufTFt0AmnMgluxNjURBqdEm/nDXF12ZcHa9Jlg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48217},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","unpkg":"./dist/index.global.js","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"a03cf5fa718eaf721ff42d7f3c6d600f45a74cbf","private":false,"scripts":{"test":"node --test test/*.test.ts","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},"_npmVersion":"11.16.0","description":"Zero-dependency browser SDK to surface an Atoa payment-approval — open the hosted approval page (popup, modal, or redirect) and resolve the human decision. The decision credential (OTP, passkey) is only ever collected on the Atoa origin; host apps forward","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.5.0","@types/node":"^22.0.0","@types/react":"^18.0.0"},"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/agentic-payment-approvals-js_0.0.3_1785929517761_0.23884425065489578","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@atoapayments/agentic-payment-approvals-js","version":"0.0.4","private":false,"type":"module","description":"Zero-dependency browser SDK to surface an Atoa payment-approval — open the hosted approval page (popup, modal, or redirect) and resolve the human decision. The decision credential (OTP, passkey) is only ever collected on the Atoa origin; host apps forward","keywords":["atoa","approvals","agentic-payments","payments","webauthn","sdk","browser"],"homepage":"https://docs.paywithatoa.co.uk/agent-pay/approvals","author":{"name":"Atoa Payments Limited"},"license":"MIT","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","unpkg":"./dist/index.global.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"publishConfig":{"access":"public"},"scripts":{"build":"tsup","test":"node --test test/*.test.ts","typecheck":"tsc --noEmit"},"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"devDependencies":{"@types/node":"^22.0.0","@types/react":"^18.0.0","tsup":"^8.0.0","typescript":"^5.5.0"},"gitHead":"759fdb9748b291ee470d8a7b968e223e7a7b7d9e","_id":"@atoapayments/agentic-payment-approvals-js@0.0.4","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-VZdVz26Mv+XGdEQpFgIr8T8f8sCFzzUv9GLvWihDZnTuQEMJm7VMUK8i9Lgv3pK2neQrjJIfrDg+p85HxSt7Gg==","shasum":"17a684f40fb825319e6aef05b2003f3c8819802f","tarball":"https://registry.npmjs.org/@atoapayments/agentic-payment-approvals-js/-/agentic-payment-approvals-js-0.0.4.tgz","fileCount":9,"unpackedSize":52023,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHY/8vdH6BFOBBJ3Z48P24617xhl17+xH3jIYQ83VlRnAiAJAhs1U2O80NV6xy3FT+wlqGhdQiXziM6kTKprbAW9RA=="}]},"_npmUser":{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},"directories":{},"maintainers":[{"name":"shariqueatoa","email":"sharique@paywithatoa.co.uk"},{"name":"rvkrish","email":"vamsi@paywithatoa.co.uk"},{"name":"tushargupta224","email":"tushar@paywithatoa.co.uk"},{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},{"name":"anandtanu","email":"tanushree@paywithatoa.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agentic-payment-approvals-js_0.0.4_1787651992948_0.059872946850421105"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-28T13:36:38.436Z","modified":"2026-08-25T09:59:53.279Z","0.0.1":"2026-07-28T13:36:38.755Z","0.0.2":"2026-08-05T04:03:45.011Z","0.0.3":"2026-08-05T11:31:57.880Z","0.0.4":"2026-08-25T09:59:53.080Z"},"author":{"name":"Atoa Payments Limited"},"license":"MIT","homepage":"https://docs.paywithatoa.co.uk/agent-pay/approvals","keywords":["atoa","approvals","agentic-payments","payments","webauthn","sdk","browser"],"description":"Zero-dependency browser SDK to surface an Atoa payment-approval — open the hosted approval page (popup, modal, or redirect) and resolve the human decision. The decision credential (OTP, passkey) is only ever collected on the Atoa origin; host apps forward","maintainers":[{"name":"shariqueatoa","email":"sharique@paywithatoa.co.uk"},{"name":"rvkrish","email":"vamsi@paywithatoa.co.uk"},{"name":"tushargupta224","email":"tushar@paywithatoa.co.uk"},{"name":"atoalicence","email":"licence@paywithatoa.co.uk"},{"name":"anandtanu","email":"tanushree@paywithatoa.co.uk"}],"readme":"# @atoapayments/agentic-payment-approvals-js\n\n**Keep the human approval of a gated payment inside your own web UI, instead of sending the user off to a redirect.** When an Atoa Agent Pay `payment.send(...)` or `payment.collect(...)` needs Strong Customer Authentication, it returns a `nextAction` with a `clientSecret`. Hand that secret to `confirmApproval` and this SDK mounts Atoa's hosted approval page as an iframe inside a container you provide — the approver enters their one-time code or passkey right there, and you get back the decision.\n\n[![npm version](https://img.shields.io/npm/v/@atoapayments/agentic-payment-approvals-js.svg)](https://www.npmjs.com/package/@atoapayments/agentic-payment-approvals-js)\n[![dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)](https://www.npmjs.com/package/@atoapayments/agentic-payment-approvals-js)\n[![types](https://img.shields.io/badge/types-included-blue.svg)](https://www.npmjs.com/package/@atoapayments/agentic-payment-approvals-js)\n![license](https://img.shields.io/badge/license-MIT-green.svg)\n\nThis is the browser companion to the `nextAction` that Atoa Agent Pay returns on a gated payment. It is **not** a payments SDK and is separate from [`@atoapayments/agent-pay`](https://www.npmjs.com/package/@atoapayments/agent-pay): its one job is to surface the approval UI. It is zero-dependency and framework-agnostic (React is an optional peer, not required).\n\nThere is exactly **one** surface: the mounted iframe. You own the chrome around it — render the container inline, inside your own modal, a bottom sheet, wherever — and the iframe fills it 100% x 100%. No popup windows, no full-page redirects.\n\nThe decision credential (OTP, passkey) is only ever collected on the Atoa origin. Your app provides a container and forwards the `clientSecret`; it never re-skins the approval or sees the code. That boundary is the security model — don't work around it.\n\n## Install\n\n```bash\nnpm i @atoapayments/agentic-payment-approvals-js\n```\n\nShips ESM + CJS + a `.d.ts`, plus a `unpkg` global build for a plain `<script>` tag.\n\n## Quickstart\n\n```ts\nimport { confirmApproval } from '@atoapayments/agentic-payment-approvals-js';\n\n// `payments` came from a gated `atoa.payment.send(...)` (or `.collect(...)`) in @atoapayments/agent-pay\nif (payments.nextAction) {\n  const approval = confirmApproval({\n    container: '#approval',                      // a selector or an HTMLElement you render + size\n    clientSecret: payments.nextAction.clientSecret,\n    colorScheme: 'light',                        // 'light' (default) | 'dark'\n    onEvent: (e) => console.log(e.type),\n  });\n\n  const { status } = await approval.result;\n  // status: 'APPROVED' | 'DECLINED' | 'EXPIRED' | 'SUPERSEDED' | 'CANCELLED'\n\n  // ...and from YOUR close affordance (backdrop click, sheet swipe-away, route change):\n  approval.destroy();                            // cancels if still pending (-> CANCELLED), removes the iframe\n}\n```\n\nYou decide where `#approval` lives and how big it is; the iframe is `100% x 100%` of it. Wrap it in your own modal or bottom sheet and the \"Approve GBP X\" card + code entry render inside — you never draw the approval itself.\n\n## Documentation\n\n- **Approvals SDK** — https://docs.paywithatoa.co.uk/agent-pay/approvals · [Theming](https://docs.paywithatoa.co.uk/agent-pay/approvals#theming) · [Events](https://docs.paywithatoa.co.uk/agent-pay/approvals#events)\n- **Where `nextAction` comes from** — [SCA on a payout](https://docs.paywithatoa.co.uk/agent-pay/send#sca-on-a-payout) · [SCA on a charge](https://docs.paywithatoa.co.uk/agent-pay/collect#sca-on-a-charge)\n- **Agent Pay overview** — https://docs.paywithatoa.co.uk/agent-pay/overview\n\n## `confirmApproval(options) → ApprovalHandle`\n\n| Option | Default | Notes |\n|---|---|---|\n| `container` | required | A CSS selector or an `HTMLElement`. You render + size it; the iframe fills it. Throws synchronously if it doesn't resolve to an element. |\n| `clientSecret` | required | From `nextAction`. Env (live/sandbox) is read from its prefix (`ap_live_...` / `ap_test_...`) — no publishable key; a malformed secret throws before any iframe is created. |\n| `colorScheme` | `light` | `'light'` or `'dark'`. Anything else (incl. `undefined`) normalizes to `light`. Independent of `theme`. |\n| `theme` | — | Bounded branding tokens (see Theming) — hex/length-validated and contrast-clamped. Amounts, warnings, and the decline button are never restyled. |\n| `labels` | — | Enumerated approve-CTA text only (see Labels). |\n| `onEvent` | — | Fires for every lifecycle event (same stream as `handle.on(...)`). |\n| `onResult` | — | Terminal-only convenience — called once with the final `{ status }`. |\n| `apiUrl` | — | Non-prod override for the hosted-page origin (e.g. `http://localhost:3001`). Ignored in normal use — the origin is derived from the secret's env prefix. |\n\n**`ApprovalHandle`** — the live handle you get back:\n\n- `result: Promise<{ status }>` — resolves **exactly once** with the terminal decision. Never rejects.\n- `on(listener) => unsubscribe` — subscribe to the lifecycle stream (same events as `onEvent`); returns an unsubscribe function.\n- `destroy()` — tear down: cancel a still-pending approval (-> `CANCELLED`), drop listeners, remove the iframe from the DOM.\n\n### Labels\n\n`labels` restyles only the approve button's verb, and only from a fixed enum — freetext is rejected (relabeling the decision away from \"you are paying\" is the dark-pattern vector this guards against). The page always appends the amount, so `PAY` renders as \"Pay GBP 42.00\". The decline label is fixed and never configurable.\n\n```ts\nlabels: { approve: 'PAY' } // 'APPROVE' (default) | 'PAY' | 'CONFIRM' | 'AUTHORIZE'\n```\n\nAnything outside the enum (or a non-object) is dropped and the default `APPROVE` is used. Branding tokens (`theme`) work the same way — see [Theming](https://docs.paywithatoa.co.uk/agent-pay/approvals#theming).\n\n## Events\n\nEvery event flows through both `onEvent` and every `on(...)` listener, as the same `{ type, ...payload }` object — filter on `e.type`. Payloads are enumerated/masked only: never an OTP, a full contact, or an account number. A listener that throws is swallowed and never breaks the stream.\n\n| `type` | Emitted when | Payload | Terminal? |\n|---|---|---|---|\n| `opened` | The instant the handle is created (iframe appended, channel listening). SDK-emitted. | — | no |\n| `loaded` | The page finished loading and resolved which CTA it will show. | `method?: 'PASSKEY' \\| 'SETUP_OFFERED' \\| 'OTP_ONLY'` | no |\n| `approved` | The human approved. | `decidedBy?: string` | yes -> `APPROVED` |\n| `declined` | The human declined. | `decidedBy?: string` | yes -> `DECLINED` |\n| `expired` | The approval window lapsed before a decision. | — | yes -> `EXPIRED` |\n| `superseded` | A newer approval for the same action replaced this one. | — | yes -> `SUPERSEDED` |\n| `error` | A recoverable page error. Non-terminal — the page may recover. | `reason: string` | no |\n| `closed` | You called `destroy()` (or it was auto-cancelled). Immediately precedes a `CANCELLED` result. SDK-emitted. | — | no |\n\n`error` does not settle `result` — the promise stays pending, and it's up to you to `destroy()` if you want to give up. `closed` is not itself terminal: the terminal `CANCELLED` status arrives on `result`/`onResult`, never as an event `type`.\n\n## Result & terminal statuses\n\n`result` (and `onResult`) resolve exactly once, with `{ status }`. Five statuses — the first four come from the page's terminal events, the fifth only from you:\n\n| Status | Source |\n|---|---|\n| `APPROVED` | `approved` event |\n| `DECLINED` | `declined` event |\n| `EXPIRED` | `expired` event |\n| `SUPERSEDED` | `superseded` event |\n| `CANCELLED` | You called `destroy()` before any of the above. |\n\n`result` never rejects — a page `error` leaves it pending rather than throwing, so always await a terminal status (or drive teardown yourself via `destroy()`).\n\n## When to call `destroy()`\n\n`destroy()` cancels a still-pending approval (resolving `result` as `CANCELLED` and emitting `closed`), drops all listeners, and removes the iframe. It is a no-op once a decision has landed. Call it from your own close affordance — the SDK draws no chrome, so nothing else can cancel for you:\n\n- a backdrop / overlay click, or the close button on your modal;\n- a bottom-sheet swipe-away or dismiss;\n- a route change or component unmount (`useEffect` cleanup, `onUnmounted`, etc.) — so an abandoned approval doesn't leak an iframe and a live `postMessage` listener.\n\nYou do not need to call it after a terminal decision — the SDK self-cleans on resolve. It's purely for the \"user walked away without deciding\" path.\n\n## Browser support, bundle size & CSP\n\n- **Zero runtime dependencies**, framework-agnostic. React is an optional peer (`>=17`) — used only for the ambient types; the SDK is plain DOM.\n- Works in any modern browser with `iframe` + `postMessage`. Passkey approval uses WebAuthn delegated to the cross-origin frame (`publickey-credentials-get` / `publickey-credentials-create`); where the browser doesn't support cross-origin passkey creation, the page falls back to a one-time code, so \"Set up passkey\" never dead-ends.\n- The hosting origin must be in the approval page's server-side `frame-ancestors` allowlist (per-business registered — never a wildcard). The `postMessage` handshake is origin-pinned: the page requests the secret and the SDK answers pinned to the page origin, so the secret never rides a URL.\n\n## Relationship to Agent Pay\n\nThis package is the browser front-end for the SCA approval that [`@atoapayments/agent-pay`](https://www.npmjs.com/package/@atoapayments/agent-pay) surfaces via `nextAction`. It is optional and independent: the same approval can be completed by handing the approver the raw `approvalUrl` from `nextAction` instead (and the Python SDK does exactly that, since this browser SDK is TypeScript-only). Use this package when you want the approval to happen inside your own web UI rather than via a redirect.\n\n## License\n\n**License.** MIT. This covers the code in this package.\n\n**Service terms.** Use of the Atoa API is governed by the Atoa Services Agreement: https://paywithatoa.co.uk/terms/. The MIT license applies to this SDK only and grants no rights to the Atoa service.\n\n**Trademarks.** \"Atoa\" and the Atoa logo are trademarks of Atoa Payments Limited. The MIT license grants rights in the code, not in our names or marks — a modified or redistributed copy must not be presented as an Atoa product.\n\n**Security.** Report vulnerabilities to hello@paywithatoa.co.uk — please do not open a public issue.\n","readmeFilename":"README.md"}