diff --git a/openapi.yaml b/openapi.yaml index c561cfb..7a6b54e 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -27,6 +27,7 @@ paths: '200': { description: Replay of an earlier request with the same key and body } '400': { $ref: '#/components/responses/Error' } '401': { $ref: '#/components/responses/Error' } + '413': { $ref: '#/components/responses/Error' } '422': { description: Idempotency-Key reused with a different body } /v1/orders/{id}: get: @@ -36,6 +37,7 @@ paths: - { name: id, in: path, required: true, schema: { type: string } } responses: '200': { description: The order, content: { application/json: { schema: { $ref: '#/components/schemas/Order' } } } } + '401': { $ref: '#/components/responses/Error' } '404': { $ref: '#/components/responses/Error' } /v1/orders/{id}/cancel: post: @@ -44,7 +46,8 @@ paths: parameters: - { name: id, in: path, required: true, schema: { type: string } } responses: - '200': { description: The cancelled order } + '200': { description: The cancelled order, content: { application/json: { schema: { $ref: '#/components/schemas/Order' } } } } + '404': { $ref: '#/components/responses/Error' } '409': { description: The order can no longer be cancelled } components: securitySchemes: diff --git a/web/src/content/docs/docs/connect/android-forwarder.md b/web/src/content/docs/docs/connect/android-forwarder.md index bb78563..b58e555 100644 --- a/web/src/content/docs/docs/connect/android-forwarder.md +++ b/web/src/content/docs/docs/connect/android-forwarder.md @@ -1,12 +1,35 @@ --- title: Android forwarder -description: Pass bank SMS and app alerts to Kaasu. +description: Pass bank SMS and app alerts from an Android phone to Kaasu. sidebar: order: 1 --- -The forwarder is a small Android app on a phone that receives your bank alerts. It signs each alert with a key unique to that phone and sends it to Kaasu. +> **Status:** the server side (pairing and signed ingest) is done and tested. The Android app itself is not built yet; this page describes what it will do and how its protocol works, so you can build against it. -- Pair it once with a code from the admin screen. -- You can revoke a phone at any time. -- Alerts older than 60 seconds or repeated are refused. +## What it will do + +A small app on the phone that receives your bank's SMS and notifications. It forwards only messages from the bank sender ids you allow, signs each with a key that never leaves the phone, and sends them to Kaasu. It keeps a short list of what it forwarded so you can see it working, and a "send test" button. + +## Pairing + +1. Kaasu shows a one-time pairing code as a QR (valid ten minutes, usable once). It contains your ingest address. +2. The phone creates an Ed25519 key pair in the Android Keystore and sends the public key with the code. +3. Kaasu stores the public key against a device id. The private key never leaves the phone. + +## Sending alerts + +Each alert is a JSON body (`source`, `sender`, `text`, `received_at`) with four headers: device id, timestamp, a 16 to 64 character nonce, and the signature over all of it. Details in [API: device ingest](/docs/reference/api/). + +- An alert whose timestamp is more than 60 seconds off is refused. +- A nonce can be used once, so a captured request cannot be replayed (the second try gets `409`). +- Every other failure is the same `401` with no detail. +- A revoked phone is refused at once. + +## Battery savers + +Phones kill background apps to save power. The app will include per-brand steps (Xiaomi, Oppo, Vivo, Samsung and others) and a foreground notification, because a phone that silently stops forwarding is the main way a shop loses confirmations. The dashboard shows **Phone offline** when it has not heard from the phone for 15 minutes. + +## Until it ships + +Use [bank email](/docs/connect/bank-email/) as a source, or build a forwarder to the protocol above. diff --git a/web/src/content/docs/docs/connect/bank-email.md b/web/src/content/docs/docs/connect/bank-email.md index 63f2365..bef7a4a 100644 --- a/web/src/content/docs/docs/connect/bank-email.md +++ b/web/src/content/docs/docs/connect/bank-email.md @@ -1,6 +1,24 @@ --- title: Bank email -description: Use bank email alerts as a second source. +description: Use bank email alerts as a second, independent source. --- -Forward bank emails to Kaasu. Each message is checked for a valid sender signature and must come from a bank domain on your allow list. Anything else is ignored. +> **Status:** the email checker is built and tested. It is not started by the server yet, and there is no setting screen for the mailbox, so it does not run in a normal install today. + +## How it works + +Kaasu reads an inbox that receives your bank's alert emails over IMAP with TLS, using an app password. For every unread message it: + +1. Checks the **DKIM signature** on the raw message. +2. Requires the signing domain to be on the bank allow list (for example `hdfcbank.net`, `icicibank.com`, `axisbank.com`, `sbi.co.in`, `kotak.com`) **and** to match the From address. +3. Reads the body, decoding base64 and quoted-printable and looking inside nested parts, with a size limit. +4. Parses the credit with the bank's parser. Unknown formats are kept as evidence and never confirm anything. +5. Marks the message read so it is not fetched again. + +A message that fails any step is logged as rejected with a reason (`no_dkim`, `bad_dkim`, `domain_not_allowed`, `from_not_aligned`) and ignored. A copy that arrives by SMS and by email is recognised as the **same payment**, which adds a second source and raises confidence. + +## Tips + +- Use a dedicated mailbox and an app password, never your main password. +- Forward only bank alerts to it. +- Email alone cannot be hurried by an attacker: a forged email fails DKIM, and an old one fails the time window. diff --git a/web/src/content/docs/docs/connect/mac-messages.md b/web/src/content/docs/docs/connect/mac-messages.md index 67ea348..72f94e5 100644 --- a/web/src/content/docs/docs/connect/mac-messages.md +++ b/web/src/content/docs/docs/connect/mac-messages.md @@ -1,6 +1,19 @@ --- title: Messages on Mac and iPhone -description: Use the Apple apps as an alert source. +description: Use an iPhone relayed to a Mac as an alert source (experimental). --- -The Apple apps can pass bank messages to Kaasu in the same signed way as the Android forwarder. Pair the device from the admin screen, then confirm it appears in the device list. +> **Status:** planned and experimental. The server side (signed ingest) is ready; the Mac agent is not built yet. + +## Idea + +An iPhone cannot let apps read its SMS. The workaround is to turn on **Text Message Forwarding** to a Mac you own. The Mac's Messages database then holds the bank SMS, and a small Kaasu agent on the Mac reads it and sends each allowed message to Kaasu. + +## What it will need + +- Full Disk Access for the agent, granted by you. +- Only messages from the bank sender ids you allow are read. +- The agent signs requests with a key held in the macOS Keychain, in exactly the same way as the [Android forwarder](/docs/connect/android-forwarder/). +- It is labelled experimental in the app, and warns you when it stops working, because it depends on how Apple stores messages. + +Prefer [bank email](/docs/connect/bank-email/) or an Android phone when you can. diff --git a/web/src/content/docs/docs/connect/supported-banks.md b/web/src/content/docs/docs/connect/supported-banks.md new file mode 100644 index 0000000..1e09116 --- /dev/null +++ b/web/src/content/docs/docs/connect/supported-banks.md @@ -0,0 +1,28 @@ +--- +title: Supported banks +description: Which bank alerts Kaasu understands, and how new ones are added. +--- + +Kaasu reads **credits** (money received) from these banks. Debits, offers and anything unfamiliar are never treated as a payment. + +| Bank | SMS sender ids | Email domain | +|---|---|---| +| HDFC Bank | `HDFCBK` | `hdfcbank.net` | +| State Bank of India | `SBIUPI`, `SBIINB`, `SBIPSG` | `sbi.co.in` | +| ICICI Bank | `ICICIB` | `icicibank.com` | +| Axis Bank | `AXISBK` | `axisbank.com` | +| Kotak Mahindra Bank | `KOTAKB` | `kotak.com` | + +Sender ids are matched with their usual operator prefix and suffix, so `VM-HDFCBK-S` counts as `HDFCBK`. A look-alike such as `HDFCBK.evil` does not match. + +## What gets read + +The amount (in paise, parsed from the digits, never as a decimal number), the 12-digit UTR, the date, a masked payer and the last digits of your account. A reference that is not exactly 12 digits is rejected, so a longer number cannot be truncated into a valid-looking one. + +## Not understood? + +If a message is not recognised, Kaasu keeps it as evidence and never confirms from it. The optional [AI helper](/docs/use/ai-features/) can propose a reading, which always goes to you for approval. + +## Add a bank + +Parsers are small and have golden test files. See [Contribute](/docs/reference/contribute/): add a pattern, a **redacted** sample message (no real names, numbers or UTRs) and the expected result. diff --git a/web/src/content/docs/docs/index.md b/web/src/content/docs/docs/index.md index 6943ced..e55af7e 100644 --- a/web/src/content/docs/docs/index.md +++ b/web/src/content/docs/docs/index.md @@ -7,10 +7,22 @@ Kaasu confirms UPI payments for small shops. Customers pay your bank directly, a ## Start here -1. [Install Kaasu](/docs/start/install/) and try it with demo data. -2. [Take your first payment](/docs/start/first-payment/). -3. [Connect a bank alert source](/docs/connect/android-forwarder/). -4. [Connect your shop](/docs/connect/woocommerce/): WooCommerce works today, [Shopify](/docs/connect/shopify/) is planned. +1. [How Kaasu works](/docs/start/how-it-works/): the flow and the rules it never breaks. +2. [Install Kaasu](/docs/start/install/) and run the first-time setup. +3. [Take your first payment](/docs/start/first-payment/). +4. [Connect an alert source](/docs/connect/android-forwarder/) and [your shop](/docs/connect/woocommerce/). + +## Everyday use + +[Dashboard](/docs/use/dashboard/), [Orders and pay links](/docs/use/orders-and-links/), [Needs your OK](/docs/use/needs-your-ok/), [Refunds](/docs/use/refunds/), [Reconciliation](/docs/use/reconciliation/), [Languages and voice](/docs/use/languages-and-voice/), [AI help](/docs/use/ai-features/), [Backups and keys](/docs/use/backup-and-keys/). + +## Reference + +[API](/docs/reference/api/), [Webhooks](/docs/reference/webhooks/), [Command line](/docs/reference/cli/), [Configuration](/docs/reference/configuration/), [Orders, states and the ledger](/docs/reference/ledger-and-states/), [Operations](/docs/reference/operations/), [Security](/docs/reference/security/), [Troubleshooting](/docs/reference/troubleshooting/), [FAQ](/docs/reference/faq/). + +## What works today + +Kaasu is early software. The core is built and tested: orders, exact amounts, the matcher, signed alerts, webhooks, the ledger, the pay and receipt pages, the dashboard and the command line. Phone and Mac apps, the email watcher's mailbox setup, backups and several screens are still being connected, and each page says so where it matters. Test with small amounts first. ## How these docs are kept diff --git a/web/src/content/docs/docs/reference/api.md b/web/src/content/docs/docs/reference/api.md index 9594d2c..b6de89d 100644 --- a/web/src/content/docs/docs/reference/api.md +++ b/web/src/content/docs/docs/reference/api.md @@ -1,11 +1,118 @@ --- title: API -description: Kaasu REST API basics, including the base path, API keys, idempotency and paise amounts. +description: "The Kaasu REST API: authentication, orders, idempotency, errors, limits, customer pages, webhooks and the device ingest API." --- -- Base path `/v1`. -- One API key per shop. -- `Idempotency-Key` header is required when creating an order. -- Money fields are integer paise, for example `49907` means ₹499.07. +Kaasu has three HTTP listeners. This page covers the three you may call from code: the **public** order API, the **customer pages**, and the **ingest** API used by bank-alert devices. The admin listener is for people and is never exposed to the internet. The machine-readable spec is `openapi.yaml` in the repository. -The full specification lives in `openapi.yaml` in the repository. +## Basics + +- Base path `/v1`, JSON in and out, `Content-Type: application/json`. +- Money is an integer number of **paise**: `49907` means ₹499.07. Floats are rejected. Currency is always `INR`. +- Send `Authorization: Bearer `. Create a key on your server with `kaasu apikey new